幸运礼物新爆率,新增多账号模式 根据standardId切换

This commit is contained in:
tianfeng 2026-01-21 19:46:38 +08:00
parent 5ef64ef311
commit 85f3e58190
5 changed files with 115 additions and 45 deletions

View File

@ -95,4 +95,10 @@ public class GameLuckyGiftBusinessEvent implements Serializable {
*/
private List<GameLuckyGiftUser> users;
/**
* 规格ID用于匹配第三方API配置.
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long standardId;
}

View File

@ -31,6 +31,7 @@ import com.red.circle.other.domain.ranking.RankingActivityType;
import com.red.circle.other.domain.ranking.RankingCycleType;
import com.red.circle.other.domain.ranking.RankingDimension;
import com.red.circle.other.infra.config.LuckyGiftApiConfig;
import com.red.circle.other.infra.config.LuckyGiftApiConfig.ApiAccount;
import com.red.circle.other.infra.database.cache.entity.game.luckgift.GameLuckyGiftConfigCache;
import com.red.circle.other.infra.database.cache.entity.game.luckgift.GameLuckyGiftInventoryCache;
import com.red.circle.other.infra.database.cache.entity.game.luckgift.LuckyGiftInventoryTemplateCache;
@ -181,7 +182,8 @@ public class GameLuckyGiftCommon {
.setOpenComboLoss(isOpenComboLoss(template))
.setSysComboLoss(template.getComboLoss())
.setOpenGiftGiveTotal(isOpenGiftGiveTotal(template))
.setSysGiftGiveTotal(template.getGiftGiveTotal());
.setSysGiftGiveTotal(template.getGiftGiveTotal())
.setStandardId(standardId);
// 是否正在连击送礼物
if (Boolean.TRUE.equals(event.getCheckCombo())) {
@ -685,12 +687,16 @@ public class GameLuckyGiftCommon {
*/
private ThirdPartyLotteryResult callThirdPartyLotteryApi(GameLuckyGiftParam param, List<String> orderIds) {
try {
// 根据 standardId 获取对应的API配置
ApiAccount apiConfig = luckyGiftApiConfig.getConfigByStandardId(param.getStandardId());
log.info("使用API配置, standardId: {}, config: {}", param.getStandardId(), apiConfig);
Map<String, Object> requestData = new HashMap<>();
requestData.put("room_id", param.getRoomId().toString());
requestData.put("user_id", param.getUserId().toString());
requestData.put("order_id", orderIds);
requestData.put("app_id", luckyGiftApiConfig.getAppId());
requestData.put("app_channel", luckyGiftApiConfig.getAppChannel());
requestData.put("app_id", apiConfig.getAppId());
requestData.put("app_channel", apiConfig.getAppChannel());
requestData.put("gift_id", param.getGiftId().intValue());
requestData.put("gift_price", param.getGift().getGiftCandy().intValue());
requestData.put("gift_num", param.getQuantity());
@ -698,7 +704,7 @@ public class GameLuckyGiftCommon {
requestData.put("timestamp", System.currentTimeMillis() / 1000);
// 生成签名
String signature = generateSignature(requestData);
String signature = generateSignature(requestData, apiConfig.getAppKey());
requestData.put("signature", signature);
log.info("调用第三方幸运礼物API请求参数{}", JSON.toJSONString(requestData));
@ -709,7 +715,7 @@ public class GameLuckyGiftCommon {
// 发送HTTP请求 - 使用Hutool的HttpUtil
String requestBody = JSON.toJSONString(requestData);
String response = HttpUtil.createPost(luckyGiftApiConfig.getUrl())
String response = HttpUtil.createPost(apiConfig.getUrl())
.header("Content-Type", "application/json")
.header("Accept", "application/json")
.timeout(10000)
@ -766,8 +772,12 @@ public class GameLuckyGiftCommon {
/**
* 生成API签名.
*
* @param params 请求参数
* @param appKey 应用密钥
* @return 签名字符串
*/
private String generateSignature(Map<String, Object> params) {
private String generateSignature(Map<String, Object> params, String appKey) {
try {
// 按键名升序排列参数
TreeMap<String, Object> sortedParams = new TreeMap<>(params);
@ -796,7 +806,7 @@ public class GameLuckyGiftCommon {
signBuilder.append(key).append("=").append(valueStr);
}
}
signBuilder.append("&app_key=").append(luckyGiftApiConfig.getAppKey());
signBuilder.append("&app_key=").append(appKey);
log.debug("签名原始字符串: {}", signBuilder.toString());
@ -1244,6 +1254,9 @@ public class GameLuckyGiftCommon {
// 获得用户头像框
UserPropsResourcesDTO avatarFrameProps = getUserAvatarFrameProps(sendUserProfile);
// 优先使用cmd传递的standardId如果为空则降级使用gift的standardId
Long standardId = Objects.nonNull(cmd.getStandardId()) ? cmd.getStandardId() : gift.getStandardId();
return new GameLuckyGiftParam()
.setId(cmd.getId())
.setGift(gift)
@ -1253,7 +1266,7 @@ public class GameLuckyGiftCommon {
.setUserId(cmd.getUserId())
.setQuantity(cmd.getQuantity())
.setSysOrigin(cmd.getSysOrigin())
.setStandardId(gift.getStandardId())
.setStandardId(standardId)
.setGiftsCount(cmd.getGiftsCount())
.setComboCount(cmd.getGiftCombos())
.setRoomAccount(cmd.getRoomAccount())

View File

@ -109,4 +109,10 @@ public class GameLuckyGiftParamCmd implements Serializable {
@JsonSerialize(using = ToStringSerializer.class)
private Long acceptUserId;
/**
* 规格ID用于匹配第三方API配置.
*/
@JsonSerialize(using = ToStringSerializer.class)
private Long standardId;
}

View File

@ -101,7 +101,8 @@ public class GameLuckyGiftBusinessListener implements MessageListener {
.setSysComboLoss(event.getSysComboLoss())
.setOpenGiftGiveTotal(event.getOpenGiftGiveTotal())
.setSysGiftGiveTotal(event.getSysGiftGiveTotal())
.setRegionCode(userRegionGateway.getRegionCode(event.getUserId()));
.setRegionCode(userRegionGateway.getRegionCode(event.getUserId()))
.setStandardId(event.getStandardId());
}

View File

@ -1,5 +1,8 @@
package com.red.circle.other.infra.config;
import java.util.List;
import java.util.Objects;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
@ -7,28 +10,34 @@ import org.springframework.stereotype.Component;
/**
* 第三方幸运礼物API配置
*/
@Data
@Component
@ConfigurationProperties(prefix = "lucky.gift.api")
@RefreshScope
public class LuckyGiftApiConfig {
/**
* API地址
* 多账号配置列表
*/
private List<ApiAccount> configs;
/**
* 默认API地址向后兼容旧配置
*/
private String url;
/**
* 应用密钥
* 默认应用密钥向后兼容旧配置
*/
private String appKey;
/**
* 应用ID
* 默认应用ID向后兼容旧配置
*/
private String appId;
/**
* 应用渠道
* 默认应用渠道向后兼容旧配置
*/
private String appChannel;
@ -37,55 +46,90 @@ public class LuckyGiftApiConfig {
*/
private boolean enabled = true;
// Getter Setter 方法
public String getUrl() {
return url;
/**
* 根据 standardId 获取对应的配置
* 优先从 configs 列表匹配匹配不到则返回默认配置
*
* @param standardId 规格ID
* @return 匹配的配置
*/
public ApiAccount getConfigByStandardId(Long standardId) {
// 优先从 configs 列表中匹配
if (configs != null && !configs.isEmpty() && standardId != null) {
for (ApiAccount config : configs) {
if (Objects.equals(config.getStandardId(), standardId)) {
return config;
}
}
}
// 匹配不到则返回默认配置向后兼容
return buildDefaultConfig();
}
public void setUrl(String url) {
this.url = url;
/**
* 构建默认配置使用旧的单一配置字段
*/
private ApiAccount buildDefaultConfig() {
ApiAccount defaultConfig = new ApiAccount();
defaultConfig.setUrl(this.url);
defaultConfig.setAppKey(this.appKey);
defaultConfig.setAppId(this.appId);
defaultConfig.setAppChannel(this.appChannel);
return defaultConfig;
}
public String getAppKey() {
return appKey;
}
/**
* 单个账号配置
*/
@Data
public static class ApiAccount {
public void setAppKey(String appKey) {
this.appKey = appKey;
}
/**
* 规格ID用于匹配
*/
private Long standardId;
public String getAppId() {
return appId;
}
/**
* API地址
*/
private String url;
public void setAppId(String appId) {
this.appId = appId;
}
/**
* 应用密钥
*/
private String appKey;
public String getAppChannel() {
return appChannel;
}
/**
* 应用ID
*/
private String appId;
public void setAppChannel(String appChannel) {
this.appChannel = appChannel;
}
/**
* 应用渠道
*/
private String appChannel;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
@Override
public String toString() {
return "ApiAccount{" +
"standardId=" + standardId +
", url='" + url + '\'' +
", appKey='***'" +
", appId='" + appId + '\'' +
", appChannel='" + appChannel + '\'' +
'}';
}
}
@Override
public String toString() {
return "LuckyGiftApiConfig{" +
"url='" + url + '\'' +
", appKey='" + "***" + '\'' + // 敏感信息脱敏
"configs=" + configs +
", url='" + url + '\'' +
", appKey='***'" +
", appId='" + appId + '\'' +
", appChannel='" + appChannel + '\'' +
", enabled=" + enabled +
'}';
}
}
}