Compare commits

...

24 Commits

Author SHA1 Message Date
shi fc7ff3a3e0 refactor(game): 将 ApiCFBalanceTransferResponseDTO 中的 bankID可以避免在处理大额交易时可能出现的溢出问题 2025-04-24 15:31:23 +08:00
shi 7f04d31fa1 refactor(game): 将 ApiCFBalanceTransferResponseDTO 中的 bankID 2025-04-24 15:30:56 +08:00
shi 0a02e3b9f6 feat(game): 优化平台列表查询逻辑
- 在查询平台列表时添加了停用状态过滤条件- 仅缓存未停用的平台信息,提高数据准确性
2025-04-24 13:41:38 +08:00
shi da64d2304a feat(game): 优化平台列表查询逻辑
- 在查询平台列表时添加了停用状态过滤条件- 仅缓存未停用的平台信息,提高数据准确性
2025-04-23 14:41:15 +08:00
shi 58064fc479 feat(game): 优化平台列表查询逻辑
- 在查询平台列表时添加了停用状态过滤条件- 仅缓存未停用的平台信息,提高数据准确性
2025-04-23 14:29:31 +08:00
shi 75ede9c934 feat(game): 添加 PP 游戏平台支持
- 新增 PP游戏平台的 API 接口实现类
- 添加 PP 游戏平台的缓存常量和时间点
- 实现 PP游戏平台的会员创建、登录、转账等功能
- 解析 PP 游戏平台的注单记录
- 添加 PP 游戏平台的地址源和成功条件判断
2025-04-21 14:03:07 +08:00
shi 5a62a0c6a5 feat(game): 添加平台管理全部获取接口并优化登录逻辑
- 在 GamePlatformController 中添加了获取所有平台信息的接口
- 优化了 SysLoginController 中的验证码校验逻辑
- 新增了平台服务的依赖注入
- 添加了权限控制注解
2025-04-12 10:13:27 +08:00
shi 16f83851e5 feat(fc): 优化 FC 地址来源
- 在 UrlInfo 类中添加 https 和 host 字段,用于存储 HTTPS 协议和端口信息
- 修改 MyFCAddressSource 类中的 getAddress 方法,使用新的 https 和 host 字段
-通过这些改动,提高了地址信息的灵活性和可配置性
2025-04-12 09:38:51 +08:00
shi e12fd287be refactor(game): 修改游戏 ID 类型并更新相关接口
-将 ApiGameInfoResponseDTO 中的 systemGameId 字段类型从 Long 改为 String
- 在 GameMapper.xml 中添加 game_id 字段的查询
- 更新 GamesPGServiceImpl 中的代码,使用 game.getGameId() 替代 game.getId()
2025-04-11 19:43:01 +08:00
shi f097c0f8aa refactor(game): 修改游戏 ID 类型并更新相关接口
-将 ApiGameInfoResponseDTO 中的 systemGameId 字段类型从 Long 改为 String
- 在 GameMapper.xml 中添加 game_id 字段的查询
- 更新 GamesPGServiceImpl 中的代码,使用 game.getGameId() 替代 game.getId()
2025-04-11 19:15:47 +08:00
shi 82cd1456a5 refactor(game): 修改游戏 ID 类型并更新相关接口
-将 ApiGameInfoResponseDTO 中的 systemGameId 字段类型从 Long 改为 String
- 在 GameMapper.xml 中添加 game_id 字段的查询
- 更新 GamesPGServiceImpl 中的代码,使用 game.getGameId() 替代 game.getId()
2025-04-11 19:08:48 +08:00
shi 908194d767 refactor(game): 恢复 DBSports 实时记录接口时间参数使用
- 重新启用 getRealtimeRecord 接口中 startTime 和 endTime 参数
- 移除测试用的硬编码时间值
-优化代码格式和缩进
2025-04-11 18:14:42 +08:00
shi dda84a866e refactor(game): 恢复 DBSports 实时记录接口时间参数使用
- 重新启用 getRealtimeRecord 接口中 startTime 和 endTime 参数
- 移除测试用的硬编码时间值
-优化代码格式和缩进
2025-04-11 17:28:38 +08:00
shi d2ced1154d refactor(game): 恢复 DBSports 实时记录接口时间参数使用
- 重新启用 getRealtimeRecord 接口中 startTime 和 endTime 参数
- 移除测试用的硬编码时间值
-优化代码格式和缩进
2025-04-11 16:58:57 +08:00
shi 9352c50a22 Merge branch 'main-meitian' into main-pgt 2025-04-11 16:56:37 +08:00
shi 39dcd026c0 fix(game): 修复游戏余额扣除和订单回滚相关问题
- 在扣除余额时增加检查,避免重复回滚增加余额
-调整订单状态更新的定时任务执行频率,从每30分钟改为每5分钟
-优化平台交易状态查询逻辑,避免不必要的错误提示
2025-04-11 16:13:15 +08:00
shi 724d5f8f06 feat(game): 实现余额转移状态查询功能
- 新增余额转移状态查询接口和相关 DTO 类- 完善定时任务处理逻辑,增加步进状态处理
- 优化游戏兑换货币相关逻辑,增加空列表判断
- 修复美天游戏同步记录方法中的类型转换问题
- 完善平台交易服务中的异常处理
2025-04-11 15:47:42 +08:00
shi 88bdfc9c16 refactor(ff-game): 重构游戏余额转移功能
- 移除冗余的平台和货币信息查询逻辑
- 使用 GameExchangeDTO封装余额转移数据
-引入 StepProcessorFactory 处理余额转移步骤
- 实现异步执行余额转移操作
-优化错误处理和日志记录
2025-04-11 15:20:58 +08:00
shi 3236b4ab55 refactor(game): 重构游戏平台交易ID生成逻辑
- 移除 CreateOrderServiceImpl 中的 getTransactionId 方法
- 在每个游戏平台的实现类中添加 getTransactionId 方法,具体实现如下:
  - GamesAEServiceImpl
  - GamesDGServiceImpl
  - GamesFCServiceImpl
  - GamesJILIServiceImpl
  - GamesKMServiceImpl - GamesPGServiceImpl
  - GamesPGTServiceImpl
  - GamesPGXServiceImpl
  - GamesSAServiceImpl
- 更新 DBSportsServiceImpl 和 FBSportsServiceImpl 中的交易ID生成逻辑
- 重构后的交易ID生成逻辑更清晰,每个平台有自己的实现方式
2025-04-11 15:20:45 +08:00
shi 265b626b6e Merge branch 'main-meitian' into main-pgt 2025-04-11 11:03:29 +08:00
shi 537b23a420 refactor(ff-game): 重构 FB 和 SV388 平台的转账逻辑
- 移除 FBSports 和 SV388 平台的重复代码
- 优化交易 ID 生成逻辑,支持不同平台的格式
-调整 CreateOrderServiceImpl 中的平台判断逻辑
- 重构 FBSportsServiceImpl 和 SV388GamesServiceImpl 中的转账方法
2025-04-11 11:03:24 +08:00
shi 9fa259268e Merge branch 'main-meitian' into main-pgt
# Conflicts:
#	ff-base/src/main/java/com/ff/base/enums/ErrorCode.java
#	ff-game/src/main/java/com/ff/common/service/impl/TenantGameQuotaServiceImpl.java
2025-04-11 10:56:12 +08:00
shi f32794285a refactor(game): 重构游戏余额转移功能
- 新增抽象步进处理类 AbstractStepProcessor 实现通用的处理和回滚逻辑- 新增具体步进处理实现类 CreateOrderServiceImpl、DeductBalanceServiceImpl 和 AddBalanceServiceImpl
-优化 ApiGameController 中的余额转移接口,采用异步处理方式- 重构 GameExchangeMoneyService 中的插入逻辑,支持更新
- 新增 GameExchangeDTO 用于游戏兑换货币的相关操作
- 更新相关枚举类和 DTO 类以支持新的业务逻辑
2025-04-11 10:52:17 +08:00
shi 6e1afc61b0 refactor(game): 重构游戏列表和金额转移相关逻辑
- 更新了 PGX、SA 和 XK游戏平台的游戏列表获取逻辑- 优化了游戏数据插入和更新的处理流程
- 改进了金额转移的处理方式,增加了状态和步骤记录
-调整了投注记录获取的接口调用方式
- 优化了代码结构,移除了不必要的注释和冗余代码
2025-04-09 09:18:47 +08:00
116 changed files with 4028 additions and 642 deletions

View File

@ -137,8 +137,14 @@ public class CacheConstants {
public static final String SV388_TIME_FROM= "sv388:time:from"; public static final String SV388_TIME_FROM= "sv388:time:from";
public static final String SV388_GAMES = "sv388_games:"; public static final String SV388_GAMES = "sv388_games:";
/**
* pp
*/
public static final String PP_GAMES= "pp_games:";
/**
* pp
*/
public static final String PP_TIME_POINT = "pp:time:point:";
} }

View File

@ -37,6 +37,7 @@ public enum ErrorCode {
Transfer_Not_Exist(1021, "转帐操作不存在"), Transfer_Not_Exist(1021, "转帐操作不存在"),
Get_Url_Failure(1022, "获取URL失败"), Get_Url_Failure(1022, "获取URL失败"),
Miss_Config(1023, "缺少配置"), Miss_Config(1023, "缺少配置"),
DUPLICATE_ORDER_ID (1024, "重复的订单id"),
; ;
// 获取错误码 // 获取错误码

View File

@ -15,10 +15,20 @@ import lombok.Getter;
@AllArgsConstructor @AllArgsConstructor
public enum GameExchangeStep { public enum GameExchangeStep {
CREATE_ORDER(1, "创建订单"), CREATE_ORDER(1, "创建订单"),
PLATFORM_TRANSACTION(2, "平台交易成功"), DEDUCT_BALANCE(2, "转入提前扣租户余额"),
PLATFORM_TRANSACTION_CONFIRM(3, "平台交易状态确认"), PLATFORM_TRANSACTION(3, "平台交易成功"),
TENANT_QUOTA_DEDUCTED(4, "租户额度扣减成功"); TENANT_QUOTA_DEDUCTED(4, "转出租户额度增加成功");
private final int code; private final Integer code;
private final String description; private final String description;
// 根据 code 获取对应的枚举
public static GameExchangeStep getByCode(int code) {
for (GameExchangeStep step : GameExchangeStep.values()) {
if (step.getCode() == code) {
return step;
}
}
return null;
}
} }

View File

@ -1,5 +1,7 @@
package com.ff.base.enums; package com.ff.base.enums;
import com.ff.base.exception.base.ApiException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -17,6 +19,7 @@ public enum GamePlatforms {
PGT("PGT", "PGT"), PGT("PGT", "PGT"),
FBSports("FBSports", "FB体育"), FBSports("FBSports", "FB体育"),
SV388("SV388", "SV388真人"), SV388("SV388", "SV388真人"),
PP("PP", "PP"),
DBSports("DBSports", "DB体育"); DBSports("DBSports", "DB体育");
private final String code; private final String code;
@ -27,6 +30,20 @@ public enum GamePlatforms {
this.info = info; this.info = info;
} }
/**
*
*
* @param code
* @return {@link GamePlatforms }
*/
public static GamePlatforms getByCode(String code) {
for (GamePlatforms platform : GamePlatforms.values()) {
if (platform.getCode().equals(code)) {
return platform;
}
}
throw new ApiException(ErrorCode.PLATFORM_NOT_EXIST.getCode());
}
public static List<String> getCodes() { public static List<String> getCodes() {
List<String> result = new ArrayList<>(); List<String> result = new ArrayList<>();

View File

@ -0,0 +1,64 @@
package com.ff.base.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Optional;
import java.util.stream.Stream;
/**
* xkgame
*
* @author shi
* @date 2024/11/13
*/
@Getter
@AllArgsConstructor
public enum PPGameType {
ELECTRONIC("vs", 1,"电子"),
// CARD_GAME("rl",2, "轮盘"),
// VIDEO("vp",6, "视频扑克"),
// SCRATCH_CARD("sc",7, "刮刮乐"),
// BLACK_JACK("bj",2, "21点"),
// CLASSIC_SLOTS("cs",1, "电子"),
// BACCARAT_NEW("bn",2, "百家乐新"),
// BACCARAT("bc",2, "百家乐"),
// LIVE_GAMES("lg",6, "现场游戏"),
;
private final String code;
private final Integer systemCode;
private final String info;
/**
*
*
* @param code
* @return {@link String }
*/
public static Integer findSystemByCode(String code) {
Optional<Integer> system = Stream.of(PPGameType.values())
.filter(gameType -> gameType.getCode().equals(code))
.map(PPGameType::getSystemCode)
.findFirst();
return system.orElse(null);
}
/**
*
*
* @param code
* @return {@link String }
*/
public static String findInfoByCode(String code) {
Optional<String> system = Stream.of(PPGameType.values())
.filter(gameType -> gameType.getCode().equals(code))
.map(PPGameType::getInfo)
.findFirst();
return system.orElse(null);
}
}

View File

@ -18,7 +18,7 @@ public enum PlatformType {
GAME_HALL(3, "游戏大厅"), GAME_HALL(3, "游戏大厅"),
FISHING(4, "捕鱼"), FISHING(4, "捕鱼"),
BETTING_MACHINE(5, "押分机 (含宾果)"), BETTING_MACHINE(5, "押分机 (含宾果)"),
VIDEO(6, "视讯"), VIDEO(6, "真人视讯"),
LOTTERY(7, "彩票"), LOTTERY(7, "彩票"),
SPORTS(8, "体育"), SPORTS(8, "体育"),
HUNTING(9, "捕猎"), HUNTING(9, "捕猎"),

View File

@ -0,0 +1,25 @@
package com.ff.base.enums;
import com.alibaba.druid.filter.AutoLoad;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
*
*
* @author shi
* @date 2025/04/09
*/
@AllArgsConstructor
@Getter
public enum TimeOutType {
GAME_EXCHANGE_MONEY("gameExchangeMoney", "游戏余额转移");
/**
*
*/
private final String code;
/**
*
*/
private final String info;
}

View File

@ -0,0 +1,21 @@
package com.ff.base.enums;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
/**
*
*
* @author shi
* @date 2025/04/09
*/
@Getter
@AllArgsConstructor
public enum TriggerType {
MANUAL(1, "用户调用手动触发"),
TIMER(2, "定时器触发");
private final int code;
private final String description;
}

View File

@ -2,11 +2,12 @@ package com.ff.base.manager;
import com.ff.base.utils.Threads; import com.ff.base.utils.Threads;
import com.ff.base.utils.spring.SpringUtils; import com.ff.base.utils.spring.SpringUtils;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.ArrayList;
import java.util.List;
import java.util.TimerTask; import java.util.TimerTask;
import java.util.concurrent.Callable; import java.util.concurrent.*;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/** /**
* *
@ -24,10 +25,33 @@ public class AsyncManager {
*/ */
private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService"); private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");
/**
* 线
*/
private List<ExecutorService> orderedExecutor = new ArrayList<>();
/**
* 线
*/
public static final int MAX_THREAD_COUNT = 16;
/**
* 线
*/
private ThreadPoolTaskExecutor taskExecutor;
/** /**
* *
*/ */
private AsyncManager() { private AsyncManager() {
for (int i = 0; i < MAX_THREAD_COUNT; i++) {
orderedExecutor.add(Executors.newSingleThreadExecutor());
}
executor = SpringUtils.getBean("scheduledExecutorService");
taskExecutor = SpringUtils.getBean("threadPoolTaskExecutor");
} }
private static AsyncManager me = new AsyncManager(); private static AsyncManager me = new AsyncManager();
@ -36,6 +60,22 @@ public class AsyncManager {
return me; return me;
} }
public void executeOrdered(String key, Runnable task) {
if (null == key || key.isEmpty()) {
taskExecutor.execute(task);
return;
}
int hash = key.hashCode();
int index = Math.abs(hash % MAX_THREAD_COUNT);
orderedExecutor.get(index).execute(task);
}
/** /**
* *
* *

View File

@ -38,11 +38,10 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
public static String DAY_END_TIME = "23:59:59"; public static String DAY_END_TIME = "23:59:59";
public static final String ISO_8601_FORMAT= "yyyy-MM-dd'T'HH:mm:ss"; public static final String ISO_8601_FORMAT = "yyyy-MM-dd'T'HH:mm:ss";
public static final String ISO_8601_FORMAT_Z = "yyyy-MM-dd'T'HH:mm:ss'Z'";
public static final String ISO_8601_FORMAT_Z= "yyyy-MM-dd'T'HH:mm:ss'Z'";
/** /**
@ -213,8 +212,8 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
* *
* *
* @param timestamp * @param timestamp
* @param format yyyy-MM-dd'T'HH:mm:ssXXX * @param format yyyy-MM-dd'T'HH:mm:ssXXX
* @param timeZone GMT+8UTC * @param timeZone GMT+8UTC
* @return * @return
*/ */
public static String convertTimestampToFormattedDate(long timestamp, String format, String timeZone) { public static String convertTimestampToFormattedDate(long timestamp, String format, String timeZone) {
@ -251,7 +250,6 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
} }
/** /**
* LocalDate ==> Date * LocalDate ==> Date
*/ */
@ -943,4 +941,57 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
public static boolean isBetween(Long value, Long minValue, Long maxValue) { public static boolean isBetween(Long value, Long minValue, Long maxValue) {
return value >= minValue && value <= maxValue; return value >= minValue && value <= maxValue;
} }
/**
*
*
* @param dateString "yyyy-MM-dd'T'HH:mm:ss.SSS"
* @param timezone UTCAsia/Shanghai
* @return
* @throws Exception
*/
public static long convertToMillisWithTimezone(String dateString, String timezone) {
try {
// 设置日期格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
// 设置解析时使用的时区
sdf.setTimeZone(TimeZone.getTimeZone(timezone));
// 解析日期字符串为 Date 对象
Date date = sdf.parse(dateString);
// 获取项目默认时区
TimeZone defaultTimeZone = TimeZone.getDefault();
// 使用默认时区的 Calendar 计算
Calendar calendar = Calendar.getInstance(defaultTimeZone);
calendar.setTime(date);
// 返回该时区对应的毫秒时间戳
return calendar.getTimeInMillis();
} catch (Exception e) {
return 0;
}
}
/**
* (UTC)
*
* @param dateStr
* @param pattern ("yyyy-MM-dd HH:mm:ss")
* @return
* @throws ParseException
*/
public static long toTimestamp(String dateStr, String pattern) {
try {
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
return sdf.parse(dateStr).getTime();
} catch (Exception e) {
return 0;
}
}
} }

View File

@ -1,6 +1,7 @@
package com.ff.api.controller; package com.ff.api.controller;
import cn.hutool.core.util.IdUtil;
import com.ff.annotation.CheckHeader; import com.ff.annotation.CheckHeader;
import com.ff.api.request.*; import com.ff.api.request.*;
import com.ff.api.response.*; import com.ff.api.response.*;
@ -8,9 +9,9 @@ import com.ff.base.constant.Constants;
import com.ff.base.core.controller.BaseController; import com.ff.base.core.controller.BaseController;
import com.ff.base.core.domain.AjaxResult; import com.ff.base.core.domain.AjaxResult;
import com.ff.base.core.page.TableDataInfo; import com.ff.base.core.page.TableDataInfo;
import com.ff.base.enums.ErrorCode; import com.ff.base.enums.*;
import com.ff.base.enums.TransferType;
import com.ff.base.exception.base.ApiException; import com.ff.base.exception.base.ApiException;
import com.ff.base.manager.AsyncManager;
import com.ff.base.system.domain.TenantSecretKey; import com.ff.base.system.domain.TenantSecretKey;
import com.ff.base.utils.StringUtils; import com.ff.base.utils.StringUtils;
import com.ff.base.utils.bean.BeanUtils; import com.ff.base.utils.bean.BeanUtils;
@ -19,6 +20,8 @@ import com.ff.common.service.ITenantGameQuotaFlowService;
import com.ff.common.service.ITenantGameQuotaService; import com.ff.common.service.ITenantGameQuotaService;
import com.ff.config.KeyConfig; import com.ff.config.KeyConfig;
import com.ff.game.api.IGamesService; import com.ff.game.api.IGamesService;
import com.ff.game.api.exchange.StepProcessorFactory;
import com.ff.game.api.exchange.dto.GameExchangeDTO;
import com.ff.game.api.request.*; import com.ff.game.api.request.*;
import com.ff.game.domain.*; import com.ff.game.domain.*;
import com.ff.game.dto.GameBettingDetailsDTO; import com.ff.game.dto.GameBettingDetailsDTO;
@ -30,8 +33,10 @@ import lombok.Data;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -39,12 +44,14 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CompletableFuture;
/** /**
* api * api
@ -91,6 +98,10 @@ public class ApiGameController extends BaseController {
@Resource @Resource
private IPlatformService platformService; private IPlatformService platformService;
@Resource
private StepProcessorFactory stepProcessorFactory;
/** /**
* *
* *
@ -148,6 +159,8 @@ public class ApiGameController extends BaseController {
ApiException.notNull(targetLang, ErrorCode.LANG_NOT_EXIST.getCode()); ApiException.notNull(targetLang, ErrorCode.LANG_NOT_EXIST.getCode());
ApiException.isTrue(game.getStopStatus(), ErrorCode.GAME_NOT_EXIST.getCode());
Member member = memberService.selectMemberByAccount(loginRequest.getAccount(), loginRequest.getCurrencyCode(), platform.getPlatformCode()); Member member = memberService.selectMemberByAccount(loginRequest.getAccount(), loginRequest.getCurrencyCode(), platform.getPlatformCode());
ApiException.notNull(member, ErrorCode.ACCOUNT_NOT_EXIST.getCode()); ApiException.notNull(member, ErrorCode.ACCOUNT_NOT_EXIST.getCode());
@ -182,8 +195,7 @@ public class ApiGameController extends BaseController {
* @return {@link AjaxResult } * @return {@link AjaxResult }
*/ */
@PostMapping("/exchange/balance") @PostMapping("/exchange/balance")
@Transactional public DeferredResult<AjaxResult> exchangeBalance(@Validated @RequestBody GameExchangeBalanceRequest gameExchangeBalanceRequest) {
public AjaxResult exchangeBalance(@Validated @RequestBody GameExchangeBalanceRequest gameExchangeBalanceRequest) {
IGamesService iGamesService = gamesService.get(gameExchangeBalanceRequest.getPlatformCode() + Constants.SERVICE); IGamesService iGamesService = gamesService.get(gameExchangeBalanceRequest.getPlatformCode() + Constants.SERVICE);
ApiException.notNull(iGamesService, ErrorCode.PLATFORM_NOT_EXIST.getCode()); ApiException.notNull(iGamesService, ErrorCode.PLATFORM_NOT_EXIST.getCode());
@ -207,51 +219,77 @@ public class ApiGameController extends BaseController {
} }
} }
ApiException.notNull(keyInfo, ErrorCode.CURRENCY_NOT_EXIST.getCode()); ApiException.notNull(keyInfo, ErrorCode.CURRENCY_NOT_EXIST.getCode());
BigDecimal quota = BigDecimal.ZERO;
//如果是扣钱提前扣
if (TransferType.GAMES.getCode().equals(gameExchangeBalanceRequest.getTransferType())) {
quota = tenantGameQuotaService.gameBalanceExchange(GameBalanceExchange.builder()
.platformCode(gameExchangeBalanceRequest.getPlatformCode())
.sourceId(gameExchangeBalanceRequest.getOrderId())
.currencyCode(gameExchangeBalanceRequest.getCurrencyCode())
.currency(targetCurrency)
.transferType(gameExchangeBalanceRequest.getTransferType())
.amount(gameExchangeBalanceRequest.getAmount())
.account(gameExchangeBalanceRequest.getAccount())
.tenantKey(tenantSecretKey.getTenantKey())
.systemCurrency(gameExchangeBalanceRequest.getCurrencyCode())
.agentId(keyInfo.getCode())
.agentKey(keyInfo.getKey())
.build());
}
// 获取用户信息 // 获取用户信息
Member member = memberService.selectMemberByAccount(gameExchangeBalanceRequest.getAccount(), gameExchangeBalanceRequest.getCurrencyCode(), gameExchangeBalanceRequest.getPlatformCode()); Member member = memberService.selectMemberByAccount(gameExchangeBalanceRequest.getAccount(), gameExchangeBalanceRequest.getCurrencyCode(), gameExchangeBalanceRequest.getPlatformCode());
ApiException.notNull(member, ErrorCode.ACCOUNT_NOT_EXIST.getCode()); ApiException.notNull(member, ErrorCode.ACCOUNT_NOT_EXIST.getCode());
List<GameExchangeMoney> gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList(
GameExchangeMoney.builder()
.tenantKey(tenantSecretKey.getTenantKey())
.orderId(gameExchangeBalanceRequest.getOrderId())
.build()
);
//操作第三方额度接口 ApiException.isTrue(CollectionUtils.isEmpty(gameExchangeMonies), ErrorCode.DUPLICATE_ORDER_ID.getCode());
ExchangeTransferMoneyRequestDTO exchangeTransferMoneyRequestDTO = ExchangeTransferMoneyRequestDTO.builder()
.agentId(keyInfo.getCode())
.agentKey(keyInfo.getKey()) Long gameExchangeMoneyId = IdUtil.getSnowflakeNextId();
.orderId(gameExchangeBalanceRequest.getOrderId()) GameExchangeDTO exchangeMoney = GameExchangeDTO.builder()
.account(member.getGameAccount()) .id(gameExchangeMoneyId)
.currency(targetCurrency)
.tenantKey(tenantSecretKey.getTenantKey()) .tenantKey(tenantSecretKey.getTenantKey())
.quota(quota) .memberId(member.getId())
.amount(gameExchangeBalanceRequest.getAmount()) .gameAccount(member.getGameAccount())
.transferType(gameExchangeBalanceRequest.getTransferType()) .memberAccount(member.getMemberAccount())
.vendor(platform) .exchangeType(gameExchangeBalanceRequest.getTransferType())
.keyInfo(keyInfo) .currencyCode(gameExchangeBalanceRequest.getCurrencyCode())
.systemCurrency(gameExchangeBalanceRequest.getCurrencyCode()) .orderId(gameExchangeBalanceRequest.getOrderId())
.balance(gameExchangeBalanceRequest.getAmount())
.triggerType(TriggerType.MANUAL.getCode())
.platformCode(gameExchangeBalanceRequest.getPlatformCode()).build();
.build();
Long exchangeTransferId = iGamesService.exchangeTransferByAgentId(exchangeTransferMoneyRequestDTO); //转出设置转出金额为0
GameExchangeMoney gameExchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(exchangeTransferId); if (TransferType.ALL.getCode().equals(gameExchangeBalanceRequest.getTransferType())){
GameExchangeBalanceResponse gameExchangeBalanceResponse = new GameExchangeBalanceResponse(); exchangeMoney.setBalance(BigDecimal.ZERO);
BeanUtils.copyProperties(gameExchangeMoney, gameExchangeBalanceResponse); }
return AjaxResult.success(gameExchangeBalanceResponse);
ExtInfo extInfo = platform.getExtInfo();
Long timeout = 5000L;
if (extInfo != null) {
timeout = extInfo.getTimeout(TimeOutType.GAME_EXCHANGE_MONEY.getCode());
}
DeferredResult<AjaxResult> output = new DeferredResult<>(timeout);
AsyncManager.me().executeOrdered(
exchangeMoney.getOrderId(),
() -> {
try {
stepProcessorFactory.getStepProcessor(GameExchangeStep.CREATE_ORDER).process(exchangeMoney);
GameExchangeMoney gameExchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(gameExchangeMoneyId);
GameExchangeBalanceResponse gameExchangeBalanceResponse = new GameExchangeBalanceResponse();
BeanUtils.copyProperties(gameExchangeMoney, gameExchangeBalanceResponse);
output.setResult(AjaxResult.success(gameExchangeBalanceResponse));
} catch (Exception e) {
log.error("ApiGameController [exchangeBalance] 余额转移失败 gameExchangeMoneyId {}", gameExchangeMoneyId,e);
stepProcessorFactory.getStepProcessor(GameExchangeStep.getByCode(exchangeMoney.getStep())).rollBack(exchangeMoney);
output.setErrorResult(AjaxResult.error(ErrorCode.BALANCE_TRANSFER_FAILED.getCode(), ErrorCode.BALANCE_TRANSFER_FAILED.getMessage()));
}
}
);
// 超时时间处理逻辑
output.onTimeout(() -> {
GameExchangeMoney gameExchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(gameExchangeMoneyId);
GameExchangeBalanceResponse gameExchangeBalanceResponse = new GameExchangeBalanceResponse();
BeanUtils.copyProperties(gameExchangeMoney, gameExchangeBalanceResponse);
output.setErrorResult(AjaxResult.success(gameExchangeBalanceResponse));
});
return output;
} }
@ -291,11 +329,6 @@ public class ApiGameController extends BaseController {
ApiException.notNull(iGamesService, ErrorCode.PLATFORM_NOT_EXIST.getCode()); ApiException.notNull(iGamesService, ErrorCode.PLATFORM_NOT_EXIST.getCode());
// TenantSecretKey tenantSecretKey = keyConfig.get();
// GameSecretKeyCurrencyDTO gameSecretKey = gameSecretKeyCurrencyService.findByGameSecretKeyCurrencyDTO(GameSecretKeyCurrencyDTO.builder()
// .platformCode(gameCreateFreeSpinRequest.getPlatformCode())
// .systemCurrency(gameCreateFreeSpinRequest.getCurrencyCode()).build());
// ApiException.notNull(gameSecretKey, ErrorCode.CURRENCY_NOT_EXIST.getCode());
Platform platform = platformService.get(gameCreateFreeSpinRequest.getPlatformCode()); Platform platform = platformService.get(gameCreateFreeSpinRequest.getPlatformCode());
ApiException.notNull(platform, ErrorCode.PLATFORM_NOT_EXIST.getCode()); ApiException.notNull(platform, ErrorCode.PLATFORM_NOT_EXIST.getCode());

View File

@ -38,7 +38,7 @@ public class GameBettingDetailsResponse implements Serializable
/** 游戏id */ /** 游戏id */
private Long gameId; private String gameId;
/** 游戏类型 ff_game_type 字典 */ /** 游戏类型 ff_game_type 字典 */
private Integer gameType; private Integer gameType;

View File

@ -67,4 +67,9 @@ public class GameBalanceExchange extends GamesBaseRequestDTO implements Serializ
*/ */
private String sourceId; private String sourceId;
/**
*
*/
private Boolean isAll;
} }

View File

@ -1,40 +1,42 @@
package com.ff.common.service.impl; package com.ff.common.service.impl;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.NumberUtil;
import com.ff.base.constant.Constants; import com.ff.base.constant.Constants;
import com.ff.base.enums.*; import com.ff.base.enums.*;
import com.ff.base.exception.base.ApiException; import com.ff.base.exception.base.ApiException;
import com.ff.base.system.domain.TenantPlatform; import com.ff.base.system.domain.TenantPlatform;
import com.ff.base.system.domain.TenantSecretKey;
import com.ff.base.system.service.ITenantPlatformService; import com.ff.base.system.service.ITenantPlatformService;
import com.ff.base.system.service.ITenantSecretKeyService;
import com.ff.base.utils.DateUtils; import com.ff.base.utils.DateUtils;
import com.ff.base.utils.QuotaUtils; import com.ff.base.utils.QuotaUtils;
import com.ff.common.domain.TenantGameQuota; import com.ff.base.utils.StringUtils;
import com.ff.common.domain.TenantGameQuotaFlow; import com.ff.common.domain.TenantGameQuotaFlow;
import com.ff.common.domain.TenantQuotaExchange; import com.ff.common.domain.TenantQuotaExchange;
import com.ff.base.system.domain.TenantSecretKey;
import com.ff.common.dto.BalanceChangesDTO; import com.ff.common.dto.BalanceChangesDTO;
import com.ff.common.dto.BalanceRealChangesDTO; import com.ff.common.dto.BalanceRealChangesDTO;
import com.ff.common.dto.GameBalanceExchange; import com.ff.common.dto.GameBalanceExchange;
import com.ff.common.mapper.TenantGameQuotaMapper;
import com.ff.common.service.ITenantGameQuotaFlowService; import com.ff.common.service.ITenantGameQuotaFlowService;
import com.ff.common.service.ITenantGameQuotaService;
import com.ff.common.service.ITenantQuotaExchangeService; import com.ff.common.service.ITenantQuotaExchangeService;
import com.ff.base.system.service.ITenantSecretKeyService;
import com.ff.game.api.IGamesService; import com.ff.game.api.IGamesService;
import com.ff.game.api.request.MemberInfoRequestDTO; import com.ff.game.api.request.MemberInfoRequestDTO;
import com.ff.member.domain.Member; import com.ff.member.domain.Member;
import com.ff.member.service.IMemberService; import com.ff.member.service.IMemberService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.ff.common.mapper.TenantGameQuotaMapper;
import com.ff.common.domain.TenantGameQuota;
import com.ff.common.service.ITenantGameQuotaService;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;
/** /**
* Service * Service
@ -150,7 +152,7 @@ public class TenantGameQuotaServiceImpl implements ITenantGameQuotaService {
BigDecimal balance = balanceChangesDTO.getBalance(); BigDecimal balance = balanceChangesDTO.getBalance();
//如果有汇率 则需要计算真实扣除额度 //如果有汇率 则需要计算真实扣除额度
if (!ObjectUtils.isEmpty(balanceChangesDTO.getActualBalance())) { if (!ObjectUtils.isEmpty(balanceChangesDTO.getActualBalance())) {
balance = NumberUtil.div(balance, balanceChangesDTO.getActualBalance(), 2, RoundingMode.FLOOR); balance = NumberUtil.div(balance, balanceChangesDTO.getActualBalance(), 5, RoundingMode.FLOOR);
} }
if (BigDecimal.ZERO.compareTo(balance) >= 0) { if (BigDecimal.ZERO.compareTo(balance) >= 0) {
@ -220,7 +222,7 @@ public class TenantGameQuotaServiceImpl implements ITenantGameQuotaService {
BigDecimal balance = balanceRealChangesDTO.getBalance(); BigDecimal balance = balanceRealChangesDTO.getBalance();
//如果有汇率 则需要计算真实扣除额度 //如果有汇率 则需要计算真实扣除额度
if (!ObjectUtils.isEmpty(balanceRealChangesDTO.getActualBalance())) { if (!ObjectUtils.isEmpty(balanceRealChangesDTO.getActualBalance())) {
balance = NumberUtil.div(balance, balanceRealChangesDTO.getActualBalance(), 2, RoundingMode.FLOOR); balance = NumberUtil.div(balance, balanceRealChangesDTO.getActualBalance(), 5, RoundingMode.FLOOR);
} }
if (BigDecimal.ZERO.compareTo(balance) >= 0) { if (BigDecimal.ZERO.compareTo(balance) >= 0) {
@ -312,19 +314,21 @@ public class TenantGameQuotaServiceImpl implements ITenantGameQuotaService {
// 如果是出账操作 // 如果是出账操作
if (isOut) { if (isOut) {
// 获取第三方钱包余额 if (ObjectUtils.isEmpty(gameBalanceExchange.getIsAll())||gameBalanceExchange.getIsAll()){
MemberInfoRequestDTO gamesBaseRequestDTO = MemberInfoRequestDTO.builder() // 获取第三方钱包余额
.accounts(member.getGameAccount()) MemberInfoRequestDTO gamesBaseRequestDTO = MemberInfoRequestDTO.builder()
.agentId(gameBalanceExchange.getAgentId()) .accounts(member.getGameAccount())
.currency(gameBalanceExchange.getCurrency()) .agentId(gameBalanceExchange.getAgentId())
.agentKey(gameBalanceExchange.getAgentKey()) .currency(gameBalanceExchange.getCurrency())
.build(); .agentKey(gameBalanceExchange.getAgentKey())
balanceRequestAmount = iGamesService.getMemberInfo(gamesBaseRequestDTO).getBalance(); .build();
balanceRequestAmount = iGamesService.getMemberInfo(gamesBaseRequestDTO).getBalance();
if (balanceRequestAmount.compareTo(BigDecimal.ZERO) <= 0) { if (balanceRequestAmount.compareTo(BigDecimal.ZERO) <= 0) {
throw new ApiException(ErrorCode.INSUFFICIENT_PLAYER_BALANCE.getCode()); throw new ApiException(ErrorCode.INSUFFICIENT_PLAYER_BALANCE.getCode());
}
} }
balanceRequestAmount = NumberUtil.add(balanceRequestAmount, NumberUtil.mul(balanceRequestAmount, NumberUtil.div(tenantPlatform.getUseCost(), Constants.HUNDRED))); balanceRequestAmount = NumberUtil.add(balanceRequestAmount, NumberUtil.mul(balanceRequestAmount, NumberUtil.div(tenantPlatform.getUseCost(), Constants.HUNDRED)));
// 计算累计转入和转出金额 // 计算累计转入和转出金额

View File

@ -52,6 +52,14 @@ public interface IGamesService {
*/ */
String getGameList(GamesBaseRequestDTO gamesBaseRequestDTO); String getGameList(GamesBaseRequestDTO gamesBaseRequestDTO);
/**
* id
*
* @param transactionIdRequestDTO iddto
* @return {@link String }
*/
String getTransactionId(TransactionIdRequestDTO transactionIdRequestDTO);
/** /**
* id * id

View File

@ -205,9 +205,9 @@ public class GamesAEServiceImpl implements IGamesService {
if (ObjectUtils.isEmpty(game)) { if (ObjectUtils.isEmpty(game)) {
game = new Game(); game = new Game();
game.setId(GAME_ID); game.setId(GAME_ID);
game.setSortNo(gameService.selectMaxSortNo(PlatformType.GAME_HALL.getCode(), GamePlatforms.AE.getCode()) + 1); game.setSortNo(gameService.selectMaxSortNo(PlatformType.VIDEO.getCode(), GamePlatforms.AE.getCode()) + 1);
game.setPlatformCode(platform.getPlatformCode()); game.setPlatformCode(platform.getPlatformCode());
game.setPlatformType(PlatformType.GAME_HALL.getCode()); game.setPlatformType(PlatformType.VIDEO.getCode());
game.setGameCode("1"); game.setGameCode("1");
game.setGameSourceType(String.valueOf(1)); game.setGameSourceType(String.valueOf(1));
game.setGameName("AE大厅"); game.setGameName("AE大厅");
@ -218,10 +218,27 @@ public class GamesAEServiceImpl implements IGamesService {
game.setNameInfo(Collections.singletonList(nameInfo)); game.setNameInfo(Collections.singletonList(nameInfo));
game.setGameId(StringUtils.addSuffix(GamePlatforms.AE.getCode(), 1)); game.setGameId(StringUtils.addSuffix(GamePlatforms.AE.getCode(), 1));
gameService.insertGame(game); gameService.insertGame(game);
}else {
NameInfo nameInfo = new NameInfo();
nameInfo.setLang("zh-CN");
nameInfo.setName("AE大厅");
game.setNameInfo(Collections.singletonList(nameInfo));
gameService.updateGame(game);
} }
return CacheConstants.AE_GAMES; return CacheConstants.AE_GAMES;
} }
/**
* id
*
* @param transactionIdRequestDTO iddto
* @return {@link String }
*/
@Override
public String getTransactionId(TransactionIdRequestDTO transactionIdRequestDTO) {
return GamePlatforms.AE.getCode() + IdUtils.simpleUUID();
}
/** /**
* id * id
* *
@ -234,34 +251,8 @@ public class GamesAEServiceImpl implements IGamesService {
log.info("GamesAEServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO); log.info("GamesAEServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO);
Member member = memberService.selectMemberByGameAccount(exchangeTransferMoneyRequestDTO.getAccount()); GameExchangeMoney exchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(exchangeTransferMoneyRequestDTO.getGameExchangeId());
String transactionId = GamePlatforms.AE.getCode() + IdUtils.simpleUUID();
List<GameExchangeMoney> gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList(
GameExchangeMoney.builder()
.tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey())
.orderId(exchangeTransferMoneyRequestDTO.getOrderId())
.build()
);
Assert.isTrue(CollectionUtils.isEmpty(gameExchangeMonies), "订单号重复");
//获取下一个自增id
GameExchangeMoney exchangeMoney = GameExchangeMoney
.builder()
.tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey())
.orderId(exchangeTransferMoneyRequestDTO.getOrderId())
.quota(exchangeTransferMoneyRequestDTO.getQuota())
.balance(exchangeTransferMoneyRequestDTO.getAmount())
.exchangeType(exchangeTransferMoneyRequestDTO.getTransferType())
.currencyCode(exchangeTransferMoneyRequestDTO.getSystemCurrency())
.memberId(member.getId())
.transactionId(transactionId)
.platformCode(GamePlatforms.AE.getInfo())
.build();
exchangeMoney.setCreateBy(Constants.SYSTEM);
exchangeMoney.setStatus(StatusType.IN_PROGRESS.getValue());
exchangeMoney.setStep(GameExchangeStep.CREATE_ORDER.getCode());
exchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode());
gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney);
Map<String, Object> params = this.getKey(exchangeTransferMoneyRequestDTO); Map<String, Object> params = this.getKey(exchangeTransferMoneyRequestDTO);
@ -270,13 +261,13 @@ public class GamesAEServiceImpl implements IGamesService {
if (TransferType.GAMES.getCode().equals(exchangeTransferMoneyRequestDTO.getTransferType())) { if (TransferType.GAMES.getCode().equals(exchangeTransferMoneyRequestDTO.getTransferType())) {
params.put("userId", exchangeTransferMoneyRequestDTO.getAccount()); params.put("userId", exchangeTransferMoneyRequestDTO.getAccount());
params.put("txCode", transactionId); params.put("txCode", exchangeTransferMoneyRequestDTO.getTransactionId());
params.put("transferAmount", exchangeTransferMoneyRequestDTO.getAmount()); params.put("transferAmount", exchangeTransferMoneyRequestDTO.getAmount());
deposit = AEClient.deposit(params); deposit = AEClient.deposit(params);
} else { } else {
params.put("userId", exchangeTransferMoneyRequestDTO.getAccount()); params.put("userId", exchangeTransferMoneyRequestDTO.getAccount());
params.put("txCode", transactionId); params.put("txCode", exchangeTransferMoneyRequestDTO.getTransactionId());
params.put("withdrawType", 1); params.put("withdrawType", 1);
deposit = AEClient.withdraw(params); deposit = AEClient.withdraw(params);
} }

View File

@ -1,4 +1,4 @@
package com.ff.sports.db.address; package com.ff.game.api.db.address;
import com.dtflys.forest.callback.AddressSource; import com.dtflys.forest.callback.AddressSource;
import com.dtflys.forest.http.ForestAddress; import com.dtflys.forest.http.ForestAddress;

View File

@ -1,8 +1,8 @@
package com.ff.sports.db.client; package com.ff.game.api.db.client;
import com.dtflys.forest.annotation.*; import com.dtflys.forest.annotation.*;
import com.ff.sports.db.address.DBSportsAddress; import com.ff.game.api.db.address.DBSportsAddress;
import com.ff.sports.db.dto.*; import com.ff.game.api.db.dto.*;
/** /**
* @author cengy * @author cengy

View File

@ -1,4 +1,4 @@
package com.ff.sports.db.dto; package com.ff.game.api.db.dto;
import com.ff.base.utils.sign.Md5Utils; import com.ff.base.utils.sign.Md5Utils;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.db.dto; package com.ff.game.api.db.dto;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.fb.dto; package com.ff.game.api.db.dto;
/** /**
* @author cengy * @author cengy

View File

@ -1,4 +1,4 @@
package com.ff.sports.db.dto; package com.ff.game.api.db.dto;
import com.ff.base.utils.sign.Md5Utils; import com.ff.base.utils.sign.Md5Utils;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.db.dto; package com.ff.game.api.db.dto;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.db.dto; package com.ff.game.api.db.dto;
import com.ff.base.utils.sign.Md5Utils; import com.ff.base.utils.sign.Md5Utils;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.db.dto; package com.ff.game.api.db.dto;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.db.dto; package com.ff.game.api.db.dto;
import com.ff.base.utils.sign.Md5Utils; import com.ff.base.utils.sign.Md5Utils;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.db.dto; package com.ff.game.api.db.dto;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.db.dto; package com.ff.game.api.db.dto;
import com.ff.base.utils.sign.Md5Utils; import com.ff.base.utils.sign.Md5Utils;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.db.dto; package com.ff.game.api.db.dto;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.db.dto; package com.ff.game.api.db.dto;
import com.ff.base.utils.sign.Md5Utils; import com.ff.base.utils.sign.Md5Utils;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.db.dto; package com.ff.game.api.db.dto;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.db.dto; package com.ff.game.api.db.dto;
import com.ff.base.utils.sign.Md5Utils; import com.ff.base.utils.sign.Md5Utils;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.db.dto; package com.ff.game.api.db.dto;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.db.impl; package com.ff.game.api.db.impl;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import com.ff.base.constant.CacheConstants; import com.ff.base.constant.CacheConstants;
@ -12,6 +12,7 @@ import com.ff.base.utils.StringUtils;
import com.ff.base.utils.sign.Md5Utils; import com.ff.base.utils.sign.Md5Utils;
import com.ff.base.utils.uuid.IdUtils; import com.ff.base.utils.uuid.IdUtils;
import com.ff.game.api.IGamesService; import com.ff.game.api.IGamesService;
import com.ff.game.api.db.dto.*;
import com.ff.game.api.request.*; import com.ff.game.api.request.*;
import com.ff.game.domain.*; import com.ff.game.domain.*;
import com.ff.game.service.IGameBettingDetailsService; import com.ff.game.service.IGameBettingDetailsService;
@ -19,12 +20,10 @@ import com.ff.game.service.IGameExchangeMoneyService;
import com.ff.game.service.IGameService; import com.ff.game.service.IGameService;
import com.ff.member.domain.Member; import com.ff.member.domain.Member;
import com.ff.member.service.IMemberService; import com.ff.member.service.IMemberService;
import com.ff.sports.db.client.DBSportsClient; import com.ff.game.api.db.client.DBSportsClient;
import com.ff.sports.db.dto.*;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
@ -120,37 +119,13 @@ public class DBSportsServiceImpl implements IGamesService {
@Transactional @Transactional
public Long exchangeTransferByAgentId(ExchangeTransferMoneyRequestDTO requestDTO) { public Long exchangeTransferByAgentId(ExchangeTransferMoneyRequestDTO requestDTO) {
Member member = memberService.selectMemberByGameAccount(requestDTO.getAccount()); GameExchangeMoney exchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(requestDTO.getGameExchangeId());
String transactionId = GamePlatforms.DBSports.getCode() + IdUtils.simpleUUID();
List<GameExchangeMoney> 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())) { if (requestDTO.getTransferType().equals(TransferType.GAMES.getCode())) {
TransferRequest request = new TransferRequest(); TransferRequest request = new TransferRequest();
request.setUserName(requestDTO.getAccount()); request.setUserName(requestDTO.getAccount());
request.setTransferType(1); request.setTransferType(1);
request.setTransferId(requestDTO.getOrderId()); request.setTransferId(requestDTO.getTransactionId());
request.setMerchantCode(requestDTO.getAgentId()); request.setMerchantCode(requestDTO.getAgentId());
request.setAmount(requestDTO.getAmount().toString()); request.setAmount(requestDTO.getAmount().toString());
request.buildSignature(requestDTO.getAgentKey()); request.buildSignature(requestDTO.getAgentKey());
@ -179,15 +154,19 @@ public class DBSportsServiceImpl implements IGamesService {
} catch (Exception e) { } catch (Exception e) {
log.error("查询会员失败, errorCode:{}, errorMessage:{}", response.getCode(), response.getMsg(), e); log.error("查询会员失败, errorCode:{}, errorMessage:{}", response.getCode(), response.getMsg(), e);
} }
exchangeMoney.setStatus(StatusType.SUCCESS.getValue()); // SUCCESS exchangeMoney.setStep(GameExchangeStep.PLATFORM_TRANSACTION.getCode());
gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney); exchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode());
gameExchangeMoneyService.updateGameExchangeMoney(exchangeMoney);
} else { } else {
exchangeMoney.setStep(GameExchangeStep.PLATFORM_TRANSACTION.getCode());
exchangeMoney.setStepStatus(GameExchangeStepStatus.FAILURE.getCode());
gameExchangeMoneyService.updateGameExchangeMoney(exchangeMoney);
throw new ApiException(ErrorCode.Transfer_In_Failure.getCode()); throw new ApiException(ErrorCode.Transfer_In_Failure.getCode());
} }
} else { } else {
// 获取第三方钱包余额 // 获取第三方钱包余额
MemberInfoRequestDTO memberInfoRequestDTO = MemberInfoRequestDTO.builder() MemberInfoRequestDTO memberInfoRequestDTO = MemberInfoRequestDTO.builder()
.accounts(member.getGameAccount()) .accounts(requestDTO.getAccount())
.agentId(requestDTO.getAgentId()) .agentId(requestDTO.getAgentId())
.agentKey(requestDTO.getAgentKey()) .agentKey(requestDTO.getAgentKey())
.build(); .build();
@ -199,7 +178,7 @@ public class DBSportsServiceImpl implements IGamesService {
TransferRequest request = new TransferRequest(); TransferRequest request = new TransferRequest();
request.setUserName(requestDTO.getAccount()); request.setUserName(requestDTO.getAccount());
request.setTransferType(2); // 转出 request.setTransferType(2); // 转出
request.setTransferId(requestDTO.getOrderId()); request.setTransferId(requestDTO.getTransactionId());
request.setMerchantCode(requestDTO.getAgentId()); request.setMerchantCode(requestDTO.getAgentId());
request.setAmount(/*requestDTO.getAmount().toString()*/ balance.toString()); request.setAmount(/*requestDTO.getAmount().toString()*/ balance.toString());
request.buildSignature(requestDTO.getAgentKey()); request.buildSignature(requestDTO.getAgentKey());
@ -221,15 +200,30 @@ public class DBSportsServiceImpl implements IGamesService {
exchangeMoney.setCoinAfter(afterAmount); exchangeMoney.setCoinAfter(afterAmount);
exchangeMoney.setCurrencyBefore(beforeAmount); exchangeMoney.setCurrencyBefore(beforeAmount);
exchangeMoney.setCurrencyAfter(afterAmount); exchangeMoney.setCurrencyAfter(afterAmount);
exchangeMoney.setStatus(StatusType.SUCCESS.getValue()); // SUCCESS exchangeMoney.setStep(GameExchangeStep.PLATFORM_TRANSACTION.getCode());
gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney); exchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode());
gameExchangeMoneyService.updateGameExchangeMoney(exchangeMoney);
} else { } else {
exchangeMoney.setStep(GameExchangeStep.PLATFORM_TRANSACTION.getCode());
exchangeMoney.setStepStatus(GameExchangeStepStatus.FAILURE.getCode());
gameExchangeMoneyService.updateGameExchangeMoney(exchangeMoney);
throw new ApiException(ErrorCode.Transfer_Out_Failure.getCode()); throw new ApiException(ErrorCode.Transfer_Out_Failure.getCode());
} }
} }
return exchangeMoney.getId(); return exchangeMoney.getId();
} }
/**
* id
*
* @param transactionIdRequestDTO iddto
* @return {@link String }
*/
@Override
public String getTransactionId(TransactionIdRequestDTO transactionIdRequestDTO) {
return gameExchangeMoneyService.getTransactionId(GamePlatforms.DBSports.getInfo(), 11);
}
/** /**
* *
* *
@ -395,8 +389,8 @@ public class DBSportsServiceImpl implements IGamesService {
void getRealtimeRecord(BetRecordByTimeDTO requestDTO, int pageNum) { void getRealtimeRecord(BetRecordByTimeDTO requestDTO, int pageNum) {
GetBetListRequest request = new GetBetListRequest(); GetBetListRequest request = new GetBetListRequest();
request.setStartTime(/*String.valueOf(requestDTO.getStartTime())*/ "1744333220000"); request.setStartTime(String.valueOf(requestDTO.getStartTime()));
request.setEndTime(/*String.valueOf(requestDTO.getEndTime())*/ "1744335020000"); request.setEndTime(String.valueOf(requestDTO.getEndTime()));
request.setMerchantCode(requestDTO.getAgentId()); request.setMerchantCode(requestDTO.getAgentId());
request.setPageNum(pageNum); request.setPageNum(pageNum);
request.setPageSize(1000); request.setPageSize(1000);

View File

@ -196,7 +196,7 @@ public class GamesDGServiceImpl implements IGamesService {
game.setId(GAME_ID); game.setId(GAME_ID);
game.setSortNo(1); game.setSortNo(1);
game.setPlatformCode(GamePlatforms.DG.getCode()); game.setPlatformCode(GamePlatforms.DG.getCode());
game.setPlatformType(PlatformType.GAME_HALL.getCode()); game.setPlatformType(PlatformType.VIDEO.getCode());
game.setGameCode("1"); game.setGameCode("1");
game.setGameSourceType(String.valueOf(1)); game.setGameSourceType(String.valueOf(1));
game.setGameName("真人棋牌"); game.setGameName("真人棋牌");
@ -204,10 +204,28 @@ public class GamesDGServiceImpl implements IGamesService {
game.setNameInfo(Collections.singletonList(new NameInfo("真人棋牌", "zh-CN"))); game.setNameInfo(Collections.singletonList(new NameInfo("真人棋牌", "zh-CN")));
game.setGameId(StringUtils.addSuffix(GamePlatforms.DG.getCode(), 1)); game.setGameId(StringUtils.addSuffix(GamePlatforms.DG.getCode(), 1));
gameService.insertGame(game); gameService.insertGame(game);
}else {
game.setNameInfo(Collections.singletonList(new NameInfo("真人棋牌", "zh-CN")));
gameService.updateGame(game);
} }
return CacheConstants.DG_GAMES; return CacheConstants.DG_GAMES;
} }
/**
* id
*
* @param transactionIdRequestDTO iddto
* @return {@link String }
*/
@Override
public String getTransactionId(TransactionIdRequestDTO transactionIdRequestDTO) {
return GamePlatforms.DG.getInfo() + IdUtils.simpleUUID();
}
/** /**
* id * id
* *
@ -220,39 +238,14 @@ public class GamesDGServiceImpl implements IGamesService {
log.info("GamesDGServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO); log.info("GamesDGServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO);
Member member = memberService.selectMemberByGameAccount(exchangeTransferMoneyRequestDTO.getAccount()); GameExchangeMoney exchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(exchangeTransferMoneyRequestDTO.getGameExchangeId());
String transactionId = GamePlatforms.DG.getInfo() + IdUtils.simpleUUID();
List<GameExchangeMoney> gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList(
GameExchangeMoney.builder()
.tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey())
.orderId(exchangeTransferMoneyRequestDTO.getOrderId())
.build()
);
Assert.isTrue(CollectionUtils.isEmpty(gameExchangeMonies), "订单号重复");
//获取下一个自增id
GameExchangeMoney exchangeMoney = GameExchangeMoney
.builder()
.tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey())
.orderId(exchangeTransferMoneyRequestDTO.getOrderId())
.quota(exchangeTransferMoneyRequestDTO.getQuota())
.balance(exchangeTransferMoneyRequestDTO.getAmount())
.exchangeType(exchangeTransferMoneyRequestDTO.getTransferType())
.currencyCode(exchangeTransferMoneyRequestDTO.getSystemCurrency())
.memberId(member.getId())
.transactionId(transactionId)
.platformCode(GamePlatforms.DG.getInfo())
.build();
exchangeMoney.setCreateBy(Constants.SYSTEM);
exchangeMoney.setStatus(StatusType.IN_PROGRESS.getValue());
exchangeMoney.setStep(GameExchangeStep.CREATE_ORDER.getCode());
exchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode());
gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney);
BigDecimal amount = exchangeTransferMoneyRequestDTO.getAmount(); BigDecimal amount = exchangeTransferMoneyRequestDTO.getAmount();
if (TransferType.ALL.getCode().equals(exchangeTransferMoneyRequestDTO.getTransferType())) { if (TransferType.ALL.getCode().equals(exchangeTransferMoneyRequestDTO.getTransferType())) {
// 获取第三方钱包余额 // 获取第三方钱包余额
MemberInfoRequestDTO gamesBaseRequestDTO = MemberInfoRequestDTO.builder() MemberInfoRequestDTO gamesBaseRequestDTO = MemberInfoRequestDTO.builder()
.accounts(member.getGameAccount()) .accounts(exchangeTransferMoneyRequestDTO.getAccount())
.agentId(exchangeTransferMoneyRequestDTO.getAgentId()) .agentId(exchangeTransferMoneyRequestDTO.getAgentId())
.currency(exchangeTransferMoneyRequestDTO.getCurrency()) .currency(exchangeTransferMoneyRequestDTO.getCurrency())
.agentKey(exchangeTransferMoneyRequestDTO.getAgentKey()) .agentKey(exchangeTransferMoneyRequestDTO.getAgentKey())
@ -265,7 +258,7 @@ public class GamesDGServiceImpl implements IGamesService {
Map<String, Object> params = new LinkedHashMap<>(); Map<String, Object> params = new LinkedHashMap<>();
params.put("username", exchangeTransferMoneyRequestDTO.getAccount()); params.put("username", exchangeTransferMoneyRequestDTO.getAccount());
params.put("amount", amount); params.put("amount", amount);
params.put("serial", transactionId); params.put("serial", exchangeTransferMoneyRequestDTO.getTransactionId());
Map<String, Object> headerMap = this.getKey(exchangeTransferMoneyRequestDTO); Map<String, Object> headerMap = this.getKey(exchangeTransferMoneyRequestDTO);
DGTransactionResponseDTO dgTransactionResponseDTO = DGClient.exchangeTransferByAgentId(params, headerMap); DGTransactionResponseDTO dgTransactionResponseDTO = DGClient.exchangeTransferByAgentId(params, headerMap);

View File

@ -0,0 +1,118 @@
package com.ff.game.api.exchange;
import com.ff.base.enums.GameExchangeStep;
import com.ff.base.enums.GameExchangeStepStatus;
import com.ff.base.exception.base.BaseException;
import com.ff.game.api.exchange.dto.GameExchangeDTO;
import com.ff.game.domain.GameExchangeMoney;
import com.ff.game.service.IGameExchangeMoneyService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.support.TransactionTemplate;
import javax.annotation.Resource;
/**
*
*
* @author shi
* @date 2025/04/09
*/
@Slf4j
public abstract class AbstractStepProcessor implements StepProcessorService {
@Resource
private StepProcessorFactory stepProcessorFactory;
@Resource
private IGameExchangeMoneyService gameExchangeMoneyService;
/**
*
*
* @param gameExchangeMoney
*/
@Override
public void process(GameExchangeDTO gameExchangeMoney) {
boolean processResult = false;
try {
processResult = doProcess(gameExchangeMoney);
} catch (Exception e) {
log.error("游戏余额转移{}-步骤任务{}-执行异常", gameExchangeMoney.getId(), stepKey().getDescription(), e);
throw new BaseException("游戏余额转移"+gameExchangeMoney.getId()+"-步骤任务"+stepKey().getDescription()+"-执行异常" );
}
//更新状态
if (processResult) {
log.info("游戏余额转移{}-步骤任务{}-执行成功", gameExchangeMoney.getId(), stepKey().getDescription());
triggerNextStep(gameExchangeMoney);
}
}
/**
*
*
* @param gameExchangeMoney
*/
@Override
public void rollBack(GameExchangeDTO gameExchangeMoney){
boolean processResult = false;
try {
processResult = doRollBack(gameExchangeMoney);
} catch (Exception e) {
log.error("游戏余额转移{}-步骤任务{}-回滚异常", gameExchangeMoney.getId(), stepKey().getDescription(), e);
}
if (processResult) {
log.info("游戏余额转移{}-步骤任务{}-回滚成功", gameExchangeMoney.getId(), stepKey().getDescription());
triggerBackStep(gameExchangeMoney);
}
}
/**
* 退
*
* @param exchangeMoney
*/
private void triggerBackStep(GameExchangeDTO exchangeMoney) {
GameExchangeStep nextStep = backStepProcessor();
if (nextStep != null) {
stepProcessorFactory.getStepProcessor(nextStep).rollBack(exchangeMoney);
}
}
/**
*
*
* @param exchangeMoney
*/
private void triggerNextStep(GameExchangeDTO exchangeMoney) {
GameExchangeStep nextStep = nextStepProcessor();
if (nextStep != null) {
stepProcessorFactory.getStepProcessor(nextStep).process(exchangeMoney);
}
}
/**
*
*
* @param gameExchangeMoney
* @return boolean
* @throws Exception
*/
abstract public boolean doRollBack(GameExchangeDTO gameExchangeMoney) throws Exception;
/**
* do
*
* @param gameExchangeMoney
* @return boolean
* @throws Exception
*/
abstract public boolean doProcess(GameExchangeDTO gameExchangeMoney) throws Exception;
}

View File

@ -0,0 +1,47 @@
package com.ff.game.api.exchange;
import com.ff.base.enums.GameExchangeStep;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
*
* @author shi
* @date 2025/04/09
*/
@Component
public class StepProcessorFactory {
@Autowired
List<StepProcessorService> stepProcessors;
private Map<GameExchangeStep, StepProcessorService> processorMap;
@PostConstruct
public void init() {
Map<GameExchangeStep, StepProcessorService> map = new HashMap<>();
for (StepProcessorService stepProcessor : stepProcessors) {
map.put(stepProcessor.stepKey(), stepProcessor);
}
processorMap = Collections.unmodifiableMap(map);
}
/**
*
*
* @param stepKey
* @return {@link StepProcessorService }
*/
public StepProcessorService getStepProcessor(GameExchangeStep stepKey) {
return processorMap.get(stepKey);
}
}

View File

@ -0,0 +1,56 @@
package com.ff.game.api.exchange;
import com.ff.base.enums.GameExchangeStep;
import com.ff.game.api.exchange.dto.GameExchangeDTO;
/**
*
*
* @author shi
* @date 2025/04/09
*/
public interface StepProcessorService {
/**
*
*
* @return {@link GameExchangeStep }
*/
GameExchangeStep stepKey();
/**
*
*
* @param gameExchangeMoney
*/
void process(GameExchangeDTO gameExchangeMoney);
/**
* 退
*
* @param gameExchangeMoney
*/
void rollBack(GameExchangeDTO gameExchangeMoney);
/**
*
*
*
* @return
*/
GameExchangeStep nextStepProcessor();
/**
*
*
*
* @return {@link GameExchangeStep }
*/
GameExchangeStep backStepProcessor();
}

View File

@ -0,0 +1,32 @@
package com.ff.game.api.exchange.dto;
import com.ff.base.annotation.Excel;
import com.ff.game.domain.GameExchangeMoney;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.SuperBuilder;
/**
* dto
*
* @author shi
* @date 2025/04/09
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder
public class GameExchangeDTO extends GameExchangeMoney {
/**
* 1 2
*/
private Integer triggerType;
/** 会员账号 */
private String memberAccount;
/** 游戏账号 */
private String gameAccount;
}

View File

@ -0,0 +1,170 @@
package com.ff.game.api.exchange.impl;
import com.ff.base.constant.Constants;
import com.ff.base.enums.*;
import com.ff.base.exception.base.ApiException;
import com.ff.base.utils.StringUtils;
import com.ff.common.domain.TenantGameQuotaFlow;
import com.ff.common.dto.BalanceChangesDTO;
import com.ff.common.dto.GameBalanceExchange;
import com.ff.common.service.ITenantGameQuotaFlowService;
import com.ff.common.service.ITenantGameQuotaService;
import com.ff.game.api.IGamesService;
import com.ff.game.api.exchange.AbstractStepProcessor;
import com.ff.game.api.exchange.dto.GameExchangeDTO;
import com.ff.game.api.request.ExchangeTransferMoneyRequestDTO;
import com.ff.game.api.request.ExchangeTransferStatusRequestDTO;
import com.ff.game.api.request.ExchangeTransferStatusResponseDTO;
import com.ff.game.domain.KeyInfo;
import com.ff.game.domain.Platform;
import com.ff.game.service.IGameExchangeMoneyService;
import com.ff.game.service.IPlatformService;
import com.ff.member.domain.Member;
import com.ff.member.service.IMemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.support.TransactionTemplate;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
/**
*
*
* @author shi
* @date 2025/04/09
*/
@Service
@Order(4)
public class AddBalanceServiceImpl extends AbstractStepProcessor {
@Resource
private IMemberService memberService;
@Resource
private ITenantGameQuotaService tenantGameQuotaService;
@Resource
private IGameExchangeMoneyService gameExchangeMoneyService;
@Resource
private PlatformTransactionManager transactionManager;
@Resource
private IPlatformService platformService;
/**
*
*
* @return {@link GameExchangeStep }
*/
@Override
public GameExchangeStep stepKey() {
return GameExchangeStep.TENANT_QUOTA_DEDUCTED;
}
/**
* do
*
* @param gameExchangeMoney
* @return boolean
*/
@Override
public boolean doProcess(GameExchangeDTO gameExchangeMoney) {
//如果不是之前的步骤代码执行过了 或者是转入操作
if (!gameExchangeMoney.getStep().equals(GameExchangeStep.PLATFORM_TRANSACTION.getCode()) ) {
return Boolean.TRUE;
}
if (!gameExchangeMoney.getStepStatus().equals(StatusType.SUCCESS.getValue())){
return Boolean.TRUE;
}
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
Boolean result = transactionTemplate.execute(transactionStatus -> {
//不是转入操作
if (!TransferType.ALL.getCode().equals(gameExchangeMoney.getExchangeType())) {
gameExchangeMoney.setStep(GameExchangeStep.DEDUCT_BALANCE.getCode());
gameExchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode());
gameExchangeMoney.setStatus(StatusType.SUCCESS.getValue());
return gameExchangeMoneyService.updateGameExchangeMoney(gameExchangeMoney) > 0;
}
Platform platform = platformService.get(gameExchangeMoney.getPlatformCode());
KeyInfo keyInfo = null;
for (KeyInfo keyData : platform.getKeyInfo()) {
if (StringUtils.isNotEmpty(gameExchangeMoney.getCurrencyCode())) {
if (keyData.getCurrency().equalsIgnoreCase(gameExchangeMoney.getCurrencyCode())) {
keyInfo = keyData;
break;
}
}
}
BigDecimal decimal = tenantGameQuotaService.gameBalanceExchange(GameBalanceExchange.builder()
.platformCode(gameExchangeMoney.getPlatformCode())
.sourceId(String.valueOf(gameExchangeMoney.getId()))
.currencyCode(gameExchangeMoney.getCurrencyCode())
.currency(gameExchangeMoney.getCurrencyCode())
.transferType(gameExchangeMoney.getExchangeType())
.amount(gameExchangeMoney.getBalance())
.isAll(Boolean.FALSE)
.account(memberService.selectMemberById(gameExchangeMoney.getMemberId()).getMemberAccount())
.tenantKey(gameExchangeMoney.getTenantKey())
.systemCurrency(gameExchangeMoney.getCurrencyCode())
.agentId(keyInfo.getCode())
.agentKey(keyInfo.getKey())
.build());
gameExchangeMoney.setQuota(decimal);
gameExchangeMoney.setStep(GameExchangeStep.TENANT_QUOTA_DEDUCTED.getCode());
gameExchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode());
gameExchangeMoney.setStatus(StatusType.SUCCESS.getValue());
return gameExchangeMoneyService.updateGameExchangeMoney(gameExchangeMoney) > 0;
});
return Boolean.TRUE.equals(result);
}
/**
*
*
* @param gameExchangeMoney
* @return boolean
*/
@Override
public boolean doRollBack(GameExchangeDTO gameExchangeMoney) {
return Boolean.TRUE;
}
/**
*
*
* @return {@link GameExchangeStep }
*/
@Override
public GameExchangeStep nextStepProcessor() {
return null;
}
/**
*
*
* @return {@link GameExchangeStep }
*/
@Override
public GameExchangeStep backStepProcessor() {
{
return null;
}
}
}

View File

@ -0,0 +1,112 @@
package com.ff.game.api.exchange.impl;
import com.ff.base.constant.Constants;
import com.ff.base.enums.*;
import com.ff.base.exception.base.ApiException;
import com.ff.base.manager.AsyncManager;
import com.ff.base.utils.DateUtils;
import com.ff.base.utils.uuid.IdUtils;
import com.ff.game.api.IGamesService;
import com.ff.game.api.exchange.AbstractStepProcessor;
import com.ff.game.api.exchange.StepProcessorFactory;
import com.ff.game.api.exchange.StepProcessorService;
import com.ff.game.api.exchange.dto.GameExchangeDTO;
import com.ff.game.api.request.ExchangeTransferStatusRequestDTO;
import com.ff.game.api.request.TransactionIdRequestDTO;
import com.ff.game.domain.GameExchangeMoney;
import com.ff.game.service.IGameExchangeMoneyService;
import com.ff.member.domain.Member;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Map;
/**
* impl
*
* @author shi
* @date 2025/04/09
*/
@Service
@Order(1)
public class CreateOrderServiceImpl extends AbstractStepProcessor {
@Resource
private IGameExchangeMoneyService gameExchangeMoneyService;
@Resource
private StepProcessorFactory stepProcessorFactory;
@Autowired
private Map<String, IGamesService> gamesService;
/**
*
*
* @return {@link GameExchangeStep }
*/
@Override
public GameExchangeStep stepKey() {
return GameExchangeStep.CREATE_ORDER;
}
/**
* do
*
* @param gameExchangeMoney
* @return boolean
*/
@Override
public boolean doProcess(GameExchangeDTO gameExchangeMoney) {
String transactionId = gamesService.get(gameExchangeMoney.getPlatformCode()+Constants.SERVICE).getTransactionId(TransactionIdRequestDTO.builder().exchangeType(gameExchangeMoney.getExchangeType()).gameAccount(gameExchangeMoney.getGameAccount()).build());
gameExchangeMoney.setTransactionId(transactionId);
gameExchangeMoney.setCreateBy(Constants.SYSTEM);
gameExchangeMoney.setStatus(StatusType.IN_PROGRESS.getValue());
gameExchangeMoney.setStep(GameExchangeStep.CREATE_ORDER.getCode());
gameExchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode());
return gameExchangeMoneyService.insertGameExchangeMoney(gameExchangeMoney) > 0;
}
/**
*
*
* @param gameExchangeMoney
* @return boolean
*/
@Override
public boolean doRollBack(GameExchangeDTO gameExchangeMoney) {
gameExchangeMoney.setStep(GameExchangeStep.CREATE_ORDER.getCode());
gameExchangeMoney.setStepStatus(GameExchangeStepStatus.FAILURE.getCode());
gameExchangeMoney.setStatus(StatusType.FAILURE.getValue());
gameExchangeMoney.setUpdateBy(Constants.SYSTEM);
gameExchangeMoney.setUpdateTime(DateUtils.getNowDate());
return gameExchangeMoneyService.updateGameExchangeMoney(gameExchangeMoney) > 0;
}
/**
*
*
* @return {@link GameExchangeStep }
*/
@Override
public GameExchangeStep nextStepProcessor() {
return GameExchangeStep.DEDUCT_BALANCE;
}
/**
*
*
* @return {@link GameExchangeStep }
*/
@Override
public GameExchangeStep backStepProcessor() {
return null;
}
}

View File

@ -0,0 +1,207 @@
package com.ff.game.api.exchange.impl;
import com.ff.base.constant.Constants;
import com.ff.base.enums.*;
import com.ff.base.exception.base.ApiException;
import com.ff.base.utils.DateUtils;
import com.ff.base.utils.QuotaUtils;
import com.ff.base.utils.StringUtils;
import com.ff.base.utils.uuid.IdUtils;
import com.ff.common.domain.TenantGameQuota;
import com.ff.common.domain.TenantGameQuotaFlow;
import com.ff.common.dto.BalanceChangesDTO;
import com.ff.common.dto.GameBalanceExchange;
import com.ff.common.service.ITenantGameQuotaFlowService;
import com.ff.common.service.ITenantGameQuotaService;
import com.ff.game.api.exchange.AbstractStepProcessor;
import com.ff.game.api.exchange.StepProcessorFactory;
import com.ff.game.api.exchange.dto.GameExchangeDTO;
import com.ff.game.domain.GameExchangeMoney;
import com.ff.game.domain.KeyInfo;
import com.ff.game.domain.Platform;
import com.ff.game.service.IGameExchangeMoneyService;
import com.ff.game.service.IPlatformService;
import com.ff.member.service.IMemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
/**
* impl
*
* @author shi
* @date 2025/04/09
*/
@Service
@Order(2)
public class DeductBalanceServiceImpl extends AbstractStepProcessor {
@Resource
private IGameExchangeMoneyService gameExchangeMoneyService;
@Resource
private ITenantGameQuotaService tenantGameQuotaService;
@Resource
private IMemberService memberService;
@Resource
private IPlatformService platformService;
@Resource
private ITenantGameQuotaFlowService tenantGameQuotaFlowService;
@Autowired
private PlatformTransactionManager transactionManager;
/**
*
*
* @return {@link GameExchangeStep }
*/
@Override
public GameExchangeStep stepKey() {
return GameExchangeStep.DEDUCT_BALANCE;
}
/**
* do
*
* @param gameExchangeMoney
* @return boolean
*/
@Override
public boolean doProcess(GameExchangeDTO gameExchangeMoney) {
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
Boolean result = transactionTemplate.execute(transactionStatus -> {
//如果不是之前的步骤代码执行过了
if (!gameExchangeMoney.getStep().equals(this.backStepProcessor().getCode())) {
return Boolean.TRUE;
}
//不是转入操作
if (!TransferType.GAMES.getCode().equals(gameExchangeMoney.getExchangeType())) {
gameExchangeMoney.setStep(GameExchangeStep.DEDUCT_BALANCE.getCode());
gameExchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode());
return gameExchangeMoneyService.updateGameExchangeMoney(gameExchangeMoney) > 0;
}
Platform platform = platformService.get(gameExchangeMoney.getPlatformCode());
KeyInfo keyInfo = null;
for (KeyInfo keyData : platform.getKeyInfo()) {
if (StringUtils.isNotEmpty(gameExchangeMoney.getCurrencyCode())) {
if (keyData.getCurrency().equalsIgnoreCase(gameExchangeMoney.getCurrencyCode())) {
keyInfo = keyData;
break;
}
}
}
BigDecimal decimal = tenantGameQuotaService.gameBalanceExchange(GameBalanceExchange.builder()
.platformCode(gameExchangeMoney.getPlatformCode())
.sourceId(String.valueOf(gameExchangeMoney.getId()))
.currencyCode(gameExchangeMoney.getCurrencyCode())
.currency(gameExchangeMoney.getCurrencyCode())
.transferType(gameExchangeMoney.getExchangeType())
.amount(gameExchangeMoney.getBalance())
.account(memberService.selectMemberById(gameExchangeMoney.getMemberId()).getMemberAccount())
.tenantKey(gameExchangeMoney.getTenantKey())
.systemCurrency(gameExchangeMoney.getCurrencyCode())
.agentId(keyInfo.getCode())
.isAll(Boolean.TRUE)
.agentKey(keyInfo.getKey())
.build());
gameExchangeMoney.setQuota(decimal);
gameExchangeMoney.setStep(GameExchangeStep.DEDUCT_BALANCE.getCode());
gameExchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode());
return gameExchangeMoneyService.updateGameExchangeMoney(gameExchangeMoney) > 0;
});
return Boolean.TRUE.equals(result);
}
/**
*
*
* @param gameExchangeMoney
* @return boolean
*/
@Override
public boolean doRollBack(GameExchangeDTO gameExchangeMoney) {
//如果不是之前的步骤代码执行过了 或者是转入操作
if (!gameExchangeMoney.getStep().equals(this.stepKey().getCode())) {
return Boolean.TRUE;
}
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
//如果该订单已经回滚过增加余额
List<TenantGameQuotaFlow> tenantGameQuotaFlows = tenantGameQuotaFlowService.selectTenantGameQuotaFlowList(
TenantGameQuotaFlow.builder()
.sourceId(String.valueOf(gameExchangeMoney.getId()))
.isOut(Boolean.TRUE)
.build());
if (!CollectionUtils.isEmpty(tenantGameQuotaFlows)){
return Boolean.TRUE;
}
tenantGameQuotaFlows = tenantGameQuotaFlowService.selectTenantGameQuotaFlowList(
TenantGameQuotaFlow.builder()
.sourceId(String.valueOf(gameExchangeMoney.getId()))
.isOut(Boolean.FALSE)
.build());
if (CollectionUtils.isEmpty(tenantGameQuotaFlows)) {
return Boolean.TRUE;
}
//取出第一个
TenantGameQuotaFlow tenantGameQuotaFlow = tenantGameQuotaFlows.get(0);
return tenantGameQuotaService.balanceChanges(BalanceChangesDTO.builder()
.isOut(Boolean.TRUE)
.platformCode(tenantGameQuotaFlow.getPlatformCode())
.currencyCode(tenantGameQuotaFlow.getCurrencyCode())
.tenantKey(tenantGameQuotaFlow.getTenantKey())
.balance(tenantGameQuotaFlow.getBalance())
.sourceId(tenantGameQuotaFlow.getSourceId())
.memberId(gameExchangeMoney.getMemberId())
.operationType(OperationType.API_BALANCE.getCode())
.remark(OperationType.API_BALANCE.getDescription())
.quotaType(tenantGameQuotaFlow.getQuotaType()).build());
}
/**
*
*
* @return {@link GameExchangeStep }
*/
@Override
public GameExchangeStep nextStepProcessor() {
return GameExchangeStep.PLATFORM_TRANSACTION;
}
/**
*
*
* @return {@link GameExchangeStep }
*/
@Override
public GameExchangeStep backStepProcessor() {
{
return GameExchangeStep.CREATE_ORDER;
}
}
}

View File

@ -0,0 +1,214 @@
package com.ff.game.api.exchange.impl;
import com.ff.base.constant.Constants;
import com.ff.base.enums.*;
import com.ff.base.exception.base.ApiException;
import com.ff.base.utils.StringUtils;
import com.ff.common.domain.TenantGameQuotaFlow;
import com.ff.common.dto.BalanceChangesDTO;
import com.ff.common.dto.GameBalanceExchange;
import com.ff.common.service.ITenantGameQuotaFlowService;
import com.ff.common.service.ITenantGameQuotaService;
import com.ff.game.api.IGamesService;
import com.ff.game.api.exchange.AbstractStepProcessor;
import com.ff.game.api.exchange.dto.GameExchangeDTO;
import com.ff.game.api.request.ExchangeTransferMoneyRequestDTO;
import com.ff.game.api.request.ExchangeTransferStatusRequestDTO;
import com.ff.game.api.request.ExchangeTransferStatusResponseDTO;
import com.ff.game.domain.GameExchangeMoney;
import com.ff.game.domain.KeyInfo;
import com.ff.game.domain.Platform;
import com.ff.game.service.IGameExchangeMoneyService;
import com.ff.game.service.IPlatformService;
import com.ff.member.domain.Member;
import com.ff.member.service.IMemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
/**
*
*
* @author shi
* @date 2025/04/09
*/
@Service
@Order(3)
public class PlatformTransactionServiceImpl extends AbstractStepProcessor {
@Resource
private IGameExchangeMoneyService gameExchangeMoneyService;
@Resource
private IMemberService memberService;
@Resource
private IPlatformService platformService;
@Autowired
private Map<String, IGamesService> gamesService;
/**
*
*
* @return {@link GameExchangeStep }
*/
@Override
public GameExchangeStep stepKey() {
return GameExchangeStep.PLATFORM_TRANSACTION;
}
/**
* do
*
* @param gameExchangeMoney
* @return boolean
*/
@Override
public boolean doProcess(GameExchangeDTO gameExchangeMoney) {
//如果不是之前的步骤代码执行过了 或者当前步骤成功的
if (!gameExchangeMoney.getStep().equals(this.backStepProcessor().getCode())&&
(GameExchangeStep.PLATFORM_TRANSACTION.getCode().equals(gameExchangeMoney.getStep())&&
gameExchangeMoney.getStepStatus().equals(GameExchangeStepStatus.SUCCESS.getCode()))
) {
return Boolean.TRUE;
}
Platform platform = platformService.get(gameExchangeMoney.getPlatformCode());
String targetCurrency = platform.getCurrencyInfo().get(gameExchangeMoney.getCurrencyCode());
ApiException.notNull(targetCurrency, ErrorCode.CURRENCY_NOT_EXIST.getCode());
KeyInfo keyInfo = null;
for (KeyInfo keyData : platform.getKeyInfo()) {
if (StringUtils.isNotEmpty(gameExchangeMoney.getCurrencyCode())) {
if (keyData.getCurrency().equalsIgnoreCase(gameExchangeMoney.getCurrencyCode())) {
keyInfo = keyData;
break;
}
}
}
Member member = memberService.selectMemberById(gameExchangeMoney.getMemberId());
IGamesService iGamesService = gamesService.get(gameExchangeMoney.getPlatformCode() + Constants.SERVICE);
//查询订单详情
if (TriggerType.TIMER.getCode() == gameExchangeMoney.getTriggerType()) {
//做二次确认调订单详情接口
this.doRollBack(gameExchangeMoney);
if (GameExchangeStepStatus.FAILURE.getCode() == gameExchangeMoney.getStepStatus()){
throw new ApiException(ErrorCode.BALANCE_TRANSFER_FAILED.getCode());
}
}
try {
//操作第三方额度接口
ExchangeTransferMoneyRequestDTO exchangeTransferMoneyRequestDTO = ExchangeTransferMoneyRequestDTO.builder()
.agentId(keyInfo.getCode())
.agentKey(keyInfo.getKey())
.account(member.getGameAccount())
.currency(targetCurrency)
.amount(gameExchangeMoney.getBalance())
.transferType(gameExchangeMoney.getExchangeType())
.transactionId(gameExchangeMoney.getTransactionId())
.gameExchangeId(gameExchangeMoney.getId())
.vendor(platform)
.keyInfo(keyInfo)
.build();
Long id = iGamesService.exchangeTransferByAgentId(exchangeTransferMoneyRequestDTO);
}catch (Exception e){
//做二次确认调订单详情接口
this.doRollBack(gameExchangeMoney);
if (GameExchangeStepStatus.FAILURE.getCode() == gameExchangeMoney.getStepStatus()){
throw new ApiException(ErrorCode.BALANCE_TRANSFER_FAILED.getCode());
}
}
GameExchangeMoney exchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(gameExchangeMoney.getId());
gameExchangeMoney.setBalance(exchangeMoney.getBalance());
gameExchangeMoney.setStep(exchangeMoney.getStep());
gameExchangeMoney.setStepStatus(exchangeMoney.getStepStatus());
return gameExchangeMoneyService.updateGameExchangeMoney(gameExchangeMoney) > 0;
}
/**
*
*
* @param gameExchangeMoney
* @return boolean
*/
@Override
public boolean doRollBack(GameExchangeDTO gameExchangeMoney) {
Platform platform = platformService.get(gameExchangeMoney.getPlatformCode());
String targetCurrency = platform.getCurrencyInfo().get(gameExchangeMoney.getCurrencyCode());
ApiException.notNull(targetCurrency, ErrorCode.CURRENCY_NOT_EXIST.getCode());
KeyInfo keyInfo = null;
for (KeyInfo keyData : platform.getKeyInfo()) {
if (StringUtils.isNotEmpty(gameExchangeMoney.getCurrencyCode())) {
if (keyData.getCurrency().equalsIgnoreCase(gameExchangeMoney.getCurrencyCode())) {
keyInfo = keyData;
break;
}
}
}
Member member = memberService.selectMemberById(gameExchangeMoney.getMemberId());
IGamesService iGamesService = gamesService.get(gameExchangeMoney.getPlatformCode() + Constants.SERVICE);
ExchangeTransferStatusRequestDTO exchangeTransferStatusRequestDTO = new ExchangeTransferStatusRequestDTO();
exchangeTransferStatusRequestDTO.setAccount(member.getGameAccount());
exchangeTransferStatusRequestDTO.setCurrency(targetCurrency);
exchangeTransferStatusRequestDTO.setOrderId(gameExchangeMoney.getTransactionId());
exchangeTransferStatusRequestDTO.setAgentId(keyInfo.getCode());
exchangeTransferStatusRequestDTO.setAgentKey(keyInfo.getKey());
exchangeTransferStatusRequestDTO.setGameExchangeMoneyId(gameExchangeMoney.getId());
exchangeTransferStatusRequestDTO.setVendor(platform);
exchangeTransferStatusRequestDTO.setKeyInfo(keyInfo);
exchangeTransferStatusRequestDTO.setSystemCurrency(gameExchangeMoney.getCurrencyCode());
ExchangeTransferStatusResponseDTO statusResponseDTO = iGamesService.exchangeTransferStatus(exchangeTransferStatusRequestDTO);
//订单已成功
if (StatusType.SUCCESS.getValue().equals(statusResponseDTO.getStatusType())) {
gameExchangeMoney.setStep(GameExchangeStep.PLATFORM_TRANSACTION.getCode());
gameExchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode());
return gameExchangeMoneyService.updateGameExchangeMoney(gameExchangeMoney) > 0;
}
gameExchangeMoney.setStep(GameExchangeStep.PLATFORM_TRANSACTION.getCode());
gameExchangeMoney.setStepStatus(GameExchangeStepStatus.FAILURE.getCode());
return gameExchangeMoneyService.updateGameExchangeMoney(gameExchangeMoney) > 0;
}
/**
*
*
* @return {@link GameExchangeStep }
*/
@Override
public GameExchangeStep nextStepProcessor() {
return GameExchangeStep.TENANT_QUOTA_DEDUCTED;
}
/**
*
*
* @return {@link GameExchangeStep }
*/
@Override
public GameExchangeStep backStepProcessor() {
{
return GameExchangeStep.DEDUCT_BALANCE;
}
}
}

View File

@ -1,4 +1,4 @@
package com.ff.sports.fb.address; package com.ff.game.api.fb.address;
import com.dtflys.forest.callback.AddressSource; import com.dtflys.forest.callback.AddressSource;
import com.dtflys.forest.http.ForestAddress; import com.dtflys.forest.http.ForestAddress;

View File

@ -1,8 +1,8 @@
package com.ff.sports.fb.client; package com.ff.game.api.fb.client;
import com.dtflys.forest.annotation.*; import com.dtflys.forest.annotation.*;
import com.ff.sports.fb.address.FBSportsAddress; import com.ff.game.api.fb.address.FBSportsAddress;
import com.ff.sports.fb.dto.*; import com.ff.game.api.fb.dto.*;
/** /**
* <a href="https://doc.newsportspro.com/apidoc_data.html"></a><br/> * <a href="https://doc.newsportspro.com/apidoc_data.html"></a><br/>

View File

@ -1,4 +1,4 @@
package com.ff.sports.fb.dto; package com.ff.game.api.fb.dto;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.fb.dto; package com.ff.game.api.fb.dto;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.db.dto; package com.ff.game.api.fb.dto;
/** /**
* @author cengy * @author cengy

View File

@ -1,4 +1,4 @@
package com.ff.sports.fb.dto; package com.ff.game.api.fb.dto;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.fb.dto; package com.ff.game.api.fb.dto;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.fb.dto; package com.ff.game.api.fb.dto;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.fb.dto; package com.ff.game.api.fb.dto;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.fb.dto; package com.ff.game.api.fb.dto;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.fb.dto; package com.ff.game.api.fb.dto;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.fb.dto; package com.ff.game.api.fb.dto;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.fb.dto; package com.ff.game.api.fb.dto;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.fb.dto; package com.ff.game.api.fb.dto;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.fb.dto; package com.ff.game.api.fb.dto;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.fb.dto; package com.ff.game.api.fb.dto;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.fb.dto; package com.ff.game.api.fb.dto;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.fb.dto; package com.ff.game.api.fb.dto;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.fb.dto; package com.ff.game.api.fb.dto;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.fb.dto; package com.ff.game.api.fb.dto;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.fb.dto; package com.ff.game.api.fb.dto;
import lombok.Data; import lombok.Data;

View File

@ -1,4 +1,4 @@
package com.ff.sports.fb.impl; package com.ff.game.api.fb.impl;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import com.ff.base.constant.CacheConstants; import com.ff.base.constant.CacheConstants;
@ -12,6 +12,7 @@ import com.ff.base.utils.StringUtils;
import com.ff.base.utils.sign.Md5Utils; import com.ff.base.utils.sign.Md5Utils;
import com.ff.base.utils.uuid.IdUtils; import com.ff.base.utils.uuid.IdUtils;
import com.ff.game.api.IGamesService; import com.ff.game.api.IGamesService;
import com.ff.game.api.fb.dto.*;
import com.ff.game.api.request.*; import com.ff.game.api.request.*;
import com.ff.game.domain.*; import com.ff.game.domain.*;
import com.ff.game.service.IGameBettingDetailsService; import com.ff.game.service.IGameBettingDetailsService;
@ -19,13 +20,11 @@ import com.ff.game.service.IGameExchangeMoneyService;
import com.ff.game.service.IGameService; import com.ff.game.service.IGameService;
import com.ff.member.domain.Member; import com.ff.member.domain.Member;
import com.ff.member.service.IMemberService; import com.ff.member.service.IMemberService;
import com.ff.sports.fb.client.FBSportsClient; import com.ff.game.api.fb.client.FBSportsClient;
import com.ff.sports.fb.dto.*;
import com.ff.utils.TimestampFromString; import com.ff.utils.TimestampFromString;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
@ -130,37 +129,15 @@ public class FBSportsServiceImpl implements IGamesService {
@Transactional @Transactional
public Long exchangeTransferByAgentId(ExchangeTransferMoneyRequestDTO requestDTO) { public Long exchangeTransferByAgentId(ExchangeTransferMoneyRequestDTO requestDTO) {
Member member = memberService.selectMemberByGameAccount(requestDTO.getAccount());
String transactionId = GamePlatforms.FBSports.getCode() + IdUtils.simpleUUID(); GameExchangeMoney exchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(requestDTO.getGameExchangeId());
List<GameExchangeMoney> gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList(
GameExchangeMoney.builder()
.tenantKey(requestDTO.getTenantKey())
.orderId(requestDTO.getOrderId())
.build()
);
Assert.isTrue(CollectionUtils.isEmpty(gameExchangeMonies), "订单号重复");
//获取下一个自增id
GameExchangeMoney exchangeMoney = GameExchangeMoney
.builder()
.orderId(requestDTO.getOrderId())
.tenantKey(requestDTO.getTenantKey())
.quota(requestDTO.getQuota())
.balance(requestDTO.getAmount())
.exchangeType(requestDTO.getTransferType())
.currencyCode(requestDTO.getSystemCurrency())
.memberId(member.getId())
.transactionId(transactionId)
.platformCode(GamePlatforms.FBSports.getCode())
.build();
exchangeMoney.setCreateBy(Constants.SYSTEM);
//接口限制限制50字符
exchangeMoney.setTransactionId(transactionId);
// 转入 // 转入
if (requestDTO.getTransferType().equals(TransferType.GAMES.getCode())) { if (requestDTO.getTransferType().equals(TransferType.GAMES.getCode())) {
TransferInRequest request = new TransferInRequest(); TransferInRequest request = new TransferInRequest();
request.setMerchantUserId(requestDTO.getAccount()); request.setMerchantUserId(requestDTO.getAccount());
request.setAmount(requestDTO.getAmount()); request.setAmount(requestDTO.getAmount());
request.setBusinessId(requestDTO.getOrderId()); request.setBusinessId(requestDTO.getTransactionId());
request.setCurrencyId(Integer.parseInt(requestDTO.getCurrency())); request.setCurrencyId(Integer.parseInt(requestDTO.getCurrency()));
long timestamp = System.currentTimeMillis(); long timestamp = System.currentTimeMillis();
String jsonBody = request.toJSON(); String jsonBody = request.toJSON();
@ -183,15 +160,19 @@ public class FBSportsServiceImpl implements IGamesService {
exchangeMoney.setCoinAfter(response.getData()); exchangeMoney.setCoinAfter(response.getData());
exchangeMoney.setCurrencyBefore(response.getData().subtract(transAmount)); exchangeMoney.setCurrencyBefore(response.getData().subtract(transAmount));
exchangeMoney.setCurrencyAfter(response.getData()); exchangeMoney.setCurrencyAfter(response.getData());
exchangeMoney.setStatus(StatusType.SUCCESS.getValue()); // SUCCESS exchangeMoney.setStep(GameExchangeStep.PLATFORM_TRANSACTION.getCode());
gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney); exchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode());
gameExchangeMoneyService.updateGameExchangeMoney(exchangeMoney);
} else { } else {
exchangeMoney.setStep(GameExchangeStep.PLATFORM_TRANSACTION.getCode());
exchangeMoney.setStepStatus(GameExchangeStepStatus.FAILURE.getCode());
gameExchangeMoneyService.updateGameExchangeMoney(exchangeMoney);
throw new ApiException(ErrorCode.Transfer_In_Failure.getCode()); throw new ApiException(ErrorCode.Transfer_In_Failure.getCode());
} }
} else { } else {
// 获取第三方钱包余额 // 获取第三方钱包余额
MemberInfoRequestDTO memberInfoRequestDTO = MemberInfoRequestDTO.builder() MemberInfoRequestDTO memberInfoRequestDTO = MemberInfoRequestDTO.builder()
.accounts(member.getGameAccount()) .accounts(requestDTO.getAccount())
.agentId(requestDTO.getAgentId()) .agentId(requestDTO.getAgentId())
.agentKey(requestDTO.getAgentKey()) .agentKey(requestDTO.getAgentKey())
.build(); .build();
@ -200,7 +181,7 @@ public class FBSportsServiceImpl implements IGamesService {
TransferOutRequest request = new TransferOutRequest(); TransferOutRequest request = new TransferOutRequest();
request.setMerchantUserId(requestDTO.getAccount()); request.setMerchantUserId(requestDTO.getAccount());
request.setAmount(/*requestDTO.getAmount()*/ balance); request.setAmount(/*requestDTO.getAmount()*/ balance);
request.setBusinessId(requestDTO.getOrderId()); request.setBusinessId(requestDTO.getTransactionId());
request.setCurrencyId(Integer.parseInt(requestDTO.getCurrency())); request.setCurrencyId(Integer.parseInt(requestDTO.getCurrency()));
long timestamp = System.currentTimeMillis(); long timestamp = System.currentTimeMillis();
@ -229,9 +210,13 @@ public class FBSportsServiceImpl implements IGamesService {
exchangeMoney.setCoinAfter(response.getData()); exchangeMoney.setCoinAfter(response.getData());
exchangeMoney.setCurrencyBefore(response.getData().add(transAmount)); exchangeMoney.setCurrencyBefore(response.getData().add(transAmount));
exchangeMoney.setCurrencyAfter(response.getData()); exchangeMoney.setCurrencyAfter(response.getData());
exchangeMoney.setStatus(StatusType.SUCCESS.getValue()); // SUCCESS exchangeMoney.setStep(GameExchangeStep.PLATFORM_TRANSACTION.getCode());
gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney); exchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode());
gameExchangeMoneyService.updateGameExchangeMoney(exchangeMoney);
} else { } else {
exchangeMoney.setStep(GameExchangeStep.PLATFORM_TRANSACTION.getCode());
exchangeMoney.setStepStatus(GameExchangeStepStatus.FAILURE.getCode());
gameExchangeMoneyService.updateGameExchangeMoney(exchangeMoney);
throw new ApiException(ErrorCode.Transfer_Out_Failure.getCode()); throw new ApiException(ErrorCode.Transfer_Out_Failure.getCode());
} }
} }
@ -278,6 +263,19 @@ public class FBSportsServiceImpl implements IGamesService {
} }
} }
/**
* id
*
* @param transactionIdRequestDTO iddto
* @return {@link String }
*/
@Override
public String getTransactionId(TransactionIdRequestDTO transactionIdRequestDTO) {
return GamePlatforms.FBSports.getCode() + IdUtils.simpleUUID();
}
/** /**
* *
* *
@ -443,7 +441,7 @@ public class FBSportsServiceImpl implements IGamesService {
); );
if (this.isSuccess(response.getCode())) { if (this.isSuccess(response.getCode())) {
status = StatusType.SUCCESS.getValue(); status = StatusType.SUCCESS.getValue();
}else { } else {
status = StatusType.FAILURE.getValue(); status = StatusType.FAILURE.getValue();
} }
} }

View File

@ -20,6 +20,10 @@ public class MyFCAddressSource implements AddressSource {
public ForestAddress getAddress(ForestRequest request) { public ForestAddress getAddress(ForestRequest request) {
String apiBaseUrl = platformService.get(GamePlatforms.FC.getCode()) String apiBaseUrl = platformService.get(GamePlatforms.FC.getCode())
.getUrlInfo().getUrl(); .getUrlInfo().getUrl();
return new ForestAddress("https", apiBaseUrl, 443, ""); String https = platformService.get(GamePlatforms.FC.getCode())
.getUrlInfo().getHttps();
String host = platformService.get(GamePlatforms.FC.getCode())
.getUrlInfo().getHost();
return new ForestAddress(https, apiBaseUrl, Integer.valueOf(host), "");
} }
} }

View File

@ -25,7 +25,7 @@ public class ApiCFBalanceTransferResponseDTO {
* ID * ID
*/ */
@JsonProperty("BankID") @JsonProperty("BankID")
private int bankID; private Long bankID;
/** /**
* ID * ID

View File

@ -25,7 +25,7 @@ public class ApiCFBalanceTransferStatusResponseDTO {
* ID * ID
*/ */
@JsonProperty("bankID") @JsonProperty("bankID")
private int bankId; private Long bankId;
/** /**
* ID * ID

View File

@ -283,6 +283,11 @@ public class GamesFCServiceImpl implements IGamesService {
gameService.insertGame(game); gameService.insertGame(game);
} else { } else {
game = games.get(0); game = games.get(0);
List<NameInfo> nameInfos = new ArrayList<>();
nameInfos.add(NameInfo.builder().lang("zh-CN").name(gameDetails.getGameNameOfChinese()).build());
nameInfos.add(NameInfo.builder().lang("en-US").name(gameDetails.getGameNameOfEnglish()).build());
game.setNameInfo(nameInfos);
gameService.updateGame(game);
} }
gameDetails.setSystemGameId(game.getGameId()); gameDetails.setSystemGameId(game.getGameId());
@ -313,34 +318,7 @@ public class GamesFCServiceImpl implements IGamesService {
log.info("GamesFCServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO); log.info("GamesFCServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO);
Member member = memberService.selectMemberByGameAccount(exchangeTransferMoneyRequestDTO.getAccount()); GameExchangeMoney exchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(exchangeTransferMoneyRequestDTO.getGameExchangeId());
String transactionId = gameExchangeMoneyService.getTransactionId(GamePlatforms.FC.getInfo(), 30);
List<GameExchangeMoney> gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList(
GameExchangeMoney.builder()
.tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey())
.orderId(exchangeTransferMoneyRequestDTO.getOrderId())
.build()
);
Assert.isTrue(CollectionUtils.isEmpty(gameExchangeMonies), "订单号重复");
//获取下一个自增id
GameExchangeMoney exchangeMoney = GameExchangeMoney
.builder()
.tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey())
.orderId(exchangeTransferMoneyRequestDTO.getOrderId())
.quota(exchangeTransferMoneyRequestDTO.getQuota())
.balance(exchangeTransferMoneyRequestDTO.getAmount())
.exchangeType(exchangeTransferMoneyRequestDTO.getTransferType())
.currencyCode(exchangeTransferMoneyRequestDTO.getSystemCurrency())
.memberId(member.getId())
.transactionId(transactionId)
.platformCode(GamePlatforms.FC.getInfo())
.build();
exchangeMoney.setCreateBy(Constants.SYSTEM);
exchangeMoney.setStatus(StatusType.IN_PROGRESS.getValue());
exchangeMoney.setStep(GameExchangeStep.CREATE_ORDER.getCode());
exchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode());
gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney);
//获取余额 //获取余额
@ -352,7 +330,7 @@ public class GamesFCServiceImpl implements IGamesService {
//获取当前游戏币 //获取当前游戏币
MemberInfoRequestDTO gamesBaseRequestDTO = MemberInfoRequestDTO.builder() MemberInfoRequestDTO gamesBaseRequestDTO = MemberInfoRequestDTO.builder()
.accounts(member.getGameAccount()) .accounts(exchangeTransferMoneyRequestDTO.getAccount())
.agentId(exchangeTransferMoneyRequestDTO.getAgentId()) .agentId(exchangeTransferMoneyRequestDTO.getAgentId())
.agentKey(exchangeTransferMoneyRequestDTO.getAgentKey()) .agentKey(exchangeTransferMoneyRequestDTO.getAgentKey())
.currency(exchangeTransferMoneyRequestDTO.getCurrency()) .currency(exchangeTransferMoneyRequestDTO.getCurrency())
@ -366,7 +344,7 @@ public class GamesFCServiceImpl implements IGamesService {
Map<String, Object> paramsMap = new HashMap<>(); Map<String, Object> paramsMap = new HashMap<>();
paramsMap.put("MemberAccount", exchangeTransferMoneyRequestDTO.getAccount()); paramsMap.put("MemberAccount", exchangeTransferMoneyRequestDTO.getAccount());
paramsMap.put("TrsID", transactionId); paramsMap.put("TrsID", exchangeTransferMoneyRequestDTO.getTransactionId());
paramsMap.put("AllOut", type); paramsMap.put("AllOut", type);
paramsMap.put("Points", amount); paramsMap.put("Points", amount);
paramsMap.putAll(getKeyMap(paramsMap, gamesBaseRequestDTO.getAgentKey(), gamesBaseRequestDTO.getCurrency(), gamesBaseRequestDTO.getAgentId())); paramsMap.putAll(getKeyMap(paramsMap, gamesBaseRequestDTO.getAgentKey(), gamesBaseRequestDTO.getCurrency(), gamesBaseRequestDTO.getAgentId()));
@ -393,6 +371,19 @@ public class GamesFCServiceImpl implements IGamesService {
return exchangeMoney.getId(); return exchangeMoney.getId();
} }
/**
* id
*
* @param transactionIdRequestDTO iddto
* @return {@link String }
*/
@Override
public String getTransactionId(TransactionIdRequestDTO transactionIdRequestDTO) {
return gameExchangeMoneyService.getTransactionId(GamePlatforms.FC.getInfo(), 30);
}
/** /**
* *
* *

View File

@ -252,6 +252,11 @@ public class GamesJILIServiceImpl implements IGamesService {
gameService.insertGame(game); gameService.insertGame(game);
} else { } else {
game = games.get(0); game = games.get(0);
List<NameInfo> nameInfos = new ArrayList<>();
nameInfos.add(new NameInfo(gamesDataDTO.getName().getZhCN(), "zh-CN"));
nameInfos.add(new NameInfo(gamesDataDTO.getName().getEnUS(), "en-US"));
game.setNameInfo(nameInfos);
gameService.updateGame(game);
} }
gamesDataDTO.setSystemGameId(game.getGameId()); gamesDataDTO.setSystemGameId(game.getGameId());
@ -269,6 +274,17 @@ public class GamesJILIServiceImpl implements IGamesService {
return CacheConstants.JILI_GAMES; return CacheConstants.JILI_GAMES;
} }
/**
* id
*
* @param transactionIdRequestDTO iddto
* @return {@link String }
*/
@Override
public String getTransactionId(TransactionIdRequestDTO transactionIdRequestDTO) {
return GamePlatforms.JILI.getInfo() + IdUtils.simpleUUID();
}
/** /**
* id * id
* *
@ -280,35 +296,10 @@ public class GamesJILIServiceImpl implements IGamesService {
public Long exchangeTransferByAgentId(ExchangeTransferMoneyRequestDTO exchangeTransferMoneyRequestDTO) { public Long exchangeTransferByAgentId(ExchangeTransferMoneyRequestDTO exchangeTransferMoneyRequestDTO) {
Member member = memberService.selectMemberByGameAccount(exchangeTransferMoneyRequestDTO.getAccount()); Member member = memberService.selectMemberByGameAccount(exchangeTransferMoneyRequestDTO.getAccount());
String transactionId = GamePlatforms.JILI.getInfo() + IdUtils.simpleUUID(); GameExchangeMoney exchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(exchangeTransferMoneyRequestDTO.getGameExchangeId());
List<GameExchangeMoney> gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList(
GameExchangeMoney.builder()
.tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey())
.orderId(exchangeTransferMoneyRequestDTO.getOrderId())
.build()
);
Assert.isTrue(CollectionUtils.isEmpty(gameExchangeMonies), "订单号重复");
//获取下一个自增id
GameExchangeMoney exchangeMoney = GameExchangeMoney
.builder()
.orderId(exchangeTransferMoneyRequestDTO.getOrderId())
.tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey())
.quota(exchangeTransferMoneyRequestDTO.getQuota())
.balance(exchangeTransferMoneyRequestDTO.getAmount())
.exchangeType(exchangeTransferMoneyRequestDTO.getTransferType())
.currencyCode(exchangeTransferMoneyRequestDTO.getSystemCurrency())
.memberId(member.getId())
.transactionId(transactionId)
.platformCode(GamePlatforms.JILI.getInfo())
.build();
exchangeMoney.setCreateBy(Constants.SYSTEM);
exchangeMoney.setStatus(StatusType.IN_PROGRESS.getValue());
exchangeMoney.setStep(GameExchangeStep.CREATE_ORDER.getCode());
exchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode());
gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney);
String query = "Account=" + exchangeTransferMoneyRequestDTO.getAccount() String query = "Account=" + exchangeTransferMoneyRequestDTO.getAccount()

View File

@ -301,12 +301,30 @@ public class GamesKMServiceImpl implements IGamesService {
gameService.insertGame(game); gameService.insertGame(game);
} else { } else {
game = games.get(0); game = games.get(0);
List<NameInfo> nameInfos = new ArrayList<>();
nameInfos.add(new NameInfo(gamesDataDTO.getName(), "zh-CN"));
game.setNameInfo(nameInfos);
gameService.updateGame(game);
} }
gamesDataDTO.setSystemGameId(game.getGameId()); gamesDataDTO.setSystemGameId(game.getGameId());
} }
return gameList.getGames(); return gameList.getGames();
} }
/**
* id
*
* @param transactionIdRequestDTO iddto
* @return {@link String }
*/
@Override
public String getTransactionId(TransactionIdRequestDTO transactionIdRequestDTO) {
return GamePlatforms.KM.getInfo() + IdUtils.simpleUUID();
}
/** /**
* id * id
* *
@ -319,41 +337,17 @@ public class GamesKMServiceImpl implements IGamesService {
log.info("GamesKMServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO); log.info("GamesKMServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO);
Member member = memberService.selectMemberByGameAccount(exchangeTransferMoneyRequestDTO.getAccount()); GameExchangeMoney exchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(exchangeTransferMoneyRequestDTO.getGameExchangeId());
String transactionId = GamePlatforms.KM.getInfo() + IdUtils.simpleUUID();
List<GameExchangeMoney> gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList(
GameExchangeMoney.builder()
.tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey())
.orderId(exchangeTransferMoneyRequestDTO.getOrderId())
.build()
);
Assert.isTrue(CollectionUtils.isEmpty(gameExchangeMonies), "订单号重复");
//获取下一个自增id
GameExchangeMoney exchangeMoney = GameExchangeMoney
.builder()
.tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey())
.orderId(exchangeTransferMoneyRequestDTO.getOrderId())
.quota(exchangeTransferMoneyRequestDTO.getQuota())
.balance(exchangeTransferMoneyRequestDTO.getAmount())
.exchangeType(exchangeTransferMoneyRequestDTO.getTransferType())
.currencyCode(exchangeTransferMoneyRequestDTO.getSystemCurrency())
.memberId(member.getId())
.transactionId(transactionId)
.platformCode(GamePlatforms.KM.getInfo())
.build();
exchangeMoney.setCreateBy(Constants.SYSTEM);
exchangeMoney.setStatus(StatusType.IN_PROGRESS.getValue());
exchangeMoney.setStep(GameExchangeStep.CREATE_ORDER.getCode());
exchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode());
gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney);
BigDecimal amount = exchangeTransferMoneyRequestDTO.getAmount(); BigDecimal amount = exchangeTransferMoneyRequestDTO.getAmount();
if (TransferType.ALL.getCode().equals(exchangeTransferMoneyRequestDTO.getTransferType())) { if (TransferType.ALL.getCode().equals(exchangeTransferMoneyRequestDTO.getTransferType())) {
// 获取第三方钱包余额 // 获取第三方钱包余额
MemberInfoRequestDTO gamesBaseRequestDTO = MemberInfoRequestDTO.builder() MemberInfoRequestDTO gamesBaseRequestDTO = MemberInfoRequestDTO.builder()
.accounts(member.getGameAccount()) .accounts(exchangeTransferMoneyRequestDTO.getAccount())
.agentId(exchangeTransferMoneyRequestDTO.getAgentId()) .agentId(exchangeTransferMoneyRequestDTO.getAgentId())
.currency(exchangeTransferMoneyRequestDTO.getCurrency()) .currency(exchangeTransferMoneyRequestDTO.getCurrency())
.agentKey(exchangeTransferMoneyRequestDTO.getAgentKey()) .agentKey(exchangeTransferMoneyRequestDTO.getAgentKey())
@ -366,7 +360,7 @@ public class GamesKMServiceImpl implements IGamesService {
params.put("userid", exchangeTransferMoneyRequestDTO.getAccount()); params.put("userid", exchangeTransferMoneyRequestDTO.getAccount());
params.put("amt", amount); params.put("amt", amount);
params.put("cur", exchangeTransferMoneyRequestDTO.getCurrency()); params.put("cur", exchangeTransferMoneyRequestDTO.getCurrency());
params.put("txid", transactionId); params.put("txid", exchangeTransferMoneyRequestDTO.getTransactionId());
Map<String, Object> headerMap = this.getKey(exchangeTransferMoneyRequestDTO); Map<String, Object> headerMap = this.getKey(exchangeTransferMoneyRequestDTO);
KMTransactionResponse kmTransactionResponse; KMTransactionResponse kmTransactionResponse;

View File

@ -247,6 +247,11 @@ public class MeiTianGameServiceImpl implements IGamesService {
gameService.insertGame(game); gameService.insertGame(game);
} else { } else {
game = games.get(0); game = games.get(0);
List<NameInfo> nameInfos = new ArrayList<>();
nameInfos.add(new NameInfo(gamesDataDTO.getCnName(), "zh-CN"));
nameInfos.add(new NameInfo(gamesDataDTO.getEnName(), "en-US"));
game.setNameInfo(nameInfos);
gameService.updateGame(game);
} }
gamesDataDTO.setSystemGameId(game.getGameId()); gamesDataDTO.setSystemGameId(game.getGameId());
} }
@ -258,6 +263,17 @@ public class MeiTianGameServiceImpl implements IGamesService {
return CacheConstants.MeiTian_GAMES; return CacheConstants.MeiTian_GAMES;
} }
/**
* id
*
* @param transactionIdRequestDTO iddto
* @return {@link String }
*/
@Override
public String getTransactionId(TransactionIdRequestDTO transactionIdRequestDTO) {
return GamePlatforms.MT.getCode() + IdUtils.simpleUUID();
}
/** /**
* id * id
* *
@ -269,35 +285,10 @@ public class MeiTianGameServiceImpl implements IGamesService {
public Long exchangeTransferByAgentId(ExchangeTransferMoneyRequestDTO exchangeTransferMoneyRequestDTO) { public Long exchangeTransferByAgentId(ExchangeTransferMoneyRequestDTO exchangeTransferMoneyRequestDTO) {
Member member = memberService.selectMemberByGameAccount(exchangeTransferMoneyRequestDTO.getAccount()); Member member = memberService.selectMemberByGameAccount(exchangeTransferMoneyRequestDTO.getAccount());
String transactionId = GamePlatforms.MT.getCode() + IdUtils.simpleUUID(); GameExchangeMoney exchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(exchangeTransferMoneyRequestDTO.getGameExchangeId());
List<GameExchangeMoney> gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList(
GameExchangeMoney.builder()
.tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey())
.orderId(exchangeTransferMoneyRequestDTO.getOrderId())
.build()
);
Assert.isTrue(CollectionUtils.isEmpty(gameExchangeMonies), "订单号重复");
//获取下一个自增id
GameExchangeMoney exchangeMoney = GameExchangeMoney
.builder()
.orderId(exchangeTransferMoneyRequestDTO.getOrderId())
.tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey())
.quota(exchangeTransferMoneyRequestDTO.getQuota())
.balance(exchangeTransferMoneyRequestDTO.getAmount())
.exchangeType(exchangeTransferMoneyRequestDTO.getTransferType())
.currencyCode(exchangeTransferMoneyRequestDTO.getSystemCurrency())
.memberId(member.getId())
.transactionId(transactionId)
.platformCode(GamePlatforms.MT.getCode())
.build();
exchangeMoney.setCreateBy(Constants.SYSTEM);
exchangeMoney.setStatus(StatusType.IN_PROGRESS.getValue());
exchangeMoney.setStep(GameExchangeStep.CREATE_ORDER.getCode());
exchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode());
gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney);
String key = exchangeTransferMoneyRequestDTO.getAgentKey(); String key = exchangeTransferMoneyRequestDTO.getAgentKey();
String merchantId = exchangeTransferMoneyRequestDTO.getAgentId(); String merchantId = exchangeTransferMoneyRequestDTO.getAgentId();
@ -316,7 +307,7 @@ public class MeiTianGameServiceImpl implements IGamesService {
Map<String, String> rawMap = new LinkedHashMap<>(); Map<String, String> rawMap = new LinkedHashMap<>();
rawMap.put("merchantId", merchantId); rawMap.put("merchantId", merchantId);
rawMap.put("playerName", playerName); rawMap.put("playerName", playerName);
rawMap.put("extTransId", transactionId); rawMap.put("extTransId", exchangeTransferMoneyRequestDTO.getTransactionId());
rawMap.put("coins", coins); rawMap.put("coins", coins);
String rawData = JSON.toJSONString(rawMap); String rawData = JSON.toJSONString(rawMap);
String data = null; String data = null;
@ -335,7 +326,7 @@ public class MeiTianGameServiceImpl implements IGamesService {
merchantId, merchantId,
playerName, playerName,
coins, coins,
transactionId, exchangeTransferMoneyRequestDTO.getTransactionId(),
md5Code, md5Code,
data data
); );
@ -368,7 +359,7 @@ public class MeiTianGameServiceImpl implements IGamesService {
merchantId, merchantId,
playerName, playerName,
coins, coins,
transactionId, exchangeTransferMoneyRequestDTO.getTransactionId(),
md5Code, md5Code,
data data
); );
@ -473,7 +464,7 @@ public class MeiTianGameServiceImpl implements IGamesService {
boolean doSyncRecordByRecordID(BetRecordByTimeDTO betRecordByTimeDTO) { boolean doSyncRecordByRecordID(BetRecordByTimeDTO betRecordByTimeDTO) {
String configKey = GamePlatforms.MT.getCode() + ":lastSyncRecordID"; String configKey = GamePlatforms.MT.getCode() + ":lastSyncRecordID";
long recordID = redisCache.getCacheObject(configKey); Long recordID = redisCache.getCacheObject(configKey);
//String lastRecordID = sysConfigServiceImpl.selectConfigByKey(configKey); //String lastRecordID = sysConfigServiceImpl.selectConfigByKey(configKey);
/*if (lastRecordID == null || lastRecordID.isEmpty()) { /*if (lastRecordID == null || lastRecordID.isEmpty()) {

View File

@ -37,5 +37,5 @@ public class ApiGameInfoResponseDTO {
/** /**
* id * id
*/ */
private Long systemGameId; private String systemGameId;
} }

View File

@ -13,6 +13,7 @@ import com.ff.base.utils.DateUtils;
import com.ff.base.utils.SleepUtil; import com.ff.base.utils.SleepUtil;
import com.ff.base.utils.StringUtils; import com.ff.base.utils.StringUtils;
import com.ff.base.utils.sign.Md5Utils; import com.ff.base.utils.sign.Md5Utils;
import com.ff.base.utils.uuid.IdUtils;
import com.ff.config.KeyConfig; import com.ff.config.KeyConfig;
import com.ff.game.api.IGamesService; import com.ff.game.api.IGamesService;
import com.ff.game.api.ng.client.NGClient; import com.ff.game.api.ng.client.NGClient;
@ -258,8 +259,14 @@ public class GamesPGServiceImpl implements IGamesService {
gameService.insertGame(game); gameService.insertGame(game);
} else { } else {
game = games.get(0); game = games.get(0);
List<NameInfo> nameInfos = new ArrayList<>();
nameInfos.add(new NameInfo(apiGameInfoResponseDTO.getGameName().get("zh-hans"), "zh-CN"));
nameInfos.add(new NameInfo(apiGameInfoResponseDTO.getGameName().get("zh-hant"), "zh-TW"));
nameInfos.add(new NameInfo(apiGameInfoResponseDTO.getGameName().get("en"), "en-US"));
game.setNameInfo(nameInfos);
gameService.updateGame(game);
} }
apiGameInfoResponseDTO.setSystemGameId(game.getId()); apiGameInfoResponseDTO.setSystemGameId(game.getGameId());
} }
@ -273,6 +280,19 @@ public class GamesPGServiceImpl implements IGamesService {
return CacheConstants.PG_GAMES; return CacheConstants.PG_GAMES;
} }
/**
* id
*
* @param transactionIdRequestDTO iddto
* @return {@link String }
*/
@Override
public String getTransactionId(TransactionIdRequestDTO transactionIdRequestDTO) {
return gameExchangeMoneyService.getTransactionId(GamePlatforms.PG.getCode(), 32);
}
/** /**
* id * id
* *
@ -285,49 +305,27 @@ public class GamesPGServiceImpl implements IGamesService {
log.info("GamesNGServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO); log.info("GamesNGServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO);
Member member = memberService.selectMemberByGameAccount(exchangeTransferMoneyRequestDTO.getAccount()); GameExchangeMoney exchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(exchangeTransferMoneyRequestDTO.getGameExchangeId());
String transactionId = gameExchangeMoneyService.getTransactionId(GamePlatforms.PG.getCode(), 32);
List<GameExchangeMoney> gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList(
GameExchangeMoney.builder()
.tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey())
.orderId(exchangeTransferMoneyRequestDTO.getOrderId())
.build()
);
Assert.isTrue(CollectionUtils.isEmpty(gameExchangeMonies), "订单号重复");
//获取下一个自增id
GameExchangeMoney exchangeMoney = GameExchangeMoney
.builder()
.tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey())
.orderId(exchangeTransferMoneyRequestDTO.getOrderId())
.quota(exchangeTransferMoneyRequestDTO.getQuota())
.balance(exchangeTransferMoneyRequestDTO.getAmount())
.exchangeType(exchangeTransferMoneyRequestDTO.getTransferType())
.currencyCode(exchangeTransferMoneyRequestDTO.getSystemCurrency())
.memberId(member.getId())
.transactionId(transactionId)
.platformCode(GamePlatforms.PG.getCode())
.build();
exchangeMoney.setCreateBy(Constants.SYSTEM);
exchangeMoney.setStatus(StatusType.IN_PROGRESS.getValue());
exchangeMoney.setStep(GameExchangeStep.CREATE_ORDER.getCode());
exchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode());
gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney);
//获取余额 //获取余额
String type = TransferType.ALL.getCode().equals(exchangeTransferMoneyRequestDTO.getTransferType()) ? NGTransferType.TRANSFER_OUT.getValue() : NGTransferType.TRANSFER_IN.getValue(); String type = TransferType.ALL.getCode().equals(exchangeTransferMoneyRequestDTO.getTransferType()) ? NGTransferType.TRANSFER_OUT.getValue() : NGTransferType.TRANSFER_IN.getValue();
//获取当前游戏币 //获取当前游戏币
MemberInfoRequestDTO gamesBaseRequestDTO = MemberInfoRequestDTO.builder() MemberInfoRequestDTO gamesBaseRequestDTO = MemberInfoRequestDTO.builder()
.accounts(member.getGameAccount()) .accounts(exchangeTransferMoneyRequestDTO.getAccount())
.agentId(exchangeTransferMoneyRequestDTO.getAgentId()) .agentId(exchangeTransferMoneyRequestDTO.getAgentId())
.agentKey(exchangeTransferMoneyRequestDTO.getAgentKey()) .agentKey(exchangeTransferMoneyRequestDTO.getAgentKey())
.currency(exchangeTransferMoneyRequestDTO.getCurrency()) .currency(exchangeTransferMoneyRequestDTO.getCurrency())
.build(); .build();
MemberInfoResponseDTO memberInfo = this.getMemberInfo(gamesBaseRequestDTO);
//判断是不是转出 //判断是不是转出
if (NGTransferType.TRANSFER_OUT.getValue().equals(type)) { if (NGTransferType.TRANSFER_OUT.getValue().equals(type)) {
MemberInfoResponseDTO memberInfo = this.getMemberInfo(gamesBaseRequestDTO);
exchangeTransferMoneyRequestDTO.setAmount(memberInfo.getBalance()); exchangeTransferMoneyRequestDTO.setAmount(memberInfo.getBalance());
if (exchangeTransferMoneyRequestDTO.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
throw new ApiException(ErrorCode.INSUFFICIENT_PLAYER_BALANCE.getCode());
}
} }
@ -337,7 +335,7 @@ public class GamesPGServiceImpl implements IGamesService {
paramsMap.put("currency", exchangeTransferMoneyRequestDTO.getCurrency()); paramsMap.put("currency", exchangeTransferMoneyRequestDTO.getCurrency());
paramsMap.put("type", type); paramsMap.put("type", type);
paramsMap.put("amount", exchangeTransferMoneyRequestDTO.getAmount()); paramsMap.put("amount", exchangeTransferMoneyRequestDTO.getAmount());
paramsMap.put("orderId", transactionId); paramsMap.put("orderId", exchangeTransferMoneyRequestDTO.getTransactionId());
Map<String, String> key = this.getKey(exchangeTransferMoneyRequestDTO); Map<String, String> key = this.getKey(exchangeTransferMoneyRequestDTO);
@ -348,6 +346,20 @@ public class GamesPGServiceImpl implements IGamesService {
exchangeMoney.setStep(GameExchangeStep.PLATFORM_TRANSACTION.getCode()); exchangeMoney.setStep(GameExchangeStep.PLATFORM_TRANSACTION.getCode());
exchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode()); exchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode());
gameExchangeMoneyService.updateGameExchangeMoney(exchangeMoney); gameExchangeMoneyService.updateGameExchangeMoney(exchangeMoney);
ExchangeTransferStatusRequestDTO exchangeTransferStatusRequestDTO = new ExchangeTransferStatusRequestDTO();
exchangeTransferStatusRequestDTO.setAccount(exchangeTransferMoneyRequestDTO.getAccount());
exchangeTransferStatusRequestDTO.setCurrency(exchangeTransferMoneyRequestDTO.getCurrency());
exchangeTransferStatusRequestDTO.setOrderId(exchangeTransferMoneyRequestDTO.getTransactionId());
exchangeTransferStatusRequestDTO.setAgentId(exchangeTransferMoneyRequestDTO.getAgentId());
exchangeTransferStatusRequestDTO.setAgentKey(exchangeTransferMoneyRequestDTO.getAgentKey());
ExchangeTransferStatusResponseDTO statusResponseDTO = this.exchangeTransferStatus(exchangeTransferStatusRequestDTO);
//更新钱
exchangeMoney.setBalance(statusResponseDTO.getBalance());
exchangeMoney.setCoinBefore(statusResponseDTO.getCoinBefore());
exchangeMoney.setCoinAfter(statusResponseDTO.getCoinAfter());
exchangeMoney.setCurrencyBefore(exchangeMoney.getCoinBefore());
exchangeMoney.setCurrencyAfter(exchangeMoney.getCoinAfter());
gameExchangeMoneyService.updateGameExchangeMoney(exchangeMoney);
} else { } else {
exchangeMoney.setStep(GameExchangeStep.PLATFORM_TRANSACTION.getCode()); exchangeMoney.setStep(GameExchangeStep.PLATFORM_TRANSACTION.getCode());
exchangeMoney.setStepStatus(GameExchangeStepStatus.FAILURE.getCode()); exchangeMoney.setStepStatus(GameExchangeStepStatus.FAILURE.getCode());
@ -367,6 +379,7 @@ public class GamesPGServiceImpl implements IGamesService {
@Override @Override
public ExchangeTransferStatusResponseDTO exchangeTransferStatus(ExchangeTransferStatusRequestDTO exchangeTransferMoneyRequestDTO) { public ExchangeTransferStatusResponseDTO exchangeTransferStatus(ExchangeTransferStatusRequestDTO exchangeTransferMoneyRequestDTO) {
SleepUtil.sleep(1000);
Map<String, Object> paramsMap = new HashMap<>(); Map<String, Object> paramsMap = new HashMap<>();
paramsMap.put("playerId", exchangeTransferMoneyRequestDTO.getAccount()); paramsMap.put("playerId", exchangeTransferMoneyRequestDTO.getAccount());
@ -385,7 +398,7 @@ public class GamesPGServiceImpl implements IGamesService {
.build(); .build();
ApiExchangeTransferStatusResponseDTO apiNGResponseDTOData = apiNGResponseDTO.getData(); ApiExchangeTransferStatusResponseDTO apiNGResponseDTOData = apiNGResponseDTO.getData();
if (!ObjectUtils.isEmpty(apiNGResponseDTOData)) { if (!ObjectUtils.isEmpty(apiNGResponseDTOData)) {
transferStatusResponseDTO.setBalance(apiNGResponseDTOData.getAmount()); transferStatusResponseDTO.setBalance(apiNGResponseDTOData.getAmount().abs());
transferStatusResponseDTO.setCoinBefore(NumberUtil.sub(apiNGResponseDTOData.getAmount(), apiNGResponseDTOData.getAfterBalance()).abs()); transferStatusResponseDTO.setCoinBefore(NumberUtil.sub(apiNGResponseDTOData.getAmount(), apiNGResponseDTOData.getAfterBalance()).abs());
transferStatusResponseDTO.setCoinAfter(apiNGResponseDTOData.getAfterBalance()); transferStatusResponseDTO.setCoinAfter(apiNGResponseDTOData.getAfterBalance());
} }

View File

@ -15,6 +15,7 @@ import com.ff.base.utils.DateUtils;
import com.ff.base.utils.JsonUtil; import com.ff.base.utils.JsonUtil;
import com.ff.base.utils.StringUtils; import com.ff.base.utils.StringUtils;
import com.ff.base.utils.sign.Base64; import com.ff.base.utils.sign.Base64;
import com.ff.base.utils.uuid.IdUtils;
import com.ff.config.KeyConfig; import com.ff.config.KeyConfig;
import com.ff.game.api.IGamesService; import com.ff.game.api.IGamesService;
import com.ff.game.api.fc.dto.ApiFCGameListResponseDTO; import com.ff.game.api.fc.dto.ApiFCGameListResponseDTO;
@ -243,6 +244,10 @@ public class GamesPGTServiceImpl implements IGamesService {
gameService.insertGame(game); gameService.insertGame(game);
} else { } else {
game = games.get(0); game = games.get(0);
List<NameInfo> nameInfos = new ArrayList<>();
nameInfos.add(NameInfo.builder().lang("en-US").name(gameIdKey.getName()).build());
game.setNameInfo(nameInfos);
gameService.updateGame(game);
} }
gameIdKey.setSystemGameId(game.getGameId()); gameIdKey.setSystemGameId(game.getGameId());
} }
@ -256,7 +261,16 @@ public class GamesPGTServiceImpl implements IGamesService {
} }
return CacheConstants.PGT_GAMES; return CacheConstants.PGT_GAMES;
} }
/**
* id
*
* @param transactionIdRequestDTO iddto
* @return {@link String }
*/
@Override
public String getTransactionId(TransactionIdRequestDTO transactionIdRequestDTO) {
return gameExchangeMoneyService.getTransactionId(GamePlatforms.PGT.getInfo(), 17);
}
/** /**
* id * id
* *
@ -268,39 +282,11 @@ public class GamesPGTServiceImpl implements IGamesService {
public Long exchangeTransferByAgentId(ExchangeTransferMoneyRequestDTO exchangeTransferMoneyRequestDTO) { public Long exchangeTransferByAgentId(ExchangeTransferMoneyRequestDTO exchangeTransferMoneyRequestDTO) {
log.info("GamesPGTServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO); log.info("GamesPGTServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO);
String currency = exchangeTransferMoneyRequestDTO.getCurrency();
Member member = memberService.selectMemberByGameAccount(exchangeTransferMoneyRequestDTO.getAccount()); GameExchangeMoney exchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(exchangeTransferMoneyRequestDTO.getGameExchangeId());
String transactionId = gameExchangeMoneyService.getTransactionId(GamePlatforms.PGX.getInfo(), 17);
List<GameExchangeMoney> gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList(
GameExchangeMoney.builder()
.tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey())
.orderId(exchangeTransferMoneyRequestDTO.getOrderId())
.build()
);
Assert.isTrue(CollectionUtils.isEmpty(gameExchangeMonies), "订单号重复");
//获取下一个自增id
GameExchangeMoney exchangeMoney = GameExchangeMoney
.builder()
.tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey())
.orderId(exchangeTransferMoneyRequestDTO.getOrderId())
.quota(exchangeTransferMoneyRequestDTO.getQuota())
.balance(exchangeTransferMoneyRequestDTO.getAmount())
.exchangeType(exchangeTransferMoneyRequestDTO.getTransferType())
.currencyCode(currency)
.memberId(member.getId())
.transactionId(transactionId)
.platformCode(GamePlatforms.PGT.getInfo())
.build();
exchangeMoney.setCreateBy(Constants.SYSTEM);
exchangeMoney.setStatus(StatusType.IN_PROGRESS.getValue());
exchangeMoney.setStep(GameExchangeStep.CREATE_ORDER.getCode());
exchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode());
gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney);
BigDecimal amount = exchangeTransferMoneyRequestDTO.getAmount(); BigDecimal amount = exchangeTransferMoneyRequestDTO.getAmount();
BigDecimal amountBefore = BigDecimal.ZERO; BigDecimal amountBefore = BigDecimal.ZERO;
@ -322,7 +308,7 @@ public class GamesPGTServiceImpl implements IGamesService {
Map<String, Object> paramsMap = new LinkedHashMap<>(); Map<String, Object> paramsMap = new LinkedHashMap<>();
paramsMap.put("username", exchangeTransferMoneyRequestDTO.getAccount()); paramsMap.put("username", exchangeTransferMoneyRequestDTO.getAccount());
paramsMap.put("amount", amount.setScale(2, RoundingMode.DOWN).toString()); paramsMap.put("amount", amount.setScale(2, RoundingMode.DOWN).toString());
paramsMap.put("transactionRef", transactionId); paramsMap.put("transactionRef", exchangeTransferMoneyRequestDTO.getTransactionId());
paramsMap.put("productId", productId); paramsMap.put("productId", productId);
Map<String, String> key = this.getKey(exchangeTransferMoneyRequestDTO); Map<String, String> key = this.getKey(exchangeTransferMoneyRequestDTO);
PGTExchangeTransferResponse errorResponse; PGTExchangeTransferResponse errorResponse;
@ -636,7 +622,12 @@ public class GamesPGTServiceImpl implements IGamesService {
List<PGTGameListResponse.Game> gamesDatas = redisCache.getCacheList(CacheConstants.PGT_GAMES); List<PGTGameListResponse.Game> gamesDatas = redisCache.getCacheList(CacheConstants.PGT_GAMES);
Map<String, PGTGameListResponse.Game> dataDTOMap = gamesDatas.stream().collect(Collectors.toMap(PGTGameListResponse.Game::getCode, e -> e)); Map<String, PGTGameListResponse.Game> dataDTOMap = gamesDatas.stream().collect(Collectors.toMap(PGTGameListResponse.Game::getCode, e -> e));
PGTGameListResponse.Game gamesDataDTO = dataDTOMap.get(resultBean.getGameCode()); PGTGameListResponse.Game gamesDataDTO = dataDTOMap.get(resultBean.getGameCode());
Integer gameStatus =GameStatus.FLAT.getCode();
if (resultBean.getPayout().compareTo(resultBean.getStake())>0){
gameStatus=GameStatus.WIN.getCode();
}else if (resultBean.getPayout().compareTo(resultBean.getStake())<0){
gameStatus=GameStatus.FAIL.getCode();
}
//数据构造 //数据构造
GameBettingDetails gameBettingDetails = GameBettingDetails.builder() GameBettingDetails gameBettingDetails = GameBettingDetails.builder()
@ -650,7 +641,7 @@ public class GamesPGTServiceImpl implements IGamesService {
//.gameId(gamesDataDTO.getSystemGameId()) //.gameId(gamesDataDTO.getSystemGameId())
.gameId(gamesDataDTO.getSystemGameId()) .gameId(gamesDataDTO.getSystemGameId())
.gameName(gamesDataDTO.getName()) .gameName(gamesDataDTO.getName())
.gameStatus(PGTPayoutStatus.getByCode(resultBean.getPayoutStatus()).getSystemCode()) .gameStatus(gameStatus)
.gameStatusType(1) .gameStatusType(1)
.gameCurrencyCode(resultBean.getCurrency()) .gameCurrencyCode(resultBean.getCurrency())
.account(resultBean.getUsername()) .account(resultBean.getUsername())

View File

@ -56,7 +56,7 @@ public interface PGXClient {
* @param parameters * @param parameters
* @return {@link PGXGameLoginResponse } * @return {@link PGXGameLoginResponse }
*/ */
@Post("/launchGames.aspx?${parameters}") @Get("/launchGames.aspx?${parameters}")
PGXGameLoginResponse loginWithoutRedirect(@Var("parameters") String parameters); PGXGameLoginResponse loginWithoutRedirect(@Var("parameters") String parameters);
/** /**

View File

@ -79,13 +79,13 @@ public class PGXBetHistoryResponse {
* () GMT/UTC +0 * () GMT/UTC +0
*/ */
@JsonProperty("start_time") @JsonProperty("start_time")
private Date startTime; private String startTime;
/** /**
* (String) GMT/UTC +0 * (String) GMT/UTC +0
*/ */
@JsonProperty("end_time") @JsonProperty("end_time")
private Date endTime; private String endTime;
/** /**
* (String) GMT/UTC +0 * (String) GMT/UTC +0

View File

@ -251,6 +251,10 @@ public class GamesPGXServiceImpl implements IGamesService {
gameService.insertGame(game); gameService.insertGame(game);
} else { } else {
game = games.get(0); game = games.get(0);
List<NameInfo> nameInfos = new ArrayList<>();
nameInfos.add(new NameInfo(gamesDataDTO.getGameName(), "en-US"));
game.setNameInfo(nameInfos);
gameService.updateGame(game);
} }
gamesDataDTO.setSystemGameId(game.getGameId()); gamesDataDTO.setSystemGameId(game.getGameId());
@ -278,35 +282,9 @@ public class GamesPGXServiceImpl implements IGamesService {
log.info("GamesPGXServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO); log.info("GamesPGXServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO);
Member member = memberService.selectMemberByGameAccount(exchangeTransferMoneyRequestDTO.getAccount()); GameExchangeMoney exchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(exchangeTransferMoneyRequestDTO.getGameExchangeId());
String transactionId = gameExchangeMoneyService.getTransactionId(GamePlatforms.PGX.getInfo(), 17);
List<GameExchangeMoney> gameExchangeMonies = gameExchangeMoneyService.selectGameExchangeMoneyList(
GameExchangeMoney.builder()
.tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey())
.orderId(exchangeTransferMoneyRequestDTO.getOrderId())
.build()
);
Assert.isTrue(CollectionUtils.isEmpty(gameExchangeMonies), "订单号重复");
//获取下一个自增id
GameExchangeMoney exchangeMoney = GameExchangeMoney
.builder()
.tenantKey(exchangeTransferMoneyRequestDTO.getTenantKey())
.orderId(exchangeTransferMoneyRequestDTO.getOrderId())
.quota(exchangeTransferMoneyRequestDTO.getQuota())
.balance(exchangeTransferMoneyRequestDTO.getAmount())
.exchangeType(exchangeTransferMoneyRequestDTO.getTransferType())
.currencyCode(exchangeTransferMoneyRequestDTO.getSystemCurrency())
.memberId(member.getId())
.transactionId(transactionId)
.platformCode(GamePlatforms.PGX.getInfo())
.build();
exchangeMoney.setCreateBy(Constants.SYSTEM);
exchangeMoney.setStatus(StatusType.IN_PROGRESS.getValue());
exchangeMoney.setStep(GameExchangeStep.CREATE_ORDER.getCode());
exchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode());
gameExchangeMoneyService.insertGameExchangeMoney(exchangeMoney);
//获取余额 //获取余额
String type = TransferType.ALL.getCode().equals(exchangeTransferMoneyRequestDTO.getTransferType()) ? PGXTransferType.WITHDRAW.getCode() : PGXTransferType.DEPOSIT.getCode(); String type = TransferType.ALL.getCode().equals(exchangeTransferMoneyRequestDTO.getTransferType()) ? PGXTransferType.WITHDRAW.getCode() : PGXTransferType.DEPOSIT.getCode();
@ -339,7 +317,7 @@ public class GamesPGXServiceImpl implements IGamesService {
paramsMap.put("operatorcode", exchangeTransferMoneyRequestDTO.getAgentId()); paramsMap.put("operatorcode", exchangeTransferMoneyRequestDTO.getAgentId());
paramsMap.put("password", keyInfo.getPassword()); paramsMap.put("password", keyInfo.getPassword());
paramsMap.put("providercode", keyInfo.getProviderCode()); paramsMap.put("providercode", keyInfo.getProviderCode());
paramsMap.put("referenceid", transactionId); paramsMap.put("referenceid", exchangeTransferMoneyRequestDTO.getTransactionId());
paramsMap.put("type", type); paramsMap.put("type", type);
paramsMap.put("username", exchangeTransferMoneyRequestDTO.getAccount()); paramsMap.put("username", exchangeTransferMoneyRequestDTO.getAccount());
String key = this.getKey(paramsMap, exchangeTransferMoneyRequestDTO); String key = this.getKey(paramsMap, exchangeTransferMoneyRequestDTO);
@ -456,6 +434,21 @@ public class GamesPGXServiceImpl implements IGamesService {
} }
} }
/**
* id
*
* @param transactionIdRequestDTO iddto
* @return {@link String }
*/
@Override
public String getTransactionId(TransactionIdRequestDTO transactionIdRequestDTO) {
return gameExchangeMoneyService.getTransactionId(GamePlatforms.PGX.getInfo(), 17);
}
/** /**
* *
* *
@ -611,6 +604,7 @@ public class GamesPGXServiceImpl implements IGamesService {
payoffAmount = NumberUtil.sub(payout, resultBean.getBet()).negate(); payoffAmount = NumberUtil.sub(payout, resultBean.getBet()).negate();
gameStatus = GameStatus.FAIL.getCode(); gameStatus = GameStatus.FAIL.getCode();
} }
long endTime = DateUtils.convertToMillisWithTimezone(resultBean.getEndTime(), "UTC");
//数据构造 //数据构造
GameBettingDetails gameBettingDetails = GameBettingDetails.builder() GameBettingDetails gameBettingDetails = GameBettingDetails.builder()
.tenantKey(member.getTenantKey()) .tenantKey(member.getTenantKey())
@ -628,11 +622,11 @@ public class GamesPGXServiceImpl implements IGamesService {
.gameCurrencyCode(/*currencyDTO.getCurrency()*/gamesDataBuildDTO.getCurrencyCode()) .gameCurrencyCode(/*currencyDTO.getCurrency()*/gamesDataBuildDTO.getCurrencyCode())
.account(resultBean.getMember()) .account(resultBean.getMember())
.wagersId(String.valueOf(resultBean.getId())) .wagersId(String.valueOf(resultBean.getId()))
.wagersTime(resultBean.getStartTime().getTime()) .wagersTime(DateUtils.convertToMillisWithTimezone(resultBean.getStartTime(),"UTC"))
.betAmount(resultBean.getBet()) .betAmount(resultBean.getBet())
.payoffTime(resultBean.getEndTime().getTime()) .payoffTime(endTime)
.payoffAmount(payoffAmount) .payoffAmount(payoffAmount)
.settlementTime(resultBean.getEndTime().getTime()) .settlementTime(endTime)
.turnover(resultBean.getTurnover()) .turnover(resultBean.getTurnover())
.settlementStatus(PGXBetRecordStatus.findSystemCodeByCode(resultBean.getStatus())) .settlementStatus(PGXBetRecordStatus.findSystemCodeByCode(resultBean.getStatus()))
.build(); .build();

View File

@ -0,0 +1,35 @@
package com.ff.game.api.pp.address;
import com.dtflys.forest.callback.AddressSource;
import com.dtflys.forest.http.ForestAddress;
import com.dtflys.forest.http.ForestRequest;
import com.ff.base.enums.GamePlatforms;
import com.ff.game.domain.Platform;
import com.ff.game.service.IPlatformService;
import com.sun.media.jfxmediaimpl.platform.PlatformManager;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* jili address
*
* @author shi
* @date 2025/02/10
*/
@Component
public class MyPPAddressSource implements AddressSource {
@Resource
private IPlatformService platformService;
@Override
public ForestAddress getAddress(ForestRequest request) {
Platform platform = platformService.get(GamePlatforms.PP.getCode());
String apiBaseUrl = platform.getUrlInfo().getUrl();
String host = platform.getUrlInfo().getHost();
String https = platform.getUrlInfo().getHttps();
return new ForestAddress(https, apiBaseUrl, Integer.parseInt(host), "/IntegrationService/v3");
}
}

View File

@ -0,0 +1,121 @@
package com.ff.game.api.pp.client;
import com.dtflys.forest.annotation.*;
import com.ff.game.api.pp.address.MyPPAddressSource;
import com.ff.game.api.pp.dto.*;
import com.ff.game.api.pp.forest.MySuccessCondition;
import java.util.Map;
/**
* pp
*
* @author shi
* @date 2025/02/10
*/
@Address(source = MyPPAddressSource.class)
public interface PPClient {
/**
*
*
* @param params
* @return {@link PPUserAccountResponse }
*/
@Post( url ="/http/CasinoGameAPI/player/account/create/",
headers = {
"Content-type: application/x-www-form-urlencoded"
})
PPUserAccountResponse createMember(@Body Map<String, Object> params);
/**
*
*
* @param params
* @return {@link PPPlayerAccountResponse }
*/
@Post( url ="/http/CasinoGameAPI/balance/current/",
headers = {
"Content-type: application/x-www-form-urlencoded"
})
PPPlayerAccountResponse getMemberInfo(@Body Map<String, Object> params);
/**
*
*
* @param params
* @return {@link PPGameLaunchResponse }
*/
@Post(url ="/http/CasinoGameAPI/game/start/",
headers = {
"Content-type: application/x-www-form-urlencoded"
})
PPGameLaunchResponse loginWithoutRedirect(@Body Map<String, Object> params);
/**
*
*
* @param params
* @return {@link PPGameResponseDTO }
*/
@Post( url ="/http/CasinoGameAPI/getCasinoGames/",
headers = {
"Content-type: application/x-www-form-urlencoded"
})
PPGameResponseDTO getGameList(@Body Map<String, Object> params);
/**
* id
*
* @param params
* @return {@link PPTransactionResponse }
*/
@Post(url = "/http/CasinoGameAPI/balance/transfer/",
headers = {
"Content-type: application/x-www-form-urlencoded"
})
@Success(condition = MySuccessCondition.class)
PPTransactionResponse exchangeTransfer(@Body Map<String, Object> params);
/**
*
*
* @param params
* @return {@link PPTransactionStatusResponse }
*/
@Post(url = "/http/CasinoGameAPI/balance/transfer/status/",
headers = {
"Content-type: application/x-www-form-urlencoded"
})
PPTransactionStatusResponse exchangeTransferStatus( @Body Map<String, Object> params);
/**
*
*
* @param params
* @return {@link String }
*/
@Get(url ="/DataFeeds/gamerounds/finished/?{params}")
String getBetRecordByTime(@Var("params") String params);
/**
*
*
* @param params
* @return {@link PPResponse }
*/
@Post(url = "/http/CasinoGameAPI/game/session/terminate/",
headers = {
"Content-type: application/x-www-form-urlencoded"
})
PPResponse kickMember(@Body Map<String, Object> params);
}

View File

@ -0,0 +1,129 @@
package com.ff.game.api.pp.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
* dgbet
*
* @author shi
* @date 2025/03/27
*/
@Data
public class DGBetRecordResponseDTO {
/** 错误码 (参考文档定义) */
@JsonProperty("codeId")
private Integer codeId;
/** 错误信息 */
@JsonProperty("msg")
private String msg;
/** 注单报告 */
@JsonProperty("list")
private List<ReportDTO> list;
/**
*
*/
@Data
public static class ReportDTO {
/** 注单ID唯一 */
@JsonProperty("id")
private Long id;
/** 游戏桌号(红包小费记录没有) */
@JsonProperty("tableId")
private Integer tableId;
/** 游戏靴号(红包小费记录没有) */
@JsonProperty("shoeId")
private Long shoeId;
/** 当靴局号(红包小费记录没有) */
@JsonProperty("playId")
private Long playId;
/** 游戏厅号1:旗舰厅2:亚洲厅34:现场厅5:性感厅8,9:区块链厅) */
@JsonProperty("lobbyId")
private Integer lobbyId;
/** 注单类型1:注单2:红包小费) */
@JsonProperty("gameType")
private Integer gameType;
/** 游戏类型(百家乐,龙虎等) */
@JsonProperty("gameId")
private Integer gameId;
/** 下注时间 */
@JsonProperty("betTime")
private Date betTime;
/** 结算时间 */
@JsonProperty("calTime")
private Date calTime;
/** 派彩金额(含本金) */
@JsonProperty("winOrLoss")
private BigDecimal winOrLoss;
/** 下注前余额(仅作参考) */
@JsonProperty("balanceBefore")
private BigDecimal balanceBefore;
/** 下注金额(下注扣款金额) */
@JsonProperty("betPoints")
private BigDecimal betPoints;
/** 洗码金额(用于计算佣金) */
@JsonProperty("availableBet")
private BigDecimal availableBet;
/** 会员账号 */
@JsonProperty("userName")
private String userName;
/** 游戏结果 */
@JsonProperty("result")
private String result;
/** 注单详情 */
@JsonProperty("betDetail")
private String betDetail;
/** 客户端IP */
@JsonProperty("ip")
private String ip;
/** 游戏唯一局号 */
@JsonProperty("ext")
private String ext;
/** 结算状态0:未结算1:已结算2:已撤销3:冻结) */
@JsonProperty("isRevocation")
private Integer isRevocation;
/** 更改单时对应的注单记录 */
@JsonProperty("parentBetId")
private Long parentBetId;
/** 币种ID请参考对应关系说明 */
@JsonProperty("currencyId")
private Integer currencyId;
/** 客户端平台ID1: PC 2: 安卓 3: 苹果 5: H5 */
@JsonProperty("deviceType")
private Integer deviceType;
/** 钱包扣款记录转账模式API没有 */
@JsonProperty("transfers")
private String transfers;
}
}

View File

@ -0,0 +1,74 @@
package com.ff.game.api.pp.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
/**
*
*/
@Data
public class DGLoginWithoutRedirectResponse {
/**
* ID
*/
@JsonProperty("codeId")
private int codeId;
/**
*
*/
@JsonProperty("msg")
private String msg;
/**
* token
*/
@JsonProperty("token")
private String token;
/**
*
*/
@JsonProperty("domains")
private String domains;
/**
*
*/
@JsonProperty("list")
private List<String> list;
/**
*
*/
@JsonProperty("limitGroup")
private String limitGroup;
/**
*
*/
@JsonProperty("limits")
private List<Limit> limits;
/**
*
*/
@Data
public static class Limit {
/**
*
*/
@JsonProperty("min")
private int min;
/**
*
*/
@JsonProperty("max")
private int max;
}
}

View File

@ -0,0 +1,26 @@
package com.ff.game.api.pp.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
*
*
* @author shi
* @date 2025/03/26
*/
@Data
public class DGResponse {
/**
* ID
*/
@JsonProperty("codeId")
private int codeId;
/**
*
*/
@JsonProperty("msg")
private String msg;
}

View File

@ -0,0 +1,45 @@
package com.ff.game.api.pp.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
*
*
* @author shi
* @date 2025/03/27
*/
@Data
public class DGTransactionResponseDTO {
/** 响应代码 */
@JsonProperty("codeId")
private Integer codeId;
/** 响应消息 */
@JsonProperty("msg")
private String msg;
/** 用户名 */
@JsonProperty("username")
private String username;
/** 交易金额 */
@JsonProperty("amount")
private BigDecimal amount;
/** 账户余额 */
@JsonProperty("balance")
private BigDecimal balance;
/** 交易流水号 */
@JsonProperty("serial")
private String serial;
/** 交易时间 */
@JsonProperty("time")
private String time;
}

View File

@ -0,0 +1,40 @@
package com.ff.game.api.pp.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
*
*
* @author shi
* @date 2025/03/26
*/
@Data
public class DGUserAccountResponse {
/**
* ID
*/
@JsonProperty("codeId")
private int codeId;
/**
*
*/
@JsonProperty("msg")
private String msg;
/**
*
*/
@JsonProperty("username")
private String username;
/**
*
*/
@JsonProperty("balance")
private BigDecimal balance;
}

View File

@ -0,0 +1,70 @@
package com.ff.game.api.pp.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
/**
*
*
* @author shi
* @date 2025/03/27
*/
@Data
public class DGUserListResponseDTO {
/**
* ID
*/
@JsonProperty("codeId")
private int codeId;
/**
*
*/
@JsonProperty("msg")
private String msg;
/** 用户列表 */
@JsonProperty("list")
private List<UserDTO> list;
/**
*
*/
@Data
public static class UserDTO {
/** 用户名 */
@JsonProperty("username")
private String username;
/** 昵称 */
@JsonProperty("nickname")
private String nickname;
/** 币种名称 */
@JsonProperty("currencyName")
private String currencyName;
/** 用户IP */
@JsonProperty("ip")
private String ip;
/** 用户设备 */
@JsonProperty("device")
private String device;
/** 登录时间 */
@JsonProperty("login")
private String login;
/** 会员ID */
@JsonProperty("memberId")
private Long memberId;
/** 用户余额 */
@JsonProperty("balance")
private Double balance;
}
}

View File

@ -0,0 +1,35 @@
package com.ff.game.api.pp.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
* ppgame
*
* @author shi
* @date 2025/04/14
*/
@Data
public class PPGameLaunchResponse {
/**
*
* : "0"
*/
@JsonProperty("error")
private String error;
/**
*
* : "OK"
*/
@JsonProperty("description")
private String description;
/**
* URL
* token
*/
@JsonProperty("gameURL")
private String gameUrl;
}

View File

@ -0,0 +1,111 @@
package com.ff.game.api.pp.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.List;
/**
* -
*
* @author shi
* @date 2025/03/27
*/
@Data
public class PPGameResponseDTO {
/** 错误码 (参考文档定义) */
@JsonProperty("error")
private String error;
/** 错误信息 */
@JsonProperty("description")
private String description;
/** 游戏信息列表 */
@JsonProperty("gameList")
private List<CasinoGame> gameList;
/**
*
*/
@Data
public static class CasinoGame {
/** 游戏唯一标识符 */
@JsonProperty("gameID")
private String gameID;
/** 游戏名称 */
@JsonProperty("gameName")
private String gameName;
/** 游戏类型标识符 */
@JsonProperty("gameTypeID")
private String gameTypeID;
/** 游戏类型描述 */
@JsonProperty("typeDescription")
private String typeDescription;
/** 游戏技术描述 */
@JsonProperty("technology")
private String technology;
/** 游戏支持的平台 */
@JsonProperty("platform")
private String platform;
/** 是否提供演示游戏 */
@JsonProperty("demoGameAvailable")
private boolean demoGameAvailable;
/** 游戏宽高比 */
@JsonProperty("aspectRatio")
private String aspectRatio;
/** 游戏技术标识符 */
@JsonProperty("technologyID")
private String technologyID;
/** 数值型游戏 ID */
@JsonProperty("gameIdNumeric")
private Long gameIdNumeric;
/** 是否提供免费回合奖励 */
@JsonProperty("frbAvailable")
private boolean frbAvailable;
/** 是否提供可变免费回合奖励 */
@JsonProperty("variableFrbAvailable")
private boolean variableFrbAvailable;
/** 游戏的投注线数 */
@JsonProperty("lines")
private Integer lines;
/** 游戏支持的功能列表 */
@JsonProperty("features")
private List<String> features;
/** 游戏数据类型 */
@JsonProperty("dataType")
private String dataType;
/** 支持的司法管辖区列表 */
@JsonProperty("jurisdictions")
private List<String> jurisdictions;
/**
* id
*/
private String systemGameId;
/**
*
*/
private Integer systemPlatformType;
}
}

View File

@ -0,0 +1,279 @@
package com.ff.game.api.pp.dto;
import com.ff.base.utils.DateUtils;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* ppgame
*
* @author shi
* @date 2025/04/15
*/
@Data
public class PPGameRoundRecord {
private static final DateTimeFormatter DATE_FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
/**
* Unix
* <p> timepoint=1618298161139</p>
*/
private Long timepoint;
/**
* Pragmatic PlayID
*
* @example 531288
*/
private String playerID;
/**
* ID
*
* @example 889325
*/
private String extPlayerID;
/**
*
*
* @example "vs20magicpot"
*/
private String gameID;
/**
* ID
* <p></p>
*
* @example 50994065
*/
private String playSessionID;
/**
* ID
* <p>ID</p>
*
* @example 50994064
*/
private String parentSessionID;
/**
*
* <p>yyyy-MM-dd HH:mm:ss</p>
*
* @example "2021-04-13 07:06:18"
*/
private Long startDate;
/**
*
* <p>nullyyyy-MM-dd HH:mm:ss</p>
*
* @example "2021-04-13 07:06:18"
*/
private Long endDate;
/**
*
* <p>
* <ul>
* <li>C - </li>
* <li>F - /</li>
* </ul>
* </p>
*
* @example "C"
*/
private String status;
/**
*
* <p>
* <ul>
* <li>F - </li>
* </ul>
* </p>
*
* @example "F"
*/
private String type;
/**
* 2
*
* @example 0.00
*/
private BigDecimal bet;
/**
* 2
*
* @example 0.00
*/
private BigDecimal win;
/**
* ISO 3
*
* @example "EUR"
*/
private String currency;
/**
* 2
*
* @example 0.00
*/
private BigDecimal jackpot;
/**
* ID
* <p>"null"</p>
*
* @example "null"
*/
private String bonusCode;
/**
* 2
*
* @example 0.00
*/
private BigDecimal bonusBet;
/**
* 2
*
* @example 0.00
*/
private BigDecimal bonusWin;
public static List<PPGameRoundRecord> parse(String data) {
List<PPGameRoundRecord> transactions = new ArrayList<>();
// 按行分割数据
String[] lines = data.split("\n");
if (lines.length < 3) {
return new ArrayList<>();
}
// 解析列名(第二行)
String[] headers = lines[1].trim().split(",");
for (int j = 2; j < lines.length; j++) {
// 解析数据行(第三行开始)
String[] values = lines[j].trim().split(",");
// 确保列数和值数匹配
if (headers.length != values.length) {
continue;
}
// 创建交易记录对象
PPGameRoundRecord transaction = new PPGameRoundRecord();
// 根据列名设置对应的值
for (int i = 0; i < headers.length; i++) {
String header = headers[i].trim();
String value = values[i].trim();
switch (header) {
case "playerID":
transaction.setPlayerID(value);
break;
case "extPlayerID":
transaction.setExtPlayerID(value);
break;
case "gameID":
transaction.setGameID(value);
break;
case "playSessionID":
transaction.setPlaySessionID(value);
break;
case "parentSessionID":
transaction.setParentSessionID(value);
break;
case "startDate":
transaction.setStartDate(DateUtils.toTimestamp(value, DateUtils.YYYY_MM_DD_HH_MM_SS));
break;
case "endDate":
transaction.setEndDate(DateUtils.toTimestamp(value, DateUtils.YYYY_MM_DD_HH_MM_SS));
break;
case "status":
transaction.setStatus(value);
break;
case "type":
transaction.setType(value);
break;
case "bet":
transaction.setBet(new BigDecimal(value));
break;
case "win":
transaction.setWin(new BigDecimal(value));
break;
case "currency":
transaction.setCurrency(value);
break;
case "jackpot":
transaction.setJackpot(new BigDecimal(value));
break;
case "bonusCode":
transaction.setBonusCode("null".equals(value) ? null : value);
break;
case "bonusBet":
transaction.setBonusBet(new BigDecimal(value));
break;
case "bonusWin":
transaction.setBonusWin(new BigDecimal(value));
break;
}
}
transactions.add(transaction);
}
return transactions;
}
/**
*
*
* @param s s
* @return {@link Long }
*/// 辅助解析方法
private static Long parseLong(String s) {
return s.isEmpty() ? null : Long.parseLong(s);
}
/**
*
*
* @param s s
* @return {@link BigDecimal }
*/
private static BigDecimal parseDouble(String s) {
return s.isEmpty() ? null : new BigDecimal(s);
}
/**
*
*
* @param s s
* @return {@link LocalDateTime }
*/
private static Date parseDateTime(String s) {
return s.isEmpty() ? null : DateUtils.parseDate(s);
}
}

View File

@ -0,0 +1,35 @@
package com.ff.game.api.pp.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
*
*/
@Data
public class PPPlayerAccountResponse {
/**
* ()
* : "0"
*/
@JsonProperty("error")
private String error;
/**
* ()
* : "OK"
*/
@JsonProperty("description")
private String description;
/**
* ()
* : 999.99
*/
@JsonProperty("balance")
private BigDecimal balance;
}

View File

@ -0,0 +1,30 @@
package com.ff.game.api.pp.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
* ppgame
*
* @author shi
* @date 2025/04/14
*/
@Data
public class PPResponse {
/**
*
* : "0"
*/
@JsonProperty("error")
private String error;
/**
*
* : "OK"
*/
@JsonProperty("description")
private String description;
}

View File

@ -0,0 +1,43 @@
package com.ff.game.api.pp.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
*
*
* @author shi
* @date 2025/04/14
*/
@Data
public class PPTransactionResponse {
/**
* ()
* : "0"
*/
@JsonProperty("error")
private String error;
/**
* ()
* : "OK"
*/
@JsonProperty("description")
private String description;
/**
* ID ()
* : 1908759
*/
@JsonProperty("transactionId")
private String transactionId;
/**
* ()
* : 999.99
*/
@JsonProperty("balance")
private BigDecimal balance;
}

View File

@ -0,0 +1,90 @@
package com.ff.game.api.pp.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
*
*
* @author shi
* @date 2025/04/14
*/
@Data
public class PPTransactionStatusResponse {
/**
*
* <p>
*
* <ul>
* <li>"0" - </li>
* <li> - </li>
* </ul>
* </p>
*
* @apiNote
* @example "0"
*/
@JsonProperty("error")
private String error;
/**
*
* <p></p>
*
* @apiNote
* @example "OK"
*/
@JsonProperty("description")
private String description;
/**
*
* <p></p>
*
* @apiNote
* @example 1908759
*/
@JsonProperty("transactionId")
private Long transactionId;
/**
*
* <p>
*
* <ul>
* <li>"Success" - </li>
* <li>"Pending" - </li>
* <li>"Failed" - </li>
* </ul>
* </p>
*
* @apiNote
* @example "Success"
*/
@JsonProperty("status")
private String status;
/**
*
* <p>
*
* </p>
*
* @apiNote
* @example "999.99"
*/
@JsonProperty("amount")
private BigDecimal amount;
/**
*
* <p>使BigDecimal</p>
*
* @apiNote null
* @example 999.99
*/
@JsonProperty("balance")
private BigDecimal balance;
}

View File

@ -0,0 +1,33 @@
package com.ff.game.api.pp.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
*
* -
*/
@Data
public class PPUserAccountResponse {
/**
* ()
* : "0"
*/
@JsonProperty("error")
private String error;
/**
* ()
* : "OK"
*/
@JsonProperty("description")
private String description;
/**
* ()
* : 6749178
*/
@JsonProperty("playerId")
private Long playerId;
}

View File

@ -0,0 +1,31 @@
package com.ff.game.api.pp.forest;
import com.dtflys.forest.callback.SuccessWhen;
import com.dtflys.forest.http.ForestRequest;
import com.dtflys.forest.http.ForestResponse;
/**
* kmsuccess
*
* @author shi
* @date 2025/04/02
*/
public class MySuccessCondition implements SuccessWhen {
/**
*
* @param req Forest
* @param res Forest
* @return true: false:
*/
@Override
public boolean successWhen(ForestRequest req, ForestResponse res) {
// req 为Forest请求对象即 ForestRequest 类实例
// res 为Forest响应对象即 ForestResponse 类实例
// 返回值为 ture 则表示请求成功false 表示请求失败
return res.noException();
// 当然在这里也可以写其它条件,比如 通过 res.getResult() 或 res.getContent() 获取业务数据
// 再根据业务数据判断是否成功
}
}

View File

@ -0,0 +1,645 @@
package com.ff.game.api.pp.impl;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import com.ff.base.constant.CacheConstants;
import com.ff.base.constant.Constants;
import com.ff.base.core.redis.RedisCache;
import com.ff.base.enums.*;
import com.ff.base.exception.base.ApiException;
import com.ff.base.exception.base.BaseException;
import com.ff.base.utils.DateUtils;
import com.ff.base.utils.JsonUtil;
import com.ff.base.utils.StringUtils;
import com.ff.base.utils.sign.Md5Utils;
import com.ff.game.api.IGamesService;
import com.ff.game.api.pp.client.PPClient;
import com.ff.game.api.pp.dto.*;
import com.ff.game.api.request.*;
import com.ff.game.domain.*;
import com.ff.game.service.IGameBettingDetailsService;
import com.ff.game.service.IGameExchangeMoneyService;
import com.ff.game.service.IGameFreeRecordService;
import com.ff.game.service.IGameService;
import com.ff.member.domain.Member;
import com.ff.member.service.IMemberService;
import com.ff.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
* DG impl
*
* @author shi
* @date 2024/11/12
*/
@Service("PPService")
@Slf4j
public class GamesPPServiceImpl implements IGamesService {
@Resource
private RedisCache gRedisCache;
@Resource
private IGameService gameService;
@Resource
private IMemberService memberService;
@Resource
private IGameFreeRecordService gameFreeRecordService;
@Resource
private PPClient ppClient;
@Resource
private IGameBettingDetailsService gameBettingDetailsService;
@Resource
private IGameExchangeMoneyService gameExchangeMoneyService;
/**
*
*
* @param errorCode
* @return {@link Boolean }
*/
private Boolean getIsSuccess(String errorCode) {
ApiException.isTrue(!"7".equals(errorCode), ErrorCode.INSUFFICIENT_PLAYER_BALANCE.getCode());
return "0".equals(errorCode);
}
/**
*
*
* @param gamesBaseRequestDTO dto
* @return {@link String }
*/
private String getKey(GamesBaseRequestDTO gamesBaseRequestDTO) {
//取出对应的key跟密钥跟请求参数
String agentKey = gamesBaseRequestDTO.getAgentKey();
return Md5Utils.md5New(gamesBaseRequestDTO.getQuery() + agentKey);
}
/**
* ingress
*
* @param terminalTypes
* @return {@link Integer }
*/
public Integer convertToIngress(String terminalTypes) {
if (terminalTypes == null || terminalTypes.isEmpty()) {
return null;
}
boolean hasMobile = terminalTypes.contains("MOBILE");
boolean hasWeb = terminalTypes.contains("WEB");
if (hasMobile && hasWeb) {
return IngressType.PC_AND_MOBILE_WEB.getValue();
} else if (hasMobile) {
return IngressType.MOBILE_WEB.getValue();
} else if (hasWeb) {
return IngressType.PC_WEB.getValue();
} else {
return null;
}
}
/**
*
*
* @param createMemberRequestDTO dto
* @return {@link Boolean }
*/
@Override
public Boolean createMember(CreateMemberRequestDTO createMemberRequestDTO) {
log.info("GamesPPServiceImpl [createMember] 请求参数 {}", createMemberRequestDTO);
Map<String, Object> params = new TreeMap<>();
params.put("externalPlayerId", createMemberRequestDTO.getAccount());
params.put("secureLogin", createMemberRequestDTO.getAgentId());
params.put("currency", createMemberRequestDTO.getCurrency());
String query = JsonUtil.mapToQueryString(params);
createMemberRequestDTO.setQuery(query);
String key = this.getKey(createMemberRequestDTO);
params.put("hash", key);
PPUserAccountResponse member = ppClient.createMember(params);
if (this.getIsSuccess(member.getError())) {
return Boolean.TRUE;
}
//判断是否获取成功
return Boolean.FALSE;
}
/**
*
*
* @param memberInfoRequestDTO dto
* @return {@link MemberInfoResponseDTO }
*/
@Override
public MemberInfoResponseDTO getMemberInfo(MemberInfoRequestDTO memberInfoRequestDTO) {
log.info("GamesPPServiceImpl [loginWithoutRedirect] 请求参数 {}", memberInfoRequestDTO);
Map<String, Object> params = new TreeMap<>();
params.put("secureLogin", memberInfoRequestDTO.getAgentId());
params.put("externalPlayerId", memberInfoRequestDTO.getAccounts());
String query = JsonUtil.mapToQueryString(params);
memberInfoRequestDTO.setQuery(query);
String key = this.getKey(memberInfoRequestDTO);
params.put("hash", key);
PPPlayerAccountResponse memberInfo = ppClient.getMemberInfo(params);
if (this.getIsSuccess(memberInfo.getError())) {
return MemberInfoResponseDTO.builder().account(memberInfoRequestDTO.getAccounts())
.balance(memberInfo.getBalance())
.status(GameMemberStatus.UNKNOWN.getCode()).build();
}
throw new ApiException(ErrorCode.ACCOUNT_NOT_EXIST.getCode());
}
/**
*
*
* @param gamesLogin
* @return {@link String }
*/
@Override
public String loginWithoutRedirect(GamesLogin gamesLogin) {
log.info("GamesPPServiceImpl [loginWithoutRedirect] 请求参数 {}", gamesLogin);
Map<String, Object> params = new TreeMap<>();
params.put("secureLogin", gamesLogin.getAgentId());
params.put("externalPlayerId", gamesLogin.getAccount());
params.put("gameId", gamesLogin.getGameId());
params.put("language", gamesLogin.getLang());
if (!StringUtils.isEmpty(gamesLogin.getPlatform())) {
if ("web".equalsIgnoreCase(gamesLogin.getPlatform())) {
params.put("platform", "WEB");
} else {
params.put("platform", "MOBILE");
}
}
params.put("lobbyURL", gamesLogin.getHomeUrl());
String query = JsonUtil.mapToQueryString(params);
gamesLogin.setQuery(query);
String key = this.getKey(gamesLogin);
params.put("hash", key);
PPGameLaunchResponse ppGameLaunchResponse = ppClient.loginWithoutRedirect(params);
if (this.getIsSuccess(ppGameLaunchResponse.getError())) {
return ppGameLaunchResponse.getGameUrl();
} else {
throw new ApiException(ErrorCode.ACCOUNT_NOT_EXIST.getCode());
}
}
/**
*
*
* @param gamesBaseRequestDTO dto
* @return {@link String }
*/
@Transactional
@Override
public String getGameList(GamesBaseRequestDTO gamesBaseRequestDTO) {
List<PPGameResponseDTO.CasinoGame> gamesDatas = gRedisCache.getCacheList(CacheConstants.PP_GAMES);
if (!CollectionUtils.isEmpty(gamesDatas)) {
return CacheConstants.PP_GAMES;
}
Map<String, Object> params = new LinkedHashMap<>();
params.put("secureLogin", gamesBaseRequestDTO.getAgentId());
String query = JsonUtil.mapToQueryString(params);
gamesBaseRequestDTO.setQuery(query);
String key = this.getKey(gamesBaseRequestDTO);
params.put("hash", key);
PPGameResponseDTO gameList = ppClient.getGameList(params);
if (this.getIsSuccess(gameList.getError())) {
for (PPGameResponseDTO.CasinoGame apiGameInfoResponseDTO : gameList.getGameList()) {
Integer platformType = PPGameType.findSystemByCode(apiGameInfoResponseDTO.getGameTypeID());
//不支持的游戏跳过
if (ObjectUtils.isEmpty(platformType)) {
continue;
}
Integer ingress = convertToIngress(apiGameInfoResponseDTO.getPlatform());
//不需要的平台
if (ObjectUtils.isEmpty(ingress)) {
continue;
}
Game game = Game.builder()
.platformCode(GamePlatforms.PP.getCode())
.platformType(platformType)
.gameCode(apiGameInfoResponseDTO.getGameID())
.build();
List<Game> games = gameService.selectGameList(game);
//不存在这个游戏
if (CollectionUtils.isEmpty(games)) {
game.setIngress(ingress);
game.setGameSourceType(apiGameInfoResponseDTO.getGameTypeID());
game.setFreespin(Boolean.FALSE);
game.setDemoStatus(Boolean.FALSE);
game.setSortNo(gameService.selectMaxSortNo(platformType, GamePlatforms.PP.getCode()) + 1);
game.setGameName(apiGameInfoResponseDTO.getGameName());
game.setCreateBy("system");
game.setPlatformCode(GamePlatforms.PP.getCode());
game.setPlatformType(platformType);
game.setGameId(StringUtils.addSuffix(GamePlatforms.PP.getCode(), apiGameInfoResponseDTO.getGameID()));
List<NameInfo> nameInfos = new ArrayList<>();
nameInfos.add(new NameInfo(apiGameInfoResponseDTO.getGameName(), "en-US"));
game.setNameInfo(nameInfos);
gameService.insertGame(game);
} else {
game = games.get(0);
}
apiGameInfoResponseDTO.setSystemGameId(game.getGameId());
apiGameInfoResponseDTO.setSystemPlatformType(platformType);
}
gRedisCache.deleteObject(CacheConstants.PP_GAMES);
gRedisCache.setCacheList(CacheConstants.PP_GAMES, gameList.getGameList());
gRedisCache.expire(CacheConstants.PP_GAMES, 5L, TimeUnit.HOURS);
} else {
throw new BaseException(gameList.getDescription());
}
return CacheConstants.PP_GAMES;
}
/**
* id
*
* @param transactionIdRequestDTO iddto
* @return {@link String }
*/
@Override
public String getTransactionId(TransactionIdRequestDTO transactionIdRequestDTO) {
return GamePlatforms.PP.getCode() + IdUtil.getSnowflakeNextIdStr();
}
/**
* id
*
* @param exchangeTransferMoneyRequestDTO moeny dto
* @return {@link Long }
*/
@Override
@Transactional
public Long exchangeTransferByAgentId(ExchangeTransferMoneyRequestDTO exchangeTransferMoneyRequestDTO) {
log.info("GamesKMServiceImpl [exchangeTransferByAgentId] 请求参数 {}", exchangeTransferMoneyRequestDTO);
GameExchangeMoney exchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(exchangeTransferMoneyRequestDTO.getGameExchangeId());
BigDecimal amount = exchangeTransferMoneyRequestDTO.getAmount();
if (TransferType.ALL.getCode().equals(exchangeTransferMoneyRequestDTO.getTransferType())) {
// 获取第三方钱包余额
MemberInfoRequestDTO gamesBaseRequestDTO = MemberInfoRequestDTO.builder()
.accounts(exchangeTransferMoneyRequestDTO.getAccount())
.agentId(exchangeTransferMoneyRequestDTO.getAgentId())
.currency(exchangeTransferMoneyRequestDTO.getCurrency())
.agentKey(exchangeTransferMoneyRequestDTO.getAgentKey())
.build();
amount = this.getMemberInfo(gamesBaseRequestDTO).getBalance().negate();
}
Map<String, Object> params = new TreeMap<>();
params.put("secureLogin", exchangeTransferMoneyRequestDTO.getAgentId());
params.put("externalPlayerId", exchangeTransferMoneyRequestDTO.getAccount());
params.put("externalTransactionId", exchangeTransferMoneyRequestDTO.getTransactionId());
params.put("amount", amount);
String query = JsonUtil.mapToQueryString(params);
exchangeTransferMoneyRequestDTO.setQuery(query);
String key = this.getKey(exchangeTransferMoneyRequestDTO);
params.put("hash", key);
PPTransactionResponse transactionResponse = ppClient.exchangeTransfer(params);
//判断是否转移成功
if (this.getIsSuccess(transactionResponse.getError())) {
amount = amount.abs();
//更新数据
exchangeMoney.setBalance(amount);
exchangeMoney.setCoinBefore(NumberUtil.sub(amount, transactionResponse.getBalance()).abs());
exchangeMoney.setCoinAfter(transactionResponse.getBalance());
exchangeMoney.setCurrencyBefore(exchangeMoney.getCoinBefore());
exchangeMoney.setCurrencyAfter(exchangeMoney.getCoinAfter());
exchangeMoney.setStep(GameExchangeStep.PLATFORM_TRANSACTION.getCode());
exchangeMoney.setStepStatus(GameExchangeStepStatus.SUCCESS.getCode());
exchangeMoney.setPartyTransactionId(transactionResponse.getTransactionId());
gameExchangeMoneyService.updateGameExchangeMoney(exchangeMoney);
} else {
exchangeMoney.setStep(GameExchangeStep.PLATFORM_TRANSACTION.getCode());
exchangeMoney.setStepStatus(GameExchangeStepStatus.FAILURE.getCode());
gameExchangeMoneyService.updateGameExchangeMoney(exchangeMoney);
log.error("GamesPPServiceImpl [exchangeTransferByAgentId] 金额转移失败,错误代码{},错误信息{}", transactionResponse.getError(), transactionResponse.getDescription());
throw new ApiException(ErrorCode.BALANCE_TRANSFER_FAILED.getCode());
}
return exchangeMoney.getId();
}
/**
*
*
* @param exchangeTransferMoneyRequestDTO dto
* @return {@link Boolean }
*/
@Override
public ExchangeTransferStatusResponseDTO exchangeTransferStatus(ExchangeTransferStatusRequestDTO exchangeTransferMoneyRequestDTO) {
log.info("GamesPPServiceImpl [exchangeTransferStatus] 请求参数 {}", exchangeTransferMoneyRequestDTO);
GameExchangeMoney exchangeMoney = gameExchangeMoneyService.selectGameExchangeMoneyById(exchangeTransferMoneyRequestDTO.getGameExchangeMoneyId());
Map<String, Object> params = new TreeMap<>();
params.put("secureLogin", exchangeTransferMoneyRequestDTO.getAgentId());
params.put("externalTransactionId", StringUtils.isEmpty(exchangeMoney.getPartyTransactionId()) ? "0" : exchangeMoney.getPartyTransactionId());
params.put("externalPlayerId", exchangeTransferMoneyRequestDTO.getOrderId());
String query = JsonUtil.mapToQueryString(params);
exchangeTransferMoneyRequestDTO.setQuery(query);
String key = this.getKey(exchangeTransferMoneyRequestDTO);
params.put("hash", key);
PPTransactionStatusResponse ppTransactionStatusResponse = ppClient.exchangeTransferStatus(params);
if (this.getIsSuccess(ppTransactionStatusResponse.getError())) {
Integer status = StatusType.IN_PROGRESS.getValue();
if ("Success".equals(ppTransactionStatusResponse.getStatus())) {
status = StatusType.SUCCESS.getValue();
} else {
status = StatusType.FAILURE.getValue();
}
return ExchangeTransferStatusResponseDTO.builder()
.statusType(status)
.balance(ppTransactionStatusResponse.getAmount())
.coinAfter(ppTransactionStatusResponse.getBalance())
.build();
} else {
log.error("GamesPPServiceImpl [exchangeTransferStatus] 金额转移确认失败,错误代码{},错误信息{}", ppTransactionStatusResponse.getError(), ppTransactionStatusResponse.getDescription());
return ExchangeTransferStatusResponseDTO.builder()
.statusType(StatusType.FAILURE.getValue())
.build();
}
}
/**
*
*
* @param betRecordByTimeDTO dto
* @return {@link List }<{@link GameBettingDetails }>
*/
@Override
public Boolean getBetRecordByTime(BetRecordByTimeDTO betRecordByTimeDTO) {
Long timepoint = gRedisCache.getCacheObject(CacheConstants.PP_TIME_POINT);
if (ObjectUtils.isEmpty(timepoint)) {
timepoint = betRecordByTimeDTO.getStartTime();
}
//请求参数
log.info("GamesPPServiceImpl [getBetRecordByTime] 请求参数 {}", betRecordByTimeDTO);
Map<String, Object> params = new LinkedHashMap<>();
params.put("login", betRecordByTimeDTO.getAgentId());
params.put("password", betRecordByTimeDTO.getAgentKey());
params.put("timepoint", timepoint);
String result = ppClient.getBetRecordByTime(JsonUtil.mapToQueryString(params));
this.batchInsert(PPGameRoundRecord.parse(result), betRecordByTimeDTO);
//重新保存最新的时间
String[] lines = result.split("\n");
timepoint = Long.parseLong(lines[0].replace("timepoint=", ""));
gRedisCache.setCacheObject(CacheConstants.PP_TIME_POINT, timepoint);
return Boolean.TRUE;
}
/**
*
*
* @param betRecordByTimeDTO dto
* @return {@link Boolean }
*/
@Override
public Boolean getBetRecordByHistoryTime(BetRecordByTimeDTO betRecordByTimeDTO) {
//请求参数
log.info("GamesPPServiceImpl [getBetRecordByHistoryTime] 请求参数 {}", betRecordByTimeDTO);
long timepoint = betRecordByTimeDTO.getStartTime();
while (timepoint < betRecordByTimeDTO.getEndTime()) {
Map<String, Object> params = new LinkedHashMap<>();
params.put("login", betRecordByTimeDTO.getAgentId());
params.put("password", betRecordByTimeDTO.getAgentKey());
params.put("timepoint", timepoint);
String result = ppClient.getBetRecordByTime(JsonUtil.mapToQueryString(params));
this.batchInsert(PPGameRoundRecord.parse(result), betRecordByTimeDTO);
//重新保存最新的时间
String[] lines = result.split("\n");
timepoint = Long.parseLong(lines[0].replace("timepoint=", ""));
}
return Boolean.TRUE;
}
/**
*
*
* @param createFreeSpinRequest
* @return {@link Boolean }
*/
@Override
public Boolean createFreeSpin(CreateFreeSpinRequestDTO createFreeSpinRequest) {
throw new ApiException(ErrorCode.PLATFORM_NOT_METHODS.getCode());
}
/**
*
*
* @param getGameDetailRequestDTO dto
* @return {@link GetGameDetailResponseDTO }
*/
@Override
public GetGameDetailResponseDTO getGameDetail(GetGameDetailRequestDTO getGameDetailRequestDTO) {
throw new ApiException(ErrorCode.PLATFORM_NOT_METHODS.getCode());
}
/**
*
*
* @param kickMemberRequestDTO dto
* @return {@link Boolean }
*/
@Override
public Boolean kickMember(KickMemberRequestDTO kickMemberRequestDTO) {
log.info("GamesPPServiceImpl [kickMember] 请求参数 {}", kickMemberRequestDTO);
Map<String, Object> params = new TreeMap<>();
params.put("secureLogin", kickMemberRequestDTO.getAgentId());
params.put("externalPlayerId", kickMemberRequestDTO.getAccount());
String query = JsonUtil.mapToQueryString(params);
kickMemberRequestDTO.setQuery(query);
String key = this.getKey(kickMemberRequestDTO);
params.put("hash", key);
PPResponse kickMember = ppClient.kickMember(params);
if (this.getIsSuccess(kickMember.getError())) {
return Boolean.TRUE;
} else {
throw new ApiException(ErrorCode.KICK_OUT_AILED.getCode());
}
}
/**
*
*
* @param kickMemberAllDTO dto
* @return {@link Boolean }
*/
@Override
public Boolean kickMemberAll(KickMemberAllDTO kickMemberAllDTO) {
throw new ApiException(ErrorCode.PLATFORM_NOT_METHODS.getCode());
}
/**
* 使
*
* @param getFreeSpinDashflowRequestDTO dashflowdto
* @return {@link List }<{@link GameFreeRecord }>
*/
@Override
public List<GameFreeRecord> 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());
}
@Override
public GameDemoLoginResponseDTO gameDemoLogin(GameDemoLoginRequestDTO gameDemoLoginRequestDTO) {
throw new ApiException(ErrorCode.PLATFORM_NOT_METHODS.getCode());
}
/**
*
*/
private synchronized void batchInsert(List<PPGameRoundRecord> report, GamesBaseRequestDTO gamesBaseRequestDTO) {
List<GameBettingDetails> gameBettingDetails = new ArrayList<>();
List<String> wagersIds = new ArrayList<>();
//数据转化
for (PPGameRoundRecord bean : report) {
GameBettingDetails bettingDetails = this.dataBuild(GamesDataBuildDTO.builder().platform(gamesBaseRequestDTO.getVendor()).data(bean).build());
if (!ObjectUtils.isEmpty(bettingDetails)) {
bettingDetails.setId(IdUtil.getSnowflakeNextId());
gameBettingDetails.add(bettingDetails);
}
wagersIds.add(String.valueOf(bean.getPlaySessionID()));
}
if (!CollectionUtils.isEmpty(gameBettingDetails)) {
//查询重复数据id
List<String> removeWagersIds = gameBettingDetailsService.selectGameBettingDetailsByWagersId(wagersIds, GamePlatforms.PP.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) {
//转化类
PPGameRoundRecord resultBean = (PPGameRoundRecord) gamesDataBuildDTO.getData();
Member member = memberService.selectMemberByGameAccount(resultBean.getExtPlayerID());
if (ObjectUtils.isEmpty(member)) {
return null;
}
List<PPGameResponseDTO.CasinoGame> gamesDatas = gRedisCache.getCacheList(CacheConstants.PP_GAMES);
Map<String, PPGameResponseDTO.CasinoGame> dataDTOMap = gamesDatas.stream().collect(Collectors.toMap(
PPGameResponseDTO.CasinoGame::getGameID,
e -> e,
(existing, replacement) -> existing
));
PPGameResponseDTO.CasinoGame casinoGame = dataDTOMap.get(resultBean.getGameID());
BigDecimal payoffAmount = NumberUtil.sub(resultBean.getWin(), resultBean.getBet());
Integer gameStatus = GameStatus.FLAT.getCode();
if (payoffAmount.compareTo(BigDecimal.ZERO) > 0) {
gameStatus = GameStatus.WIN.getCode();
} else if (payoffAmount.compareTo(BigDecimal.ZERO) < 0) {
gameStatus = GameStatus.FAIL.getCode();
}
//数据构造
GameBettingDetails gameBettingDetails = GameBettingDetails.builder()
.tenantKey(member.getTenantKey())
//保存我们的币种id
.currencyCode(gamesDataBuildDTO.getPlatform().getOurCurrency(resultBean.getCurrency()))
.memberId(member.getId())
.gameCode(resultBean.getGameID())
.gameType(casinoGame.getSystemPlatformType())
.platformCode(GamePlatforms.PP.getInfo())
.gameId(casinoGame.getSystemGameId())
.gameName(casinoGame.getGameName())
.gameStatus(gameStatus)
.gameStatusType("F".equals(resultBean.getType()) ? 19 : 1)
.gameCurrencyCode(resultBean.getCurrency())
.account(resultBean.getExtPlayerID())
.wagersId(resultBean.getPlaySessionID())
.wagersTime(resultBean.getStartDate())
.betAmount(resultBean.getBet())
.payoffTime(resultBean.getEndDate())
.payoffAmount(payoffAmount.abs())
.settlementTime(resultBean.getEndDate())
.turnover(resultBean.getBet())
.settlementStatus(SettlementStatusEnum.COMPLETED.getCode())
.build();
gameBettingDetails.setCreateBy(Constants.SYSTEM);
gameBettingDetails.setCreateTime(DateUtils.getNowDate());
return gameBettingDetails;
}
}

View File

@ -27,15 +27,7 @@ public class ExchangeTransferMoneyRequestDTO extends GamesBaseRequestDTO {
*/ */
private String account; private String account;
/**
*
*/
private String tenantKey;
/**
* id
*/
private String orderId;
/** /**
* *
*/ */
@ -43,9 +35,14 @@ public class ExchangeTransferMoneyRequestDTO extends GamesBaseRequestDTO {
/** /**
* * id
*/ */
private BigDecimal quota; private Long gameExchangeId;
/**
*
*/
private String transactionId;
/** /**

View File

@ -0,0 +1,25 @@
package com.ff.game.api.request;
import com.ff.base.annotation.Excel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* iddto
*
* @author shi
* @date 2025/04/11
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class TransactionIdRequestDTO {
/** 转出类型 1游戏商转入到用户全部转出 2 用户转移到游戏商 3 游戏商转移额度到平台商 */
private Integer exchangeType;
/** 游戏账号 */
private String gameAccount;
}

View File

@ -65,6 +65,14 @@ public interface SAClient {
String exchangeTransferByInto(@Body String params); String exchangeTransferByInto(@Body String params);
@Post( url ="/api.aspx/CheckOrderDetailsDV",
headers = {
"Content-type: application/x-www-form-urlencoded"
})
String exchangeTransferStatus(@Body String params);
/** /**
* *
* *

View File

@ -0,0 +1,74 @@
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;
import java.util.Date;
/**
* CheckOrderDetailsResponse - XML Java
*/
@Data
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "CheckOrderDetailsResponse")
public class SACheckOrderDetailsResponse {
/**
* ID
*/
@XmlElement(name = "ErrorMsgId")
private Integer errorMsgId;
/**
*
*/
@XmlElement(name = "ErrorMsg")
private String errorMsg;
/**
*
*/
@XmlElement(name = "isExist")
private Boolean isExist;
/**
*
*/
@XmlElement(name = "Date")
private Date date;
/**
*
*/
@XmlElement(name = "Type")
private Integer type;
/**
*
*/
@XmlElement(name = "Currency")
private String currency;
/**
*
*/
@XmlElement(name = "Amount")
private BigDecimal amount;
/**
*
*/
@XmlElement(name = "PreviousBalance")
private BigDecimal previousBalance;
/**
*
*/
@XmlElement(name = "Balance")
private BigDecimal balance;
}

Some files were not shown because too many files have changed in this diff Show More