Compare commits
No commits in common. "3bbaa78528478019ad7a81e01f68a7dae6ff4cdb" and "3ec362be15c748c925f90671884e66865acca861" have entirely different histories.
3bbaa78528
...
3ec362be15
@ -46,8 +46,6 @@ red-circle:
|
|||||||
endpoint: ${LIKEI_TRTC_ENDPOINT}
|
endpoint: ${LIKEI_TRTC_ENDPOINT}
|
||||||
region: ${LIKEI_TRTC_REGION:ap-singapore}
|
region: ${LIKEI_TRTC_REGION:ap-singapore}
|
||||||
sdkAppId: ${LIKEI_TRTC_SDK_APP_ID}
|
sdkAppId: ${LIKEI_TRTC_SDK_APP_ID}
|
||||||
userSigKey: ${LIKEI_TRTC_USER_SIG_KEY:${LIKEI_TRTC_SECRET_KEY}}
|
|
||||||
userSigExpireSeconds: ${LIKEI_TRTC_USER_SIG_EXPIRE_SECOND:7200}
|
|
||||||
tencet-im:
|
tencet-im:
|
||||||
appId: ${LIKEI_IM_APP_ID}
|
appId: ${LIKEI_IM_APP_ID}
|
||||||
key: ${LIKEI_IM_KEY}
|
key: ${LIKEI_IM_KEY}
|
||||||
|
|||||||
@ -39,10 +39,10 @@ public class LoginAccessValidationService {
|
|||||||
"香港", "澳门", "澳門", "台湾", "台灣", "Hong Kong", "Macau", "Macao", "Taiwan"
|
"香港", "澳门", "澳門", "台湾", "台灣", "Hong Kong", "Macau", "Macao", "Taiwan"
|
||||||
);
|
);
|
||||||
private static final List<String> BLOCKED_COUNTRY_CODES = List.of(
|
private static final List<String> BLOCKED_COUNTRY_CODES = List.of(
|
||||||
"MO", "SG"
|
"MO", "SG", "TW"
|
||||||
);
|
);
|
||||||
private static final List<String> BLOCKED_COUNTRY_NAMES = List.of(
|
private static final List<String> BLOCKED_COUNTRY_NAMES = List.of(
|
||||||
"澳门", "澳門", "Macau", "Macao", "新加坡", "Singapore"
|
"澳门", "澳門", "台湾", "台灣", "Macau", "Macao", "Taiwan", "新加坡", "Singapore"
|
||||||
);
|
);
|
||||||
private static final List<IpGeoProvider> IP_GEO_PROVIDERS = List.of(
|
private static final List<IpGeoProvider> IP_GEO_PROVIDERS = List.of(
|
||||||
new IpGeoProvider("ip.sb", "https://api.ip.sb/geoip/%s"),
|
new IpGeoProvider("ip.sb", "https://api.ip.sb/geoip/%s"),
|
||||||
|
|||||||
@ -107,21 +107,21 @@ public class LoginAccessValidationServiceTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void allowTaiwanRegion() {
|
public void blockTaiwanRegion() {
|
||||||
JSONObject data = JSON.parseObject("""
|
JSONObject data = JSON.parseObject("""
|
||||||
{"country_id":"CN","country":"中国","region":"台湾"}
|
{"country_id":"CN","country":"中国","region":"台湾"}
|
||||||
""");
|
""");
|
||||||
|
|
||||||
assertFalse(LoginAccessValidationService.isMainlandChina(data));
|
assertFalse(LoginAccessValidationService.isMainlandChina(data));
|
||||||
assertFalse(LoginAccessValidationService.isBlockedIpRegion(data));
|
assertTrue(LoginAccessValidationService.isBlockedIpRegion(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void allowTaiwanCountryCode() {
|
public void blockTaiwanCountryCode() {
|
||||||
JSONObject data = JSON.parseObject("""
|
JSONObject data = JSON.parseObject("""
|
||||||
{"country_id":"TW","country":"Taiwan","region":""}
|
{"country_id":"TW","country":"Taiwan","region":""}
|
||||||
""");
|
""");
|
||||||
|
|
||||||
assertFalse(LoginAccessValidationService.isBlockedIpRegion(data));
|
assertTrue(LoginAccessValidationService.isBlockedIpRegion(data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,74 +0,0 @@
|
|||||||
package com.red.circle.common.business.dto.rtc;
|
|
||||||
|
|
||||||
import com.red.circle.framework.dto.ClientObject;
|
|
||||||
import java.io.Serial;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.EqualsAndHashCode;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* RTC credential returned to compatible clients.
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Accessors(chain = true)
|
|
||||||
@EqualsAndHashCode(callSuper = true)
|
|
||||||
public class RtcCredentialCO extends ClientObject {
|
|
||||||
|
|
||||||
@Serial
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* AGORA or TRTC.
|
|
||||||
*/
|
|
||||||
private String rtcProvider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Legacy Agora token.
|
|
||||||
*/
|
|
||||||
private String agoraToken;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Agora channel name, currently the business room id.
|
|
||||||
*/
|
|
||||||
private String agoraChannelName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tencent TRTC sdkAppId.
|
|
||||||
*/
|
|
||||||
private Long trtcSdkAppId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TRTC user id. Use business userId string.
|
|
||||||
*/
|
|
||||||
private String trtcUserId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TRTC UserSig.
|
|
||||||
*/
|
|
||||||
private String trtcUserSig;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Numeric TRTC room id when available.
|
|
||||||
*/
|
|
||||||
private Long trtcRoomId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* String TRTC room id fallback.
|
|
||||||
*/
|
|
||||||
private String trtcStrRoomId;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TRTC role: 20 anchor, 21 audience.
|
|
||||||
*/
|
|
||||||
private Integer trtcRole;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* UserSig lifetime in seconds.
|
|
||||||
*/
|
|
||||||
private Long trtcUserSigExpireSeconds;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* UserSig expire timestamp in milliseconds.
|
|
||||||
*/
|
|
||||||
private Long trtcUserSigExpireAt;
|
|
||||||
}
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
package com.red.circle.common.business.dto.rtc;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* RTC provider used by voice rooms.
|
|
||||||
*/
|
|
||||||
public enum RtcProviderEnum {
|
|
||||||
AGORA,
|
|
||||||
TRTC;
|
|
||||||
|
|
||||||
public static RtcProviderEnum of(String provider) {
|
|
||||||
if (provider == null || provider.isBlank()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
for (RtcProviderEnum value : values()) {
|
|
||||||
if (value.name().equalsIgnoreCase(provider.trim())) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,66 +0,0 @@
|
|||||||
package com.red.circle.common.business.dto.rtc;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Version based RTC compatibility rules.
|
|
||||||
*/
|
|
||||||
public final class RtcVersionSupport {
|
|
||||||
|
|
||||||
public static final String TRTC_MIN_VERSION = "1.4.0";
|
|
||||||
public static final String ROOM_PROVIDER_KEY_PREFIX = "RTC:ROOM:PROVIDER:";
|
|
||||||
public static final long ROOM_PROVIDER_TTL_SECONDS = 12 * 60 * 60L;
|
|
||||||
|
|
||||||
private RtcVersionSupport() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static RtcProviderEnum defaultProvider(String version) {
|
|
||||||
return compareVersion(version, TRTC_MIN_VERSION) <= 0
|
|
||||||
? RtcProviderEnum.AGORA
|
|
||||||
: RtcProviderEnum.TRTC;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String roomProviderKey(Object roomId) {
|
|
||||||
return ROOM_PROVIDER_KEY_PREFIX + roomId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int compareVersion(String left, String right) {
|
|
||||||
int[] leftParts = parseVersion(left);
|
|
||||||
int[] rightParts = parseVersion(right);
|
|
||||||
int length = Math.max(leftParts.length, rightParts.length);
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
int leftPart = i < leftParts.length ? leftParts[i] : 0;
|
|
||||||
int rightPart = i < rightParts.length ? rightParts[i] : 0;
|
|
||||||
if (leftPart != rightPart) {
|
|
||||||
return Integer.compare(leftPart, rightPart);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int[] parseVersion(String version) {
|
|
||||||
if (version == null || version.isBlank()) {
|
|
||||||
return new int[]{0};
|
|
||||||
}
|
|
||||||
String normalized = version.trim().split("-", 2)[0];
|
|
||||||
String[] parts = normalized.split("\\.");
|
|
||||||
int[] values = new int[parts.length];
|
|
||||||
for (int i = 0; i < parts.length; i++) {
|
|
||||||
values[i] = parseVersionPart(parts[i]);
|
|
||||||
}
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int parseVersionPart(String part) {
|
|
||||||
if (part == null || part.isBlank()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
String digits = part.replaceAll("[^0-9].*$", "");
|
|
||||||
if (digits.isBlank()) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return Integer.parseInt(digits);
|
|
||||||
} catch (NumberFormatException ignored) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,6 +1,5 @@
|
|||||||
package com.red.circle.external.inner.endpoint.message.api;
|
package com.red.circle.external.inner.endpoint.message.api;
|
||||||
|
|
||||||
import com.red.circle.common.business.dto.rtc.RtcCredentialCO;
|
|
||||||
import com.red.circle.external.inner.model.cmd.message.TrtcRemoveUserCmd;
|
import com.red.circle.external.inner.model.cmd.message.TrtcRemoveUserCmd;
|
||||||
import com.red.circle.external.inner.model.cmd.message.TrtcUserBlockedCmd;
|
import com.red.circle.external.inner.model.cmd.message.TrtcUserBlockedCmd;
|
||||||
import com.red.circle.framework.dto.ResultResponse;
|
import com.red.circle.framework.dto.ResultResponse;
|
||||||
@ -57,14 +56,4 @@ public interface TrtcClientApi {
|
|||||||
@RequestParam("type") String channelName
|
@RequestParam("type") String channelName
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建 TRTC 入房凭证.
|
|
||||||
*/
|
|
||||||
@GetMapping("/createTrtcCredential")
|
|
||||||
ResultResponse<RtcCredentialCO> createTrtcCredential(
|
|
||||||
@RequestParam("userId") Long userId,
|
|
||||||
@RequestParam("roomIdentifier") String roomIdentifier,
|
|
||||||
@RequestParam(value = "publisher", required = false) Boolean publisher
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,18 +4,12 @@ import com.google.gson.Gson;
|
|||||||
import com.google.gson.JsonSyntaxException;
|
import com.google.gson.JsonSyntaxException;
|
||||||
import com.red.circle.auth.inner.endpoint.AuthClient;
|
import com.red.circle.auth.inner.endpoint.AuthClient;
|
||||||
import com.red.circle.common.business.dto.cmd.AppExtCommand;
|
import com.red.circle.common.business.dto.cmd.AppExtCommand;
|
||||||
import com.red.circle.common.business.dto.rtc.RtcCredentialCO;
|
|
||||||
import com.red.circle.common.business.dto.rtc.RtcProviderEnum;
|
|
||||||
import com.red.circle.common.business.dto.rtc.RtcVersionSupport;
|
|
||||||
import com.red.circle.component.instant.msg.InstantMessageProperties;
|
|
||||||
import com.red.circle.component.instant.msg.agora.AgoraAuthentication;
|
import com.red.circle.component.instant.msg.agora.AgoraAuthentication;
|
||||||
import com.red.circle.component.instant.msg.tencet.props.TrtcTencetProperties;
|
|
||||||
import com.red.circle.component.instant.msg.tencet.service.endpoint.api.im.account.ImAccountManagerService;
|
import com.red.circle.component.instant.msg.tencet.service.endpoint.api.im.account.ImAccountManagerService;
|
||||||
import com.red.circle.component.instant.msg.tencet.service.endpoint.api.im.group.ImGroupAvManagerService;
|
import com.red.circle.component.instant.msg.tencet.service.endpoint.api.im.group.ImGroupAvManagerService;
|
||||||
import com.red.circle.component.instant.msg.tencet.service.endpoint.api.trtc.TencentTrtcService;
|
import com.red.circle.component.instant.msg.tencet.service.endpoint.api.trtc.TencentTrtcService;
|
||||||
import com.red.circle.component.instant.msg.tencet.service.result.OnlineStatusResult;
|
import com.red.circle.component.instant.msg.tencet.service.result.OnlineStatusResult;
|
||||||
import com.red.circle.component.instant.msg.tencet.service.result.OnlineStatusResult.OnlineStatus;
|
import com.red.circle.component.instant.msg.tencet.service.result.OnlineStatusResult.OnlineStatus;
|
||||||
import com.red.circle.component.redis.service.RedisService;
|
|
||||||
import com.red.circle.external.clienobject.TmpSigCO;
|
import com.red.circle.external.clienobject.TmpSigCO;
|
||||||
import com.red.circle.external.cmd.imtrtc.ImRoomRemoveUserCmd;
|
import com.red.circle.external.cmd.imtrtc.ImRoomRemoveUserCmd;
|
||||||
import com.red.circle.external.infra.database.redis.service.UserAgoraTokenCacheService;
|
import com.red.circle.external.infra.database.redis.service.UserAgoraTokenCacheService;
|
||||||
@ -32,12 +26,10 @@ import com.red.circle.tool.core.text.StringPool;
|
|||||||
import com.red.circle.other.inner.asserts.user.UserErrorCode;
|
import com.red.circle.other.inner.asserts.user.UserErrorCode;
|
||||||
import com.red.circle.other.inner.endpoint.user.user.UserProfileClient;
|
import com.red.circle.other.inner.endpoint.user.user.UserProfileClient;
|
||||||
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
|
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
|
||||||
import com.tencentyun.TLSSigAPIv2;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import io.agora.media.RtcTokenBuilder2;
|
import io.agora.media.RtcTokenBuilder2;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@ -51,7 +43,6 @@ 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.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IM操作.
|
* IM操作.
|
||||||
@ -74,20 +65,12 @@ public class ImRestController extends BaseController {
|
|||||||
private final ImGroupAvManagerService imGroupAvManagerService;
|
private final ImGroupAvManagerService imGroupAvManagerService;
|
||||||
private final ImAccountManagerService imAccountManagerService;
|
private final ImAccountManagerService imAccountManagerService;
|
||||||
private final UserAgoraTokenCacheService userAgoraTokenCacheService;
|
private final UserAgoraTokenCacheService userAgoraTokenCacheService;
|
||||||
private final RedisService redisService;
|
|
||||||
private final InstantMessageProperties instantMessageProperties;
|
|
||||||
|
|
||||||
@Value("${rtc.appId}")
|
@Value("${rtc.appId}")
|
||||||
private String appId;
|
private String appId;
|
||||||
@Value("${rtc.certificate}")
|
@Value("${rtc.certificate}")
|
||||||
private String certificate;
|
private String certificate;
|
||||||
|
|
||||||
@Value("${red-circle.instant-message.tencet-trtc.userSigExpireSeconds:7200}")
|
|
||||||
private long trtcUserSigExpireSeconds;
|
|
||||||
|
|
||||||
@Value("${red-circle.instant-message.tencet-trtc.userSigKey:${red-circle.instant-message.tencet-trtc.secretKey:}}")
|
|
||||||
private String trtcUserSigKey;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 认证签名(腾讯).
|
* 认证签名(腾讯).
|
||||||
*
|
*
|
||||||
@ -145,14 +128,11 @@ public class ImRestController extends BaseController {
|
|||||||
* @eo.request-type formdata
|
* @eo.request-type formdata
|
||||||
*/
|
*/
|
||||||
@GetMapping("/tmp/agora/sig")
|
@GetMapping("/tmp/agora/sig")
|
||||||
public TmpSigCO userSig(AppExtCommand cmd, Long userId, String channelName, Boolean isPublisher) {
|
public TmpSigCO userSig(Long userId, String channelName,Boolean isPublisher) {
|
||||||
log.warn("/tmp/agora/sig {}, {}, {}", userId, channelName, isPublisher);
|
log.warn("/tmp/agora/sig {}, {}, {}", userId, channelName, isPublisher);
|
||||||
if (isPublisher == null){
|
if (isPublisher == null){
|
||||||
isPublisher = false;
|
isPublisher = false;
|
||||||
}
|
}
|
||||||
RtcProviderEnum provider = resolveRoomProvider(channelName, currentVersion(cmd));
|
|
||||||
ResponseAssert.isTrue(CommonErrorCode.UPGRADE_VERSION,
|
|
||||||
!Objects.equals(RtcProviderEnum.TRTC, provider));
|
|
||||||
String token;
|
String token;
|
||||||
if (isPublisher){
|
if (isPublisher){
|
||||||
token = userAgoraTokenCacheService.getUserAgoraToken(userId, Long.valueOf(channelName));
|
token = userAgoraTokenCacheService.getUserAgoraToken(userId, Long.valueOf(channelName));
|
||||||
@ -177,61 +157,13 @@ public class ImRestController extends BaseController {
|
|||||||
if (Objects.nonNull(json)) {
|
if (Objects.nonNull(json)) {
|
||||||
return getTmpSigByUserCredential(userId, token, json, gson);
|
return getTmpSigByUserCredential(userId, token, json, gson);
|
||||||
} else {
|
} else {
|
||||||
RtcCredentialCO credential = createAgoraCredential(channelName, token);
|
|
||||||
return new TmpSigCO()
|
return new TmpSigCO()
|
||||||
.setRtcToken(token)
|
.setRtcToken(token)
|
||||||
.setRtcProvider(RtcProviderEnum.AGORA.name())
|
|
||||||
.setRtcCredential(credential)
|
|
||||||
.setNewServiceToken(authClient.createIfAbsentUserCredentialToken(userId).getBody());
|
.setNewServiceToken(authClient.createIfAbsentUserCredentialToken(userId).getBody());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* RTC 凭证,支持按客户端版本和房间级 provider 在 Agora/TRTC 间分流.
|
|
||||||
*
|
|
||||||
* @param userId 用户id
|
|
||||||
* @param roomId 业务房间id,作为房间级 provider 缓存 key
|
|
||||||
* @param channelName 历史 Agora channel,可为空
|
|
||||||
* @param roomAccount TRTC 房间号,优先使用
|
|
||||||
* @param isPublisher 是否主播/上麦
|
|
||||||
*/
|
|
||||||
@GetMapping("/tmp/rtc/sig")
|
|
||||||
public TmpSigCO rtcSig(
|
|
||||||
AppExtCommand cmd,
|
|
||||||
@RequestParam("userId") Long userId,
|
|
||||||
@RequestParam(value = "roomId", required = false) Long roomId,
|
|
||||||
@RequestParam(value = "channelName", required = false) String channelName,
|
|
||||||
@RequestParam(value = "roomAccount", required = false) String roomAccount,
|
|
||||||
@RequestParam(value = "isPublisher", required = false) Boolean isPublisher) {
|
|
||||||
String providerRoomKey = Objects.nonNull(roomId) ? roomId.toString() : channelName;
|
|
||||||
ResponseAssert.isTrue(ResponseErrorCode.REQUEST_PARAMETER_ERROR,
|
|
||||||
StringUtils.hasText(providerRoomKey));
|
|
||||||
|
|
||||||
RtcProviderEnum provider = resolveRoomProvider(providerRoomKey, currentVersion(cmd));
|
|
||||||
boolean publisher = Boolean.TRUE.equals(isPublisher);
|
|
||||||
if (Objects.equals(RtcProviderEnum.AGORA, provider)) {
|
|
||||||
String agoraChannelName = StringUtils.hasText(channelName) ? channelName : providerRoomKey;
|
|
||||||
String token = publisher
|
|
||||||
? createChannelPublisherToken(agoraChannelName, userId)
|
|
||||||
: createChannelSubscriberToken(agoraChannelName, userId);
|
|
||||||
RtcCredentialCO credential = createAgoraCredential(agoraChannelName, token);
|
|
||||||
return new TmpSigCO()
|
|
||||||
.setRtcToken(token)
|
|
||||||
.setRtcProvider(RtcProviderEnum.AGORA.name())
|
|
||||||
.setRtcCredential(credential)
|
|
||||||
.setNewServiceToken(authClient.createIfAbsentUserCredentialToken(userId).getBody());
|
|
||||||
}
|
|
||||||
|
|
||||||
String trtcRoomIdentifier = firstText(roomAccount, channelName, providerRoomKey);
|
|
||||||
RtcCredentialCO credential = createTrtcCredential(userId, trtcRoomIdentifier, publisher);
|
|
||||||
return new TmpSigCO()
|
|
||||||
.setRtcToken(credential.getTrtcUserSig())
|
|
||||||
.setRtcProvider(RtcProviderEnum.TRTC.name())
|
|
||||||
.setRtcCredential(credential)
|
|
||||||
.setNewServiceToken(authClient.createIfAbsentUserCredentialToken(userId).getBody());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据用户信息获取用户Servicetoken
|
* 根据用户信息获取用户Servicetoken
|
||||||
*
|
*
|
||||||
@ -242,95 +174,19 @@ public class ImRestController extends BaseController {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private TmpSigCO getTmpSigByUserCredential(Long userId, String token, String json, Gson gson) {
|
private TmpSigCO getTmpSigByUserCredential(Long userId, String token, String json, Gson gson) {
|
||||||
RtcCredentialCO credential = createAgoraCredential(null, token);
|
|
||||||
try {
|
try {
|
||||||
UserCredential userCredential = gson.fromJson(json, UserCredential.class);
|
UserCredential userCredential = gson.fromJson(json, UserCredential.class);
|
||||||
return new TmpSigCO()
|
return new TmpSigCO()
|
||||||
.setRtcToken(token)
|
.setRtcToken(token)
|
||||||
.setRtcProvider(RtcProviderEnum.AGORA.name())
|
|
||||||
.setRtcCredential(credential)
|
|
||||||
.setNewServiceToken(userCredential.token());
|
.setNewServiceToken(userCredential.token());
|
||||||
} catch (JsonSyntaxException e) {
|
} catch (JsonSyntaxException e) {
|
||||||
log.error("/tmp/agora/sig类型转换错误", e);
|
log.error("/tmp/agora/sig类型转换错误", e);
|
||||||
return new TmpSigCO()
|
return new TmpSigCO()
|
||||||
.setRtcToken(token)
|
.setRtcToken(token)
|
||||||
.setRtcProvider(RtcProviderEnum.AGORA.name())
|
|
||||||
.setRtcCredential(credential)
|
|
||||||
.setNewServiceToken(authClient.createIfAbsentUserCredentialToken(userId).getBody());
|
.setNewServiceToken(authClient.createIfAbsentUserCredentialToken(userId).getBody());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private RtcProviderEnum resolveRoomProvider(String roomKey, String version) {
|
|
||||||
if (!StringUtils.hasText(roomKey)) {
|
|
||||||
return RtcVersionSupport.defaultProvider(version);
|
|
||||||
}
|
|
||||||
String cacheKey = RtcVersionSupport.roomProviderKey(roomKey.trim());
|
|
||||||
RtcProviderEnum cached = RtcProviderEnum.of(redisService.getString(cacheKey));
|
|
||||||
if (Objects.nonNull(cached)) {
|
|
||||||
return cached;
|
|
||||||
}
|
|
||||||
RtcProviderEnum provider = RtcVersionSupport.defaultProvider(version);
|
|
||||||
redisService.setIfAbsent(cacheKey, provider.name(),
|
|
||||||
RtcVersionSupport.ROOM_PROVIDER_TTL_SECONDS, TimeUnit.SECONDS);
|
|
||||||
RtcProviderEnum resolved = RtcProviderEnum.of(redisService.getString(cacheKey));
|
|
||||||
return Objects.nonNull(resolved) ? resolved : provider;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String currentVersion(AppExtCommand cmd) {
|
|
||||||
return Optional.ofNullable(cmd)
|
|
||||||
.map(AppExtCommand::getReqAppIntel)
|
|
||||||
.map(reqAppIntel -> reqAppIntel.getVersion())
|
|
||||||
.orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private RtcCredentialCO createAgoraCredential(String channelName, String token) {
|
|
||||||
return new RtcCredentialCO()
|
|
||||||
.setRtcProvider(RtcProviderEnum.AGORA.name())
|
|
||||||
.setAgoraChannelName(channelName)
|
|
||||||
.setAgoraToken(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
private RtcCredentialCO createTrtcCredential(Long userId, String roomIdentifier,
|
|
||||||
boolean publisher) {
|
|
||||||
TrtcTencetProperties trtcProperties = instantMessageProperties.getTencetTrtc();
|
|
||||||
ResponseAssert.notNull(CommonErrorCode.CONFIGURATION_ERROR, trtcProperties);
|
|
||||||
ResponseAssert.notNull(CommonErrorCode.CONFIGURATION_ERROR, trtcProperties.getSdkAppId());
|
|
||||||
ResponseAssert.isTrue(CommonErrorCode.CONFIGURATION_ERROR, StringUtils.hasText(trtcUserSigKey));
|
|
||||||
|
|
||||||
String trtcUserId = userId.toString();
|
|
||||||
String userSig = new TLSSigAPIv2(trtcProperties.getSdkAppId(), trtcUserSigKey)
|
|
||||||
.genUserSig(trtcUserId, trtcUserSigExpireSeconds);
|
|
||||||
RtcCredentialCO credential = new RtcCredentialCO()
|
|
||||||
.setRtcProvider(RtcProviderEnum.TRTC.name())
|
|
||||||
.setTrtcSdkAppId(trtcProperties.getSdkAppId())
|
|
||||||
.setTrtcUserId(trtcUserId)
|
|
||||||
.setTrtcUserSig(userSig)
|
|
||||||
.setTrtcRole(publisher ? 20 : 21)
|
|
||||||
.setTrtcUserSigExpireSeconds(trtcUserSigExpireSeconds)
|
|
||||||
.setTrtcUserSigExpireAt(
|
|
||||||
System.currentTimeMillis() + trtcUserSigExpireSeconds * 1000L);
|
|
||||||
applyTrtcRoomIdentifier(credential, roomIdentifier);
|
|
||||||
return credential;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void applyTrtcRoomIdentifier(RtcCredentialCO credential, String roomIdentifier) {
|
|
||||||
String normalizedRoomIdentifier = roomIdentifier.trim();
|
|
||||||
try {
|
|
||||||
credential.setTrtcRoomId(Long.valueOf(normalizedRoomIdentifier));
|
|
||||||
} catch (NumberFormatException ignored) {
|
|
||||||
credential.setTrtcStrRoomId(normalizedRoomIdentifier);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String firstText(String... values) {
|
|
||||||
for (String value : values) {
|
|
||||||
if (StringUtils.hasText(value)) {
|
|
||||||
return value.trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户在线状态.
|
* 用户在线状态.
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
package com.red.circle.external.clienobject;
|
package com.red.circle.external.clienobject;
|
||||||
|
|
||||||
import com.red.circle.common.business.dto.rtc.RtcCredentialCO;
|
|
||||||
import com.red.circle.framework.dto.ClientObject;
|
import com.red.circle.framework.dto.ClientObject;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
@ -25,14 +24,4 @@ public class TmpSigCO extends ClientObject {
|
|||||||
* 新服务token.
|
* 新服务token.
|
||||||
*/
|
*/
|
||||||
private String newServiceToken;
|
private String newServiceToken;
|
||||||
|
|
||||||
/**
|
|
||||||
* RTC provider: AGORA or TRTC.
|
|
||||||
*/
|
|
||||||
private String rtcProvider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provider specific credential.
|
|
||||||
*/
|
|
||||||
private RtcCredentialCO rtcCredential;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
package com.red.circle.external.inner.endpoint.message;
|
package com.red.circle.external.inner.endpoint.message;
|
||||||
|
|
||||||
import com.red.circle.common.business.dto.rtc.RtcCredentialCO;
|
|
||||||
import com.red.circle.external.inner.endpoint.message.api.TrtcClientApi;
|
import com.red.circle.external.inner.endpoint.message.api.TrtcClientApi;
|
||||||
import com.red.circle.external.inner.model.cmd.message.TrtcRemoveUserCmd;
|
import com.red.circle.external.inner.model.cmd.message.TrtcRemoveUserCmd;
|
||||||
import com.red.circle.external.inner.model.cmd.message.TrtcUserBlockedCmd;
|
import com.red.circle.external.inner.model.cmd.message.TrtcUserBlockedCmd;
|
||||||
@ -50,11 +49,4 @@ public class TrtcClientEndpoint implements TrtcClientApi {
|
|||||||
return ResultResponse.success(trtcClientService.createAgoraTokenGoUp(userId, channelName));
|
return ResultResponse.success(trtcClientService.createAgoraTokenGoUp(userId, channelName));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public ResultResponse<RtcCredentialCO> createTrtcCredential(Long userId, String roomIdentifier,
|
|
||||||
Boolean publisher) {
|
|
||||||
return ResultResponse.success(
|
|
||||||
trtcClientService.createTrtcCredential(userId, roomIdentifier, publisher));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
package com.red.circle.external.inner.service.message;
|
package com.red.circle.external.inner.service.message;
|
||||||
|
|
||||||
import com.red.circle.common.business.dto.rtc.RtcCredentialCO;
|
|
||||||
import com.red.circle.external.inner.model.cmd.message.TrtcRemoveUserCmd;
|
import com.red.circle.external.inner.model.cmd.message.TrtcRemoveUserCmd;
|
||||||
import com.red.circle.external.inner.model.cmd.message.TrtcUserBlockedCmd;
|
import com.red.circle.external.inner.model.cmd.message.TrtcUserBlockedCmd;
|
||||||
|
|
||||||
@ -38,9 +37,4 @@ public interface TrtcClientService {
|
|||||||
|
|
||||||
String createAgoraTokenGoUp(Long userId, String channelName);
|
String createAgoraTokenGoUp(Long userId, String channelName);
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建 TRTC 入房凭证.
|
|
||||||
*/
|
|
||||||
RtcCredentialCO createTrtcCredential(Long userId, String roomIdentifier, Boolean publisher);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,23 +1,17 @@
|
|||||||
package com.red.circle.external.inner.service.message.impl;
|
package com.red.circle.external.inner.service.message.impl;
|
||||||
|
|
||||||
import com.red.circle.common.business.dto.rtc.RtcCredentialCO;
|
import com.red.circle.component.instant.msg.agora.AgoraAuthentication;
|
||||||
import com.red.circle.common.business.dto.rtc.RtcProviderEnum;
|
import com.red.circle.component.instant.msg.agora.AgoraProperties;
|
||||||
import com.red.circle.component.instant.msg.InstantMessageProperties;
|
|
||||||
import com.red.circle.component.instant.msg.tencet.props.TrtcTencetProperties;
|
|
||||||
import com.red.circle.component.instant.msg.tencet.service.endpoint.api.trtc.TencentTrtcService;
|
import com.red.circle.component.instant.msg.tencet.service.endpoint.api.trtc.TencentTrtcService;
|
||||||
import com.red.circle.external.inner.model.cmd.message.TrtcRemoveUserCmd;
|
import com.red.circle.external.inner.model.cmd.message.TrtcRemoveUserCmd;
|
||||||
import com.red.circle.external.inner.model.cmd.message.TrtcUserBlockedCmd;
|
import com.red.circle.external.inner.model.cmd.message.TrtcUserBlockedCmd;
|
||||||
import com.red.circle.external.inner.service.message.TrtcClientService;
|
import com.red.circle.external.inner.service.message.TrtcClientService;
|
||||||
import com.red.circle.framework.core.asserts.ResponseAssert;
|
|
||||||
import com.red.circle.framework.core.response.CommonErrorCode;
|
|
||||||
import com.red.circle.other.inner.endpoint.user.user.UserProfileClient;
|
import com.red.circle.other.inner.endpoint.user.user.UserProfileClient;
|
||||||
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
|
import com.red.circle.other.inner.model.dto.user.UserProfileDTO;
|
||||||
import com.tencentyun.TLSSigAPIv2;
|
|
||||||
import io.agora.media.RtcTokenBuilder2;
|
import io.agora.media.RtcTokenBuilder2;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* trtc 服务.
|
* trtc 服务.
|
||||||
@ -30,7 +24,8 @@ public class TrtcClientServiceImpl implements TrtcClientService {
|
|||||||
|
|
||||||
private final UserProfileClient userProfileClient;
|
private final UserProfileClient userProfileClient;
|
||||||
private final TencentTrtcService tencentTrtcService;
|
private final TencentTrtcService tencentTrtcService;
|
||||||
private final InstantMessageProperties instantMessageProperties;
|
// private final AgoraAuthentication agoraAuthentication;
|
||||||
|
// private final AgoraProperties agoraProperties;
|
||||||
|
|
||||||
@Value("${rtc.appId}")
|
@Value("${rtc.appId}")
|
||||||
private String appId;
|
private String appId;
|
||||||
@ -38,12 +33,6 @@ public class TrtcClientServiceImpl implements TrtcClientService {
|
|||||||
@Value("${rtc.certificate}")
|
@Value("${rtc.certificate}")
|
||||||
private String certificate;
|
private String certificate;
|
||||||
|
|
||||||
@Value("${red-circle.instant-message.tencet-trtc.userSigExpireSeconds:7200}")
|
|
||||||
private long trtcUserSigExpireSeconds;
|
|
||||||
|
|
||||||
@Value("${red-circle.instant-message.tencet-trtc.userSigKey:${red-circle.instant-message.tencet-trtc.secretKey:}}")
|
|
||||||
private String trtcUserSigKey;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean removeUser(TrtcRemoveUserCmd cmd) {
|
public boolean removeUser(TrtcRemoveUserCmd cmd) {
|
||||||
return tencentTrtcService.removeUser(cmd.getRoomId(),
|
return tencentTrtcService.removeUser(cmd.getRoomId(),
|
||||||
@ -78,44 +67,4 @@ public class TrtcClientServiceImpl implements TrtcClientService {
|
|||||||
return var3.buildTokenWithUid(appId, certificate, channelName, Integer.parseInt(userProfile.getAccount()), RtcTokenBuilder2.Role.ROLE_PUBLISHER, 21600, 21600);
|
return var3.buildTokenWithUid(appId, certificate, channelName, Integer.parseInt(userProfile.getAccount()), RtcTokenBuilder2.Role.ROLE_PUBLISHER, 21600, 21600);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public RtcCredentialCO createTrtcCredential(Long userId, String roomIdentifier,
|
|
||||||
Boolean publisher) {
|
|
||||||
ResponseAssert.notNull(CommonErrorCode.REQUIRED_FIELDS_CANNOT_BE_IGNORED, userId);
|
|
||||||
ResponseAssert.isTrue(CommonErrorCode.REQUIRED_FIELDS_CANNOT_BE_IGNORED,
|
|
||||||
StringUtils.hasText(roomIdentifier));
|
|
||||||
|
|
||||||
TrtcTencetProperties trtcProperties = instantMessageProperties.getTencetTrtc();
|
|
||||||
ResponseAssert.notNull(CommonErrorCode.CONFIGURATION_ERROR, trtcProperties);
|
|
||||||
ResponseAssert.notNull(CommonErrorCode.CONFIGURATION_ERROR, trtcProperties.getSdkAppId());
|
|
||||||
ResponseAssert.isTrue(CommonErrorCode.CONFIGURATION_ERROR, StringUtils.hasText(trtcUserSigKey));
|
|
||||||
|
|
||||||
String trtcUserId = userId.toString();
|
|
||||||
String userSig = new TLSSigAPIv2(
|
|
||||||
trtcProperties.getSdkAppId(),
|
|
||||||
trtcUserSigKey
|
|
||||||
).genUserSig(trtcUserId, trtcUserSigExpireSeconds);
|
|
||||||
|
|
||||||
RtcCredentialCO credential = new RtcCredentialCO()
|
|
||||||
.setRtcProvider(RtcProviderEnum.TRTC.name())
|
|
||||||
.setTrtcSdkAppId(trtcProperties.getSdkAppId())
|
|
||||||
.setTrtcUserId(trtcUserId)
|
|
||||||
.setTrtcUserSig(userSig)
|
|
||||||
.setTrtcRole(Boolean.TRUE.equals(publisher) ? 20 : 21)
|
|
||||||
.setTrtcUserSigExpireSeconds(trtcUserSigExpireSeconds)
|
|
||||||
.setTrtcUserSigExpireAt(
|
|
||||||
System.currentTimeMillis() + trtcUserSigExpireSeconds * 1000L);
|
|
||||||
applyTrtcRoomIdentifier(credential, roomIdentifier);
|
|
||||||
return credential;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void applyTrtcRoomIdentifier(RtcCredentialCO credential, String roomIdentifier) {
|
|
||||||
String normalizedRoomIdentifier = roomIdentifier.trim();
|
|
||||||
try {
|
|
||||||
credential.setTrtcRoomId(Long.valueOf(normalizedRoomIdentifier));
|
|
||||||
} catch (NumberFormatException ignored) {
|
|
||||||
credential.setTrtcStrRoomId(normalizedRoomIdentifier);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,5 @@
|
|||||||
package com.red.circle.live.app.command.mic;
|
package com.red.circle.live.app.command.mic;
|
||||||
|
|
||||||
import com.red.circle.common.business.dto.rtc.RtcCredentialCO;
|
|
||||||
import com.red.circle.common.business.dto.rtc.RtcProviderEnum;
|
|
||||||
import com.red.circle.common.business.dto.rtc.RtcVersionSupport;
|
|
||||||
import com.red.circle.component.redis.service.RedisService;
|
import com.red.circle.component.redis.service.RedisService;
|
||||||
import com.red.circle.external.inner.endpoint.message.TrtcClient;
|
import com.red.circle.external.inner.endpoint.message.TrtcClient;
|
||||||
import com.red.circle.framework.core.asserts.ResponseAssert;
|
import com.red.circle.framework.core.asserts.ResponseAssert;
|
||||||
@ -33,7 +30,6 @@ import org.springframework.data.redis.core.RedisTemplate;
|
|||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
|
||||||
@ -62,19 +58,10 @@ public class LiveMicGoUpCmdExe {
|
|||||||
public LiveMicrophoneCO execute(MicUpDownCmd cmd) {
|
public LiveMicrophoneCO execute(MicUpDownCmd cmd) {
|
||||||
boolean targetMicAlreadySelf = false;
|
boolean targetMicAlreadySelf = false;
|
||||||
boolean goUpCompleted = false;
|
boolean goUpCompleted = false;
|
||||||
RtcProviderEnum rtcProvider = null;
|
|
||||||
try {
|
try {
|
||||||
checkPermissions(cmd);
|
checkPermissions(cmd);
|
||||||
targetMicAlreadySelf = checkTargetMicAvailableOrSelf(cmd);
|
targetMicAlreadySelf = checkTargetMicAvailableOrSelf(cmd);
|
||||||
rtcProvider = resolveRoomProvider(cmd);
|
String roomToken = createPublisherToken(cmd);
|
||||||
String roomToken = null;
|
|
||||||
RtcCredentialCO rtcCredential;
|
|
||||||
if (Objects.equals(RtcProviderEnum.AGORA, rtcProvider)) {
|
|
||||||
roomToken = createPublisherToken(cmd);
|
|
||||||
rtcCredential = createAgoraCredential(cmd, roomToken);
|
|
||||||
} else {
|
|
||||||
rtcCredential = createTrtcCredential(cmd, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
LiveMicrophoneNoticeDTO noticeDTO = liveMicrophoneGateway.goUp(
|
LiveMicrophoneNoticeDTO noticeDTO = liveMicrophoneGateway.goUp(
|
||||||
cmd.getRoomId(),
|
cmd.getRoomId(),
|
||||||
@ -83,22 +70,16 @@ public class LiveMicGoUpCmdExe {
|
|||||||
);
|
);
|
||||||
goUpCompleted = true;
|
goUpCompleted = true;
|
||||||
|
|
||||||
if (Objects.equals(RtcProviderEnum.AGORA, rtcProvider)) {
|
cachePublisherToken(cmd, roomToken);
|
||||||
cachePublisherToken(cmd, roomToken);
|
|
||||||
}
|
|
||||||
LiveMicrophoneCO notice = returnMicrophoneCO(cmd, noticeDTO);
|
LiveMicrophoneCO notice = returnMicrophoneCO(cmd, noticeDTO);
|
||||||
notice.setRoomToken(roomToken)
|
notice.setRoomToken(roomToken);
|
||||||
.setRtcProvider(rtcProvider.name())
|
|
||||||
.setRtcCredential(rtcCredential);
|
|
||||||
|
|
||||||
// 房主邀请成员上麦
|
// 房主邀请成员上麦
|
||||||
handleRoomDailyTask(cmd);
|
handleRoomDailyTask(cmd);
|
||||||
return notice;
|
return notice;
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
if (goUpCompleted) {
|
if (goUpCompleted) {
|
||||||
if (Objects.equals(RtcProviderEnum.AGORA, rtcProvider)) {
|
rollbackPublisherToken(cmd);
|
||||||
rollbackPublisherToken(cmd);
|
|
||||||
}
|
|
||||||
if (!targetMicAlreadySelf) {
|
if (!targetMicAlreadySelf) {
|
||||||
rollbackMicSeat(cmd, e);
|
rollbackMicSeat(cmd, e);
|
||||||
}
|
}
|
||||||
@ -122,60 +103,6 @@ public class LiveMicGoUpCmdExe {
|
|||||||
userAgoraTokenCacheService.save(roomToken, cmd.requiredReqUserId(), cmd.getRoomId());
|
userAgoraTokenCacheService.save(roomToken, cmd.requiredReqUserId(), cmd.getRoomId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private RtcProviderEnum resolveRoomProvider(MicUpDownCmd cmd) {
|
|
||||||
if (Objects.isNull(redisService)) {
|
|
||||||
return RtcVersionSupport.defaultProvider(currentVersion(cmd));
|
|
||||||
}
|
|
||||||
String cacheKey = RtcVersionSupport.roomProviderKey(cmd.getRoomId());
|
|
||||||
RtcProviderEnum requestedProvider = RtcVersionSupport.defaultProvider(currentVersion(cmd));
|
|
||||||
RtcProviderEnum cachedProvider = RtcProviderEnum.of(redisService.getString(cacheKey));
|
|
||||||
if (Objects.nonNull(cachedProvider)) {
|
|
||||||
ResponseAssert.isTrue(CommonErrorCode.UPGRADE_VERSION,
|
|
||||||
!Objects.equals(RtcProviderEnum.AGORA, requestedProvider)
|
|
||||||
|| !Objects.equals(RtcProviderEnum.TRTC, cachedProvider));
|
|
||||||
return cachedProvider;
|
|
||||||
}
|
|
||||||
redisService.setIfAbsent(cacheKey, requestedProvider.name(),
|
|
||||||
RtcVersionSupport.ROOM_PROVIDER_TTL_SECONDS, TimeUnit.SECONDS);
|
|
||||||
RtcProviderEnum resolvedProvider = RtcProviderEnum.of(redisService.getString(cacheKey));
|
|
||||||
return Objects.nonNull(resolvedProvider) ? resolvedProvider : requestedProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String currentVersion(MicUpDownCmd cmd) {
|
|
||||||
return Optional.ofNullable(cmd)
|
|
||||||
.map(MicUpDownCmd::getReqAppIntel)
|
|
||||||
.map(reqAppIntel -> reqAppIntel.getVersion())
|
|
||||||
.orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private RtcCredentialCO createAgoraCredential(MicUpDownCmd cmd, String token) {
|
|
||||||
return new RtcCredentialCO()
|
|
||||||
.setRtcProvider(RtcProviderEnum.AGORA.name())
|
|
||||||
.setAgoraChannelName(cmd.getRoomId().toString())
|
|
||||||
.setAgoraToken(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
private RtcCredentialCO createTrtcCredential(MicUpDownCmd cmd, boolean publisher) {
|
|
||||||
ResultResponse<RtcCredentialCO> response = trtcClient.createTrtcCredential(
|
|
||||||
cmd.requiredReqUserId(),
|
|
||||||
resolveTrtcRoomIdentifier(cmd),
|
|
||||||
publisher
|
|
||||||
);
|
|
||||||
RtcCredentialCO credential = Objects.nonNull(response) ? response.getBody() : null;
|
|
||||||
ResponseAssert.notNull(CommonErrorCode.THIRD_PARTY_SERVER_ERROR, credential);
|
|
||||||
return credential;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String resolveTrtcRoomIdentifier(MicUpDownCmd cmd) {
|
|
||||||
ResultResponse<RoomProfileDTO> response = roomManagerClient.getById(cmd.getRoomId());
|
|
||||||
RoomProfileDTO roomProfile = Objects.nonNull(response) ? response.getBody() : null;
|
|
||||||
if (Objects.nonNull(roomProfile) && Objects.nonNull(roomProfile.getRoomAccount())
|
|
||||||
&& !roomProfile.getRoomAccount().isBlank()) {
|
|
||||||
return roomProfile.getRoomAccount();
|
|
||||||
}
|
|
||||||
return cmd.getRoomId().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean checkTargetMicAvailableOrSelf(MicUpDownCmd cmd) {
|
private boolean checkTargetMicAvailableOrSelf(MicUpDownCmd cmd) {
|
||||||
boolean targetMicAlreadySelf = liveMicCacheService.checkEqSelf(
|
boolean targetMicAlreadySelf = liveMicCacheService.checkEqSelf(
|
||||||
cmd.getRoomId(),
|
cmd.getRoomId(),
|
||||||
|
|||||||
@ -2,7 +2,6 @@ package com.red.circle.live.app.dto.clientobject;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||||
import com.red.circle.common.business.dto.rtc.RtcCredentialCO;
|
|
||||||
import com.red.circle.framework.dto.ClientObject;
|
import com.red.circle.framework.dto.ClientObject;
|
||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@ -53,14 +52,4 @@ public class LiveMicrophoneCO extends ClientObject {
|
|||||||
*/
|
*/
|
||||||
private String roomToken;
|
private String roomToken;
|
||||||
|
|
||||||
/**
|
|
||||||
* RTC provider: AGORA or TRTC.
|
|
||||||
*/
|
|
||||||
private String rtcProvider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* RTC credential for clients that support provider negotiation.
|
|
||||||
*/
|
|
||||||
private RtcCredentialCO rtcCredential;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,6 @@
|
|||||||
package com.red.circle.other.app.command.room;
|
package com.red.circle.other.app.command.room;
|
||||||
|
|
||||||
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
|
import com.red.circle.common.business.core.enums.SysOriginPlatformEnum;
|
||||||
import com.red.circle.common.business.dto.rtc.RtcCredentialCO;
|
|
||||||
import com.red.circle.common.business.dto.rtc.RtcProviderEnum;
|
|
||||||
import com.red.circle.common.business.dto.rtc.RtcVersionSupport;
|
|
||||||
import com.red.circle.external.inner.endpoint.message.ImGroupClient;
|
import com.red.circle.external.inner.endpoint.message.ImGroupClient;
|
||||||
import com.red.circle.external.inner.endpoint.message.TrtcClient;
|
import com.red.circle.external.inner.endpoint.message.TrtcClient;
|
||||||
import com.red.circle.external.inner.model.cmd.message.CreateGroupCmd;
|
import com.red.circle.external.inner.model.cmd.message.CreateGroupCmd;
|
||||||
@ -124,20 +121,12 @@ public class RoomEnterCmdExe {
|
|||||||
);
|
);
|
||||||
|
|
||||||
ResponseAssert.notNull(UserErrorCode.USER_INFO_NOT_FOUND, ownUserProfile);
|
ResponseAssert.notNull(UserErrorCode.USER_INFO_NOT_FOUND, ownUserProfile);
|
||||||
RtcProviderEnum rtcProvider = resolveRoomProvider(cmd);
|
//String token = createAgoraToken(cmd);
|
||||||
String token = null;
|
String token = userAgoraTokenCacheService.getUserAgoraToken(cmd.getReqUserId(), cmd.getRoomId());
|
||||||
RtcCredentialCO rtcCredential;
|
if (Objects.isNull(token)) {
|
||||||
if (Objects.equals(RtcProviderEnum.AGORA, rtcProvider)) {
|
token = trtcClient.createAgoraToken(cmd.getReqUserId(), cmd.getRoomId().toString()).getBody();
|
||||||
token = userAgoraTokenCacheService.getUserAgoraToken(cmd.getReqUserId(), cmd.getRoomId());
|
log.warn("进房间token:{}", token);
|
||||||
if (Objects.isNull(token)) {
|
userAgoraTokenCacheService.save(token, cmd.getReqUserId(), cmd.getRoomId());
|
||||||
token = trtcClient.createAgoraToken(cmd.getReqUserId(), cmd.getRoomId().toString())
|
|
||||||
.getBody();
|
|
||||||
log.warn("进房间token:{}", token);
|
|
||||||
userAgoraTokenCacheService.save(token, cmd.getReqUserId(), cmd.getRoomId());
|
|
||||||
}
|
|
||||||
rtcCredential = createAgoraCredential(cmd, token);
|
|
||||||
} else {
|
|
||||||
rtcCredential = createTrtcCredential(cmd, manager, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -173,9 +162,7 @@ public class RoomEnterCmdExe {
|
|||||||
cmd.getRoomId()))
|
cmd.getRoomId()))
|
||||||
.setLevel(getUserLevel(cmd.requireReqSysOriginEnum(), cmd.getReqUserId()))
|
.setLevel(getUserLevel(cmd.requireReqSysOriginEnum(), cmd.getReqUserId()))
|
||||||
.setNobleVipAbility(listUserPropsVipActualEquity(cmd))
|
.setNobleVipAbility(listUserPropsVipActualEquity(cmd))
|
||||||
.setRoomToken(token)
|
.setRoomToken(token)
|
||||||
.setRtcProvider(rtcProvider.name())
|
|
||||||
.setRtcCredential(rtcCredential)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,56 +231,6 @@ public class RoomEnterCmdExe {
|
|||||||
return agoraToken.get();
|
return agoraToken.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
private RtcProviderEnum resolveRoomProvider(RoomEntryCmd cmd) {
|
|
||||||
String cacheKey = RtcVersionSupport.roomProviderKey(cmd.getRoomId());
|
|
||||||
RtcProviderEnum requestedProvider = RtcVersionSupport.defaultProvider(currentVersion(cmd));
|
|
||||||
RtcProviderEnum cachedProvider = RtcProviderEnum.of(redisService.getString(cacheKey));
|
|
||||||
if (Objects.nonNull(cachedProvider)) {
|
|
||||||
ResponseAssert.isTrue(CommonErrorCode.UPGRADE_VERSION,
|
|
||||||
!Objects.equals(RtcProviderEnum.AGORA, requestedProvider)
|
|
||||||
|| !Objects.equals(RtcProviderEnum.TRTC, cachedProvider));
|
|
||||||
return cachedProvider;
|
|
||||||
}
|
|
||||||
redisService.setIfAbsent(cacheKey, requestedProvider.name(),
|
|
||||||
RtcVersionSupport.ROOM_PROVIDER_TTL_SECONDS, TimeUnit.SECONDS);
|
|
||||||
RtcProviderEnum resolvedProvider = RtcProviderEnum.of(redisService.getString(cacheKey));
|
|
||||||
return Objects.nonNull(resolvedProvider) ? resolvedProvider : requestedProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String currentVersion(RoomEntryCmd cmd) {
|
|
||||||
return Optional.ofNullable(cmd)
|
|
||||||
.map(RoomEntryCmd::getReqAppIntel)
|
|
||||||
.map(reqAppIntel -> reqAppIntel.getVersion())
|
|
||||||
.orElse(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private RtcCredentialCO createAgoraCredential(RoomEntryCmd cmd, String token) {
|
|
||||||
return new RtcCredentialCO()
|
|
||||||
.setRtcProvider(RtcProviderEnum.AGORA.name())
|
|
||||||
.setAgoraChannelName(cmd.getRoomId().toString())
|
|
||||||
.setAgoraToken(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
private RtcCredentialCO createTrtcCredential(RoomEntryCmd cmd, RoomProfileManager manager,
|
|
||||||
boolean publisher) {
|
|
||||||
ResultResponse<RtcCredentialCO> response = trtcClient.createTrtcCredential(
|
|
||||||
cmd.getReqUserId(),
|
|
||||||
resolveTrtcRoomIdentifier(cmd, manager),
|
|
||||||
publisher
|
|
||||||
);
|
|
||||||
RtcCredentialCO credential = Objects.nonNull(response) ? response.getBody() : null;
|
|
||||||
ResponseAssert.notNull(CommonErrorCode.THIRD_PARTY_SERVER_ERROR, credential);
|
|
||||||
return credential;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String resolveTrtcRoomIdentifier(RoomEntryCmd cmd, RoomProfileManager manager) {
|
|
||||||
if (Objects.nonNull(manager) && Objects.nonNull(manager.getRoomAccount())
|
|
||||||
&& !manager.getRoomAccount().isBlank()) {
|
|
||||||
return manager.getRoomAccount();
|
|
||||||
}
|
|
||||||
return cmd.getRoomId().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<PropsVipActualEquityEnum> listUserPropsVipActualEquity(RoomEntryCmd cmd) {
|
private List<PropsVipActualEquityEnum> listUserPropsVipActualEquity(RoomEntryCmd cmd) {
|
||||||
return userProfileGateway.listUserActualEquityEnum(cmd.requiredReqUserId());
|
return userProfileGateway.listUserActualEquityEnum(cmd.requiredReqUserId());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
package com.red.circle.other.app.dto.clientobject.room;
|
package com.red.circle.other.app.dto.clientobject.room;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.red.circle.common.business.dto.rtc.RtcCredentialCO;
|
|
||||||
import com.red.circle.framework.dto.ClientObject;
|
import com.red.circle.framework.dto.ClientObject;
|
||||||
import com.red.circle.other.inner.enums.live.RoomUserRolesEnum;
|
import com.red.circle.other.inner.enums.live.RoomUserRolesEnum;
|
||||||
import com.red.circle.other.inner.enums.material.PropsVipActualEquityEnum;
|
import com.red.circle.other.inner.enums.material.PropsVipActualEquityEnum;
|
||||||
@ -42,14 +41,4 @@ public class EntryRoomEntrantsCO extends ClientObject {
|
|||||||
*/
|
*/
|
||||||
private String roomToken;
|
private String roomToken;
|
||||||
|
|
||||||
/**
|
|
||||||
* RTC provider: AGORA or TRTC.
|
|
||||||
*/
|
|
||||||
private String rtcProvider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* RTC credential for clients that support provider negotiation.
|
|
||||||
*/
|
|
||||||
private RtcCredentialCO rtcCredential;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,10 +32,10 @@ public class IpCountryUtils {
|
|||||||
"香港", "澳门", "澳門", "台湾", "台灣", "Hong Kong", "Macau", "Macao", "Taiwan"
|
"香港", "澳门", "澳門", "台湾", "台灣", "Hong Kong", "Macau", "Macao", "Taiwan"
|
||||||
);
|
);
|
||||||
private static final List<String> BLOCKED_COUNTRY_CODES = List.of(
|
private static final List<String> BLOCKED_COUNTRY_CODES = List.of(
|
||||||
"MO", "SG"
|
"MO", "SG", "TW"
|
||||||
);
|
);
|
||||||
private static final List<String> BLOCKED_COUNTRY_NAMES = List.of(
|
private static final List<String> BLOCKED_COUNTRY_NAMES = List.of(
|
||||||
"澳门", "澳門", "Macau", "Macao", "新加坡", "Singapore"
|
"澳门", "澳門", "台湾", "台灣", "Macau", "Macao", "Taiwan", "新加坡", "Singapore"
|
||||||
);
|
);
|
||||||
private static final List<IpGeoProvider> IP_GEO_PROVIDERS = List.of(
|
private static final List<IpGeoProvider> IP_GEO_PROVIDERS = List.of(
|
||||||
new IpGeoProvider("ip.sb", "https://api.ip.sb/geoip/%s"),
|
new IpGeoProvider("ip.sb", "https://api.ip.sb/geoip/%s"),
|
||||||
|
|||||||
@ -99,17 +99,17 @@ public class IpCountryUtilsTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void allowTaiwanRegion() {
|
public void blockTaiwanRegion() {
|
||||||
IpCountryUtils.IpGeoData data = new IpCountryUtils.IpGeoData("CN", "中国", "台湾", "test");
|
IpCountryUtils.IpGeoData data = new IpCountryUtils.IpGeoData("CN", "中国", "台湾", "test");
|
||||||
|
|
||||||
assertFalse(IpCountryUtils.isMainlandChina(data));
|
assertFalse(IpCountryUtils.isMainlandChina(data));
|
||||||
assertFalse(IpCountryUtils.isBlockedIpRegion(data));
|
assertTrue(IpCountryUtils.isBlockedIpRegion(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void allowTaiwanCountryCode() {
|
public void blockTaiwanCountryCode() {
|
||||||
IpCountryUtils.IpGeoData data = new IpCountryUtils.IpGeoData("TW", "Taiwan", "", "test");
|
IpCountryUtils.IpGeoData data = new IpCountryUtils.IpGeoData("TW", "Taiwan", "", "test");
|
||||||
|
|
||||||
assertFalse(IpCountryUtils.isBlockedIpRegion(data));
|
assertTrue(IpCountryUtils.isBlockedIpRegion(data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user