add===>:增加医生排班、视频问诊、websocket。
This commit is contained in:
parent
e8f6a27df4
commit
f77b1815bf
@ -169,3 +169,10 @@ xss:
|
|||||||
excludes: /system/notice
|
excludes: /system/notice
|
||||||
# 匹配链接
|
# 匹配链接
|
||||||
urlPatterns: /system/*,/monitor/*,/tool/*
|
urlPatterns: /system/*,/monitor/*,/tool/*
|
||||||
|
|
||||||
|
# 腾讯云音视频
|
||||||
|
trtc:
|
||||||
|
sdkappid: 1400236771
|
||||||
|
sdksecretkey: 83ab78d1a8513af6626d58cc2bacd7b28bfb2af06515fa02b0204129ebb53422
|
||||||
|
secretid: AKIDOBpP2ICALat0wP4lcIiAMtZ7XgUJ5vMO
|
||||||
|
secretkey: zxjJhGcx75lECyweHgphKYefWCkBPSHt
|
||||||
|
|||||||
@ -17,6 +17,17 @@
|
|||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Spring框架基本的核心工具 -->
|
<!-- Spring框架基本的核心工具 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework</groupId>
|
<groupId>org.springframework</groupId>
|
||||||
@ -135,6 +146,40 @@
|
|||||||
<groupId>org.projectlombok</groupId>
|
<groupId>org.projectlombok</groupId>
|
||||||
<artifactId>lombok</artifactId>
|
<artifactId>lombok</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-websocket</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okio</groupId>
|
||||||
|
<artifactId>okio</artifactId>
|
||||||
|
<version>1.12.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okhttp</groupId>
|
||||||
|
<artifactId>okhttp</artifactId>
|
||||||
|
<version>2.7.5</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.gson</groupId>
|
||||||
|
<artifactId>gson</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>javax.xml.bind</groupId>
|
||||||
|
<artifactId>jaxb-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!--糊涂工具 https://github.com/looly/hutool/-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-all</artifactId>
|
||||||
|
<version>5.4.7</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.tomcat.embed</groupId>
|
||||||
|
<artifactId>tomcat-embed-websocket</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
@ -0,0 +1,55 @@
|
|||||||
|
package com.xinelu.common.core.dto;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shitianqi <br/>
|
||||||
|
* 2022-01-19 19:02 <br/>
|
||||||
|
* 长连接消息模板
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class MessageTemplate {
|
||||||
|
/**
|
||||||
|
* 发送消息对象key值(消息来源)
|
||||||
|
*/
|
||||||
|
private String fromKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送消息对象Name值(消息来源)
|
||||||
|
*/
|
||||||
|
private String fromName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接收消息对象key值(消息去向)
|
||||||
|
*/
|
||||||
|
private String toKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接收消息对象name值(消息去向)
|
||||||
|
*/
|
||||||
|
private String toName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息内容(Json)
|
||||||
|
*/
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消息类型(标识在{@link com.xinelu.common.enums.MessageContentType}中)
|
||||||
|
*/
|
||||||
|
private String msgType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送时间
|
||||||
|
* */
|
||||||
|
private Date sendTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 问诊记录业务主键
|
||||||
|
*/
|
||||||
|
private String recordId;
|
||||||
|
|
||||||
|
/** 问诊房间号 */
|
||||||
|
private String roomNo;
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
package com.xinelu.common.enums;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shitainqi<br/>
|
||||||
|
* 2022-01-18 21:01
|
||||||
|
* 长连接内容对象枚举列表(在此处增加长连接返回对象)
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
public enum MessageContentType {
|
||||||
|
|
||||||
|
DEVICE,
|
||||||
|
NOTICE,
|
||||||
|
PUSH,
|
||||||
|
CHAT,
|
||||||
|
/** 会诊 */
|
||||||
|
CONSULTATION,
|
||||||
|
/** 问诊 */
|
||||||
|
VIDEO
|
||||||
|
}
|
||||||
@ -0,0 +1,74 @@
|
|||||||
|
package com.xinelu.common.socket;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.websocket.OnClose;
|
||||||
|
import javax.websocket.OnError;
|
||||||
|
import javax.websocket.OnMessage;
|
||||||
|
import javax.websocket.OnOpen;
|
||||||
|
import javax.websocket.Session;
|
||||||
|
import javax.websocket.server.PathParam;
|
||||||
|
import javax.websocket.server.ServerEndpoint;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@ServerEndpoint(value = "/webSocket/{key}")
|
||||||
|
public class WebSocket {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 连接建立成功调用的方法
|
||||||
|
*/
|
||||||
|
@OnOpen
|
||||||
|
public void onOpen(@PathParam(value = "key") String key, Session session) throws IOException {
|
||||||
|
if (StringUtils.isNotBlank(key)) {
|
||||||
|
WebSocketUtils.add(key, session);
|
||||||
|
} else {
|
||||||
|
session.getAsyncRemote().sendText("来自服务器的消息:您未传递key值");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 连接关闭调用的方法
|
||||||
|
*/
|
||||||
|
@OnClose
|
||||||
|
public void onClose(@PathParam("key") String key) throws IOException {
|
||||||
|
WebSocketUtils.remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 收到客户端消息后调用的方法
|
||||||
|
*
|
||||||
|
* @param message 客户端发送过来的消息
|
||||||
|
*/
|
||||||
|
@OnMessage
|
||||||
|
public void onMessage(String message, Session fromSession) {
|
||||||
|
if (message.equals("ping")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (Map.Entry<String, Session> sessionEntry : WebSocketUtils.clients.entrySet()) {
|
||||||
|
// 获取自己
|
||||||
|
if (fromSession.getId().equals(sessionEntry.getValue().getId())) {
|
||||||
|
//打印消息
|
||||||
|
WebSocketUtils.receive(sessionEntry.getKey(), message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@OnError
|
||||||
|
public void onError(Session session, Throwable error) throws IOException {
|
||||||
|
for (Map.Entry<String, Session> sessionEntry : WebSocketUtils.clients.entrySet()) {
|
||||||
|
// 获取自己
|
||||||
|
if (session.getId().equals(sessionEntry.getValue().getId())) {
|
||||||
|
//清除异常连接
|
||||||
|
WebSocketUtils.remove(sessionEntry.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.error("发生错误");
|
||||||
|
error.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
package com.xinelu.common.socket;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class WebSocketConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注入一个ServerEndpointExporter,该Bean会自动注册使用@ServerEndpoint注解申明的websocket endpoint
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public ServerEndpointExporter serverEndpointExporter() {
|
||||||
|
return new ServerEndpointExporter();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,102 @@
|
|||||||
|
package com.xinelu.common.socket;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.xinelu.common.core.dto.MessageTemplate;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import javax.websocket.Session;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shitianqi
|
||||||
|
* 2022-01-18 19:17
|
||||||
|
* socket类和请求和方法
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class WebSocketUtils {
|
||||||
|
|
||||||
|
|
||||||
|
//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
|
||||||
|
/**
|
||||||
|
* 记录当前在线连接数
|
||||||
|
*/
|
||||||
|
public static AtomicInteger onlineCount = new AtomicInteger();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 存放所有在线的客户端
|
||||||
|
*/
|
||||||
|
public static ConcurrentHashMap<String, Session> clients = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shitianqi <br/>
|
||||||
|
* 2022-01-18 19:47 <br/>
|
||||||
|
* 上线用户 <br/>
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @param session
|
||||||
|
*/
|
||||||
|
public static void add(String key, Session session) throws IOException {
|
||||||
|
remove(key);
|
||||||
|
clients.put(key, session);
|
||||||
|
onlineCount.incrementAndGet(); // 在线数加1
|
||||||
|
int count = onlineCount.get();
|
||||||
|
log.info("有新连接加入:{},当前在线人数为:{}", key, count > 0? count: 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shitianqi <br/>
|
||||||
|
* 2022-01-18 19:47 <br/>
|
||||||
|
* 打印某在线用户接收消息内容和在线情况到日志 <br/>
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
public static void receive(String key, String message) {
|
||||||
|
log.info("服务端收到客户端[{}]的消息:{}", key, message);
|
||||||
|
// log.info("当前连接数 = " + clients.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shitianqi <br/>
|
||||||
|
* 2022-01-18 19:47 <br/>
|
||||||
|
* 下线用户 <br/>
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
*/
|
||||||
|
public static void remove(String key) throws IOException {
|
||||||
|
if (clients.containsKey(key)) {
|
||||||
|
clients.get(key).close();
|
||||||
|
clients.remove(key);
|
||||||
|
onlineCount.decrementAndGet(); // 在线数减1
|
||||||
|
// log.info("有一连接关闭:{},当前在线人数为:{}", key, onlineCount.get());
|
||||||
|
}
|
||||||
|
// log.info("当前连接数 = " + clients.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* shitianqi <br/>
|
||||||
|
* 2022-01-18 19:47 <br/>
|
||||||
|
* 发送消息(内容为对象json) <br/>
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @param msg
|
||||||
|
* @return boolean 是否成功
|
||||||
|
*/
|
||||||
|
public static boolean sendMessage(String key, MessageTemplate msg) {
|
||||||
|
// log.info("当前连接数 = " + clients.size());
|
||||||
|
if (clients.get(key) == null) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
log.info("发送消息:" + JSON.toJSONString(msg));
|
||||||
|
clients.get(key).getBasicRemote().sendText(JSON.toJSONString(msg));
|
||||||
|
return true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,521 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 THL A29 Limited, a Tencent company. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.xinelu.common.utils.tencentcloudapi.common;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.JsonSyntaxException;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
import com.squareup.okhttp.Headers;
|
||||||
|
import com.squareup.okhttp.Headers.Builder;
|
||||||
|
import com.squareup.okhttp.Response;
|
||||||
|
import com.xinelu.common.utils.tencentcloudapi.common.exception.TencentCloudSDKException;
|
||||||
|
import com.xinelu.common.utils.tencentcloudapi.common.http.HttpConnection;
|
||||||
|
import com.xinelu.common.utils.tencentcloudapi.common.profile.ClientProfile;
|
||||||
|
import com.xinelu.common.utils.tencentcloudapi.common.profile.HttpProfile;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.sql.Date;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
import java.util.UUID;
|
||||||
|
import javax.crypto.Mac;
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.xml.bind.DatatypeConverter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 抽象client类
|
||||||
|
*/
|
||||||
|
abstract public class AbstractClient {
|
||||||
|
|
||||||
|
public static final int HTTP_RSP_OK = 200;
|
||||||
|
public static final String SDK_VERSION = "SDK_JAVA_3.0.89";
|
||||||
|
|
||||||
|
|
||||||
|
private Credential credential;
|
||||||
|
private ClientProfile profile;
|
||||||
|
private String endpoint;
|
||||||
|
private String region;
|
||||||
|
private String path;
|
||||||
|
private String sdkVersion;
|
||||||
|
private String apiVersion;
|
||||||
|
public Gson gson;
|
||||||
|
|
||||||
|
public AbstractClient(String endpoint, String version, Credential credential, String region) {
|
||||||
|
this(endpoint, version, credential, region, new ClientProfile());
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractClient(String endpoint, String version, Credential credential, String region,
|
||||||
|
ClientProfile profile) {
|
||||||
|
|
||||||
|
this.credential = credential;
|
||||||
|
this.profile = profile;
|
||||||
|
this.endpoint = endpoint;
|
||||||
|
this.region = region;
|
||||||
|
this.path = "/";
|
||||||
|
this.sdkVersion = AbstractClient.SDK_VERSION;
|
||||||
|
this.apiVersion = version;
|
||||||
|
this.gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
|
||||||
|
warmup();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置产品地域
|
||||||
|
*
|
||||||
|
* @param region
|
||||||
|
* 产品地域
|
||||||
|
*/
|
||||||
|
public void setRegion(String region) {
|
||||||
|
this.region = region;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回产品地域
|
||||||
|
*
|
||||||
|
* @return 地域名称
|
||||||
|
*/
|
||||||
|
public String getRegion() {
|
||||||
|
return this.region;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置配置实例
|
||||||
|
*
|
||||||
|
* @param profile
|
||||||
|
* 配置实例
|
||||||
|
*/
|
||||||
|
public void setClientProfile(ClientProfile profile) {
|
||||||
|
this.profile = profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取配置实例
|
||||||
|
*
|
||||||
|
* @return 配置实例
|
||||||
|
*/
|
||||||
|
public ClientProfile getClientProfile() {
|
||||||
|
return this.profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置认证信息实例
|
||||||
|
*
|
||||||
|
* @param credential
|
||||||
|
* 认证信息实例
|
||||||
|
*/
|
||||||
|
public void setCredential(Credential credential) {
|
||||||
|
this.credential = credential;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取认证信息实例
|
||||||
|
*
|
||||||
|
* @return 认证信息实例
|
||||||
|
*/
|
||||||
|
public Credential getCredential() {
|
||||||
|
return this.credential;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use post/json with tc3-hmac-sha256 signature to call any action. Ignore
|
||||||
|
* request method and signature method defined in profile.
|
||||||
|
*
|
||||||
|
* @param action
|
||||||
|
* Name of action to be called.
|
||||||
|
* @param jsonPayload
|
||||||
|
* Parameters of action serialized in json string format.
|
||||||
|
* @return Raw response from API if request succeeded, otherwise an exception
|
||||||
|
* will be raised instead of raw response
|
||||||
|
* @throws TencentCloudSDKException
|
||||||
|
*/
|
||||||
|
public String call(String action, String jsonPayload) throws TencentCloudSDKException {
|
||||||
|
String endpoint = this.endpoint;
|
||||||
|
// in case user has reset endpoint after init this client
|
||||||
|
if (!(this.profile.getHttpProfile().getEndpoint() == null)) {
|
||||||
|
endpoint = this.profile.getHttpProfile().getEndpoint();
|
||||||
|
}
|
||||||
|
// always use post tc3-hmac-sha256 signature process
|
||||||
|
// okhttp always set charset even we don't specify it,
|
||||||
|
// to ensure signature be correct, we have to set it here as well.
|
||||||
|
String contentType = "application/json; charset=utf-8";
|
||||||
|
byte[] requestPayload = jsonPayload.getBytes();
|
||||||
|
String canonicalUri = "/";
|
||||||
|
String canonicalQueryString = "";
|
||||||
|
String canonicalHeaders = "content-type:" + contentType + "\nhost:" + endpoint + "\n";
|
||||||
|
String signedHeaders = "content-type;host";
|
||||||
|
|
||||||
|
String hashedRequestPayload = "";
|
||||||
|
if (this.profile.isUnsignedPayload()) {
|
||||||
|
hashedRequestPayload = Sign.sha256Hex("UNSIGNED-PAYLOAD".getBytes());
|
||||||
|
} else {
|
||||||
|
hashedRequestPayload = Sign.sha256Hex(requestPayload);
|
||||||
|
}
|
||||||
|
String canonicalRequest = HttpProfile.REQ_POST + "\n" + canonicalUri + "\n" + canonicalQueryString + "\n"
|
||||||
|
+ canonicalHeaders + "\n" + signedHeaders + "\n" + hashedRequestPayload;
|
||||||
|
|
||||||
|
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||||
|
String date = sdf.format(new Date(Long.valueOf(timestamp + "000")));
|
||||||
|
String service = endpoint.split("\\.")[0];
|
||||||
|
String credentialScope = date + "/" + service + "/" + "tc3_request";
|
||||||
|
String hashedCanonicalRequest = Sign.sha256Hex(canonicalRequest.getBytes());
|
||||||
|
String stringToSign = "TC3-HMAC-SHA256\n" + timestamp + "\n" + credentialScope + "\n" + hashedCanonicalRequest;
|
||||||
|
|
||||||
|
String secretId = this.credential.getSecretId();
|
||||||
|
String secretKey = this.credential.getSecretKey();
|
||||||
|
byte[] secretDate = Sign.hmac256(("TC3" + secretKey).getBytes(), date);
|
||||||
|
byte[] secretService = Sign.hmac256(secretDate, service);
|
||||||
|
byte[] secretSigning = Sign.hmac256(secretService, "tc3_request");
|
||||||
|
String signature = DatatypeConverter.printHexBinary(Sign.hmac256(secretSigning, stringToSign)).toLowerCase();
|
||||||
|
String authorization = "TC3-HMAC-SHA256 " + "Credential=" + secretId + "/" + credentialScope + ", "
|
||||||
|
+ "SignedHeaders=" + signedHeaders + ", " + "Signature=" + signature;
|
||||||
|
|
||||||
|
HttpConnection conn = new HttpConnection(this.profile.getHttpProfile().getConnTimeout(),
|
||||||
|
this.profile.getHttpProfile().getReadTimeout(), this.profile.getHttpProfile().getWriteTimeout());
|
||||||
|
String url = this.profile.getHttpProfile().getProtocol() + endpoint + this.path;
|
||||||
|
Builder hb = new Headers.Builder();
|
||||||
|
hb.add("Content-Type", contentType).add("Host", endpoint).add("Authorization", authorization)
|
||||||
|
.add("X-TC-Action", action).add("X-TC-Timestamp", timestamp).add("X-TC-Version", this.apiVersion)
|
||||||
|
.add("X-TC-Region", this.getRegion()).add("X-TC-RequestClient", SDK_VERSION);
|
||||||
|
String token = this.credential.getToken();
|
||||||
|
if (token != null && !token.isEmpty()) {
|
||||||
|
hb.add("X-TC-Token", token);
|
||||||
|
}
|
||||||
|
if (this.profile.isUnsignedPayload()) {
|
||||||
|
hb.add("X-TC-Content-SHA256", "UNSIGNED-PAYLOAD");
|
||||||
|
}
|
||||||
|
|
||||||
|
Headers headers = hb.build();
|
||||||
|
Response resp = conn.postRequest(url, requestPayload, headers);
|
||||||
|
if (resp.code() != AbstractClient.HTTP_RSP_OK) {
|
||||||
|
throw new TencentCloudSDKException(resp.code() + resp.message());
|
||||||
|
}
|
||||||
|
String respbody = null;
|
||||||
|
try {
|
||||||
|
respbody = resp.body().string();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new TencentCloudSDKException(e.getClass().getName() + "-" + e.getMessage());
|
||||||
|
}
|
||||||
|
JsonResponseModel<JsonResponseErrModel> errResp = null;
|
||||||
|
try {
|
||||||
|
Type errType = new TypeToken<JsonResponseModel<JsonResponseErrModel>>() {
|
||||||
|
}.getType();
|
||||||
|
errResp = gson.fromJson(respbody, errType);
|
||||||
|
} catch (JsonSyntaxException e) {
|
||||||
|
throw new TencentCloudSDKException(e.getClass().getName() + "-" + e.getMessage());
|
||||||
|
}
|
||||||
|
if (errResp.response.error != null) {
|
||||||
|
throw new TencentCloudSDKException(errResp.response.error.code + "-" + errResp.response.error.message,
|
||||||
|
errResp.response.requestId);
|
||||||
|
}
|
||||||
|
return respbody;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String internalRequest(AbstractModel request, String actionName) throws TencentCloudSDKException {
|
||||||
|
Response okRsp = null;
|
||||||
|
String endpoint = this.endpoint;
|
||||||
|
if (!(this.profile.getHttpProfile().getEndpoint() == null)) {
|
||||||
|
endpoint = this.profile.getHttpProfile().getEndpoint();
|
||||||
|
}
|
||||||
|
String [] binaryParams = request.getBinaryParams();
|
||||||
|
String sm = this.profile.getSignMethod();
|
||||||
|
String reqMethod = this.profile.getHttpProfile().getReqMethod();
|
||||||
|
|
||||||
|
// currently, customized params only can be supported via post json tc3-hmac-sha256
|
||||||
|
HashMap<String, Object> customizedParams = request.any();
|
||||||
|
if (customizedParams.size() > 0) {
|
||||||
|
if (binaryParams.length > 0) {
|
||||||
|
throw new TencentCloudSDKException("WrongUsage: Cannot post multipart with customized parameters.");
|
||||||
|
}
|
||||||
|
if (sm.equals(ClientProfile.SIGN_SHA1) || sm.equals(ClientProfile.SIGN_SHA256)) {
|
||||||
|
throw new TencentCloudSDKException("WrongUsage: Cannot use HmacSHA1 or HmacSHA256 with customized parameters.");
|
||||||
|
}
|
||||||
|
if (reqMethod.equals(HttpProfile.REQ_GET)) {
|
||||||
|
throw new TencentCloudSDKException("WrongUsage: Cannot use get method with customized parameters.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (binaryParams.length > 0 || sm.equals(ClientProfile.SIGN_TC3_256)) {
|
||||||
|
okRsp = doRequestWithTC3(endpoint, request, actionName);
|
||||||
|
} else if (sm.equals(ClientProfile.SIGN_SHA1) || sm.equals(ClientProfile.SIGN_SHA256)) {
|
||||||
|
okRsp = doRequest(endpoint, request, actionName);
|
||||||
|
} else {
|
||||||
|
throw new TencentCloudSDKException("Signature method " + sm + " is invalid or not supported yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (okRsp.code() != AbstractClient.HTTP_RSP_OK) {
|
||||||
|
throw new TencentCloudSDKException(okRsp.code() + okRsp.message());
|
||||||
|
}
|
||||||
|
String strResp = null;
|
||||||
|
try {
|
||||||
|
strResp = okRsp.body().string();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new TencentCloudSDKException(e.getClass().getName() + "-" + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonResponseModel<JsonResponseErrModel> errResp = null;
|
||||||
|
try {
|
||||||
|
Type errType = new TypeToken<JsonResponseModel<JsonResponseErrModel>>() {
|
||||||
|
}.getType();
|
||||||
|
errResp = gson.fromJson(strResp, errType);
|
||||||
|
} catch (JsonSyntaxException e) {
|
||||||
|
throw new TencentCloudSDKException(e.getClass().getName() + "-" + e.getMessage());
|
||||||
|
}
|
||||||
|
if (errResp.response.error != null) {
|
||||||
|
throw new TencentCloudSDKException(errResp.response.error.code + "-" + errResp.response.error.message,
|
||||||
|
errResp.response.requestId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return strResp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response doRequest(String endpoint, AbstractModel request, String action) throws TencentCloudSDKException {
|
||||||
|
HashMap<String, String> param = new HashMap<String, String>();
|
||||||
|
request.toMap(param, "");
|
||||||
|
String strParam = this.formatRequestData(action, param);
|
||||||
|
HttpConnection conn = new HttpConnection(
|
||||||
|
this.profile.getHttpProfile().getConnTimeout(),
|
||||||
|
this.profile.getHttpProfile().getReadTimeout(),
|
||||||
|
this.profile.getHttpProfile().getWriteTimeout());
|
||||||
|
String reqMethod = this.profile.getHttpProfile().getReqMethod();
|
||||||
|
String url = this.profile.getHttpProfile().getProtocol() + endpoint + this.path;
|
||||||
|
if (reqMethod.equals(HttpProfile.REQ_GET)) {
|
||||||
|
return conn.getRequest(url + "?" + strParam);
|
||||||
|
} else if (reqMethod.equals(HttpProfile.REQ_POST)) {
|
||||||
|
return conn.postRequest(url, strParam);
|
||||||
|
} else {
|
||||||
|
throw new TencentCloudSDKException("Method only support (GET, POST)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response doRequestWithTC3(String endpoint, AbstractModel request, String action) throws TencentCloudSDKException {
|
||||||
|
String httpRequestMethod = this.profile.getHttpProfile().getReqMethod();
|
||||||
|
if (httpRequestMethod == null) {
|
||||||
|
throw new TencentCloudSDKException("Request method should not be null, can only be GET or POST");
|
||||||
|
}
|
||||||
|
String contentType = "application/x-www-form-urlencoded";
|
||||||
|
byte [] requestPayload = "".getBytes();
|
||||||
|
HashMap<String, String> params = new HashMap<String, String>();
|
||||||
|
request.toMap(params, "");
|
||||||
|
String [] binaryParams = request.getBinaryParams();
|
||||||
|
if ( binaryParams.length > 0 ) {
|
||||||
|
httpRequestMethod = HttpProfile.REQ_POST;
|
||||||
|
String boundary = UUID.randomUUID().toString();
|
||||||
|
// okhttp always set charset even we don't specify it,
|
||||||
|
// to ensure signature be correct, we have to set it here as well.
|
||||||
|
contentType = "multipart/form-data; charset=utf-8" + "; boundary=" + boundary;
|
||||||
|
try {
|
||||||
|
requestPayload = getMultipartPayload(request, boundary);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new TencentCloudSDKException("Failed to generate multipart. because: " + e);
|
||||||
|
}
|
||||||
|
} else if (httpRequestMethod.equals(HttpProfile.REQ_POST)) {
|
||||||
|
requestPayload = AbstractModel.toJsonString(request).getBytes();
|
||||||
|
// okhttp always set charset even we don't specify it,
|
||||||
|
// to ensure signature be correct, we have to set it here as well.
|
||||||
|
contentType = "application/json; charset=utf-8";
|
||||||
|
}
|
||||||
|
String canonicalUri = "/";
|
||||||
|
String canonicalQueryString = this.getCanonicalQueryString(params, httpRequestMethod);
|
||||||
|
String canonicalHeaders = "content-type:" + contentType + "\nhost:" + endpoint + "\n";
|
||||||
|
String signedHeaders = "content-type;host";
|
||||||
|
|
||||||
|
String hashedRequestPayload = "";
|
||||||
|
if (this.profile.isUnsignedPayload()) {
|
||||||
|
hashedRequestPayload = Sign.sha256Hex("UNSIGNED-PAYLOAD".getBytes());
|
||||||
|
} else {
|
||||||
|
hashedRequestPayload = Sign.sha256Hex(requestPayload);
|
||||||
|
}
|
||||||
|
String canonicalRequest = httpRequestMethod + "\n" + canonicalUri + "\n" + canonicalQueryString + "\n"
|
||||||
|
+ canonicalHeaders + "\n" + signedHeaders + "\n" + hashedRequestPayload;
|
||||||
|
|
||||||
|
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
|
||||||
|
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||||
|
String date = sdf.format(new Date(Long.valueOf(timestamp + "000")));
|
||||||
|
String service = endpoint.split("\\.")[0];
|
||||||
|
String credentialScope = date + "/" + service + "/" + "tc3_request";
|
||||||
|
String hashedCanonicalRequest = Sign.sha256Hex(canonicalRequest.getBytes());
|
||||||
|
String stringToSign = "TC3-HMAC-SHA256\n" + timestamp + "\n" + credentialScope + "\n" + hashedCanonicalRequest;
|
||||||
|
|
||||||
|
String secretId = this.credential.getSecretId();
|
||||||
|
String secretKey = this.credential.getSecretKey();
|
||||||
|
byte[] secretDate = Sign.hmac256(("TC3" + secretKey).getBytes(), date);
|
||||||
|
byte[] secretService = Sign.hmac256(secretDate, service);
|
||||||
|
byte[] secretSigning = Sign.hmac256(secretService, "tc3_request");
|
||||||
|
String signature = DatatypeConverter.printHexBinary(Sign.hmac256(secretSigning, stringToSign)).toLowerCase();
|
||||||
|
String authorization = "TC3-HMAC-SHA256 " + "Credential=" + secretId + "/" + credentialScope + ", "
|
||||||
|
+ "SignedHeaders=" + signedHeaders + ", " + "Signature=" + signature;
|
||||||
|
|
||||||
|
HttpConnection conn = new HttpConnection(
|
||||||
|
this.profile.getHttpProfile().getConnTimeout(),
|
||||||
|
this.profile.getHttpProfile().getReadTimeout(),
|
||||||
|
this.profile.getHttpProfile().getWriteTimeout());
|
||||||
|
String url = this.profile.getHttpProfile().getProtocol() + endpoint + this.path;
|
||||||
|
Builder hb = new Headers.Builder();
|
||||||
|
hb.add("Content-Type", contentType)
|
||||||
|
.add("Host", endpoint)
|
||||||
|
.add("Authorization", authorization)
|
||||||
|
.add("X-TC-Action", action)
|
||||||
|
.add("X-TC-Timestamp", timestamp)
|
||||||
|
.add("X-TC-Version", this.apiVersion)
|
||||||
|
.add("X-TC-RequestClient", SDK_VERSION);
|
||||||
|
if (null != this.getRegion()) {
|
||||||
|
hb.add("X-TC-Region", this.getRegion());
|
||||||
|
}
|
||||||
|
String token = this.credential.getToken();
|
||||||
|
if (token != null && ! token.isEmpty()) {
|
||||||
|
hb.add("X-TC-Token", token);
|
||||||
|
}
|
||||||
|
if (this.profile.isUnsignedPayload()) {
|
||||||
|
hb.add("X-TC-Content-SHA256", "UNSIGNED-PAYLOAD");
|
||||||
|
}
|
||||||
|
|
||||||
|
Headers headers = hb.build();
|
||||||
|
if (httpRequestMethod.equals(HttpProfile.REQ_GET)) {
|
||||||
|
return conn.getRequest(url + "?" + canonicalQueryString, headers);
|
||||||
|
} else if (httpRequestMethod.equals(HttpProfile.REQ_POST)) {
|
||||||
|
return conn.postRequest(url, requestPayload, headers);
|
||||||
|
} else {
|
||||||
|
throw new TencentCloudSDKException("Method only support GET, POST");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte [] getMultipartPayload(AbstractModel request, String boundary) throws Exception {
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
String [] binaryParams = request.getBinaryParams();
|
||||||
|
for (Map.Entry<String, byte []> entry : request.getMultipartRequestParams().entrySet()) {
|
||||||
|
baos.write("--".getBytes());
|
||||||
|
baos.write(boundary.getBytes());
|
||||||
|
baos.write("\r\n".getBytes());
|
||||||
|
baos.write("Content-Disposition: form-data; name=\"".getBytes());
|
||||||
|
baos.write(entry.getKey().getBytes());
|
||||||
|
if (Arrays.asList(binaryParams).contains(entry.getKey())) {
|
||||||
|
baos.write("\"; filename=\"".getBytes());
|
||||||
|
baos.write(entry.getKey().getBytes());
|
||||||
|
baos.write("\"\r\n".getBytes());
|
||||||
|
} else {
|
||||||
|
baos.write("\"\r\n".getBytes());
|
||||||
|
}
|
||||||
|
baos.write("\r\n".getBytes());
|
||||||
|
baos.write(entry.getValue());
|
||||||
|
baos.write("\r\n".getBytes());
|
||||||
|
}
|
||||||
|
if (baos.size() != 0) {
|
||||||
|
baos.write("--".getBytes());
|
||||||
|
baos.write(boundary.getBytes());
|
||||||
|
baos.write("--\r\n".getBytes());
|
||||||
|
}
|
||||||
|
byte [] bytes = baos.toByteArray();
|
||||||
|
baos.close();
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getCanonicalQueryString(HashMap<String, String> params, String method) throws TencentCloudSDKException {
|
||||||
|
if ( method != null && method.equals(HttpProfile.REQ_POST)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
StringBuilder queryString = new StringBuilder("");
|
||||||
|
for (Map.Entry<String, String> entry : params.entrySet()) {
|
||||||
|
String v;
|
||||||
|
try {
|
||||||
|
v = URLEncoder.encode(entry.getValue(), "UTF8");
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new TencentCloudSDKException("UTF8 is not supported." + e.getMessage());
|
||||||
|
}
|
||||||
|
queryString.append("&")
|
||||||
|
.append(entry.getKey())
|
||||||
|
.append("=")
|
||||||
|
.append(v);
|
||||||
|
}
|
||||||
|
return queryString.toString().substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatRequestData(String action, Map<String, String> param) throws TencentCloudSDKException {
|
||||||
|
param.put("Action", action);
|
||||||
|
param.put("RequestClient", this.sdkVersion);
|
||||||
|
param.put("Nonce", String.valueOf(Math.abs(new Random().nextInt())));
|
||||||
|
param.put("Timestamp", String.valueOf(System.currentTimeMillis() / 1000));
|
||||||
|
param.put("Version", this.apiVersion);
|
||||||
|
|
||||||
|
if (this.credential.getSecretId() != null && (!this.credential.getSecretId().isEmpty())) {
|
||||||
|
param.put("SecretId", this.credential.getSecretId());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.region != null && (!this.region.isEmpty())) {
|
||||||
|
param.put("Region", this.region);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.profile.getSignMethod() != null && (!this.profile.getSignMethod().isEmpty())) {
|
||||||
|
param.put("SignatureMethod", this.profile.getSignMethod());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.credential.getToken() != null && (!this.credential.getToken().isEmpty())) {
|
||||||
|
param.put("Token", this.credential.getToken());
|
||||||
|
}
|
||||||
|
|
||||||
|
String endpoint = this.endpoint;
|
||||||
|
if (!(this.profile.getHttpProfile().getEndpoint() == null)) {
|
||||||
|
endpoint = this.profile.getHttpProfile().getEndpoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
String sigInParam = Sign.makeSignPlainText(new TreeMap<String, String>(param),
|
||||||
|
this.profile.getHttpProfile().getReqMethod(), endpoint, this.path);
|
||||||
|
String sigOutParam = Sign.sign(this.credential.getSecretKey(), sigInParam, this.profile.getSignMethod());
|
||||||
|
|
||||||
|
String strParam = "";
|
||||||
|
try {
|
||||||
|
for (Map.Entry<String, String> entry : param.entrySet()) {
|
||||||
|
strParam += (URLEncoder.encode(entry.getKey(), "utf-8") + "="
|
||||||
|
+ URLEncoder.encode(entry.getValue(), "utf-8") + "&");
|
||||||
|
}
|
||||||
|
strParam += ("Signature=" + URLEncoder.encode(sigOutParam, "utf-8"));
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new TencentCloudSDKException(e.getClass().getName() + "-" + e.getMessage());
|
||||||
|
}
|
||||||
|
return strParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* warm up, try to avoid unnecessary cost in the first request
|
||||||
|
*/
|
||||||
|
private void warmup() {
|
||||||
|
try {
|
||||||
|
// it happens in SDK signature process.
|
||||||
|
// first invoke costs around 250 ms.
|
||||||
|
Mac.getInstance("HmacSHA1");
|
||||||
|
Mac.getInstance("HmacSHA256");
|
||||||
|
// it happens inside okhttp, but I think any https framework/package will do the same.
|
||||||
|
// first invoke costs around 150 ms.
|
||||||
|
SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||||
|
sslContext.init(null, null, null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// ignore but print message to console
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,165 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 THL A29 Limited, a Tencent company. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.xinelu.common.utils.tencentcloudapi.common;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 抽象model类
|
||||||
|
*/
|
||||||
|
abstract public class AbstractModel {
|
||||||
|
// any stores customized parameters which are not documented.
|
||||||
|
// You should make sure it can be correctly serialized to json string.
|
||||||
|
private HashMap<String, Object> customizedParams = new HashMap<String, Object>();
|
||||||
|
|
||||||
|
protected abstract void toMap(HashMap<String, String> map, String prefix);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* valid only when it's a request object.
|
||||||
|
* some actions can only be posted in multipart format,
|
||||||
|
* this method is used to mark which parameters are binary type.
|
||||||
|
*/
|
||||||
|
protected String [] getBinaryParams() {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* valid only when it's a multipart request object.
|
||||||
|
*/
|
||||||
|
protected HashMap<String, byte []> getMultipartRequestParams() {
|
||||||
|
return new HashMap<String, byte []>();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <V> void setParamSimple(HashMap<String, String> map, String key, V value) {
|
||||||
|
if (value != null) {
|
||||||
|
|
||||||
|
key = key.substring(0, 1).toUpperCase() + key.substring(1);
|
||||||
|
key = key.replace("_", ".");
|
||||||
|
map.put(key, String.valueOf(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <V> void setParamArraySimple(HashMap<String, String> map, String prefix, V [] array) {
|
||||||
|
if (array != null) {
|
||||||
|
for (int i = 0; i < array.length; i++) {
|
||||||
|
this.setParamSimple(map, prefix + i, array[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <V extends AbstractModel> void setParamObj(HashMap<String, String> map, String prefix, V obj) {
|
||||||
|
if (obj != null) {
|
||||||
|
obj.toMap(map, prefix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <V extends AbstractModel> void setParamArrayObj(HashMap<String, String> map, String prefix, V [] array) {
|
||||||
|
if (array != null) {
|
||||||
|
for (int i = 0; i < array.length; i++) {
|
||||||
|
this.setParamObj(map, prefix + i + ".", array[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 序列化函数,将对象数据转化为json格式的string
|
||||||
|
*
|
||||||
|
* @param obj
|
||||||
|
* 集成自AbstractModel的子类实例
|
||||||
|
* @return json格式的string
|
||||||
|
*/
|
||||||
|
public static <O extends AbstractModel> String toJsonString(O obj) {
|
||||||
|
return toJsonObject(obj).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively generate obj's JSON object. Even if obj.any() is empty, this
|
||||||
|
* recursive progress cannot be skipped because customized additional parameter
|
||||||
|
* might be hidden in lower data structure.
|
||||||
|
*
|
||||||
|
* @param obj
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static <O extends AbstractModel> JsonObject toJsonObject(O obj) {
|
||||||
|
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
|
||||||
|
JsonObject joall = new JsonObject();
|
||||||
|
JsonObject joadd = gson.toJsonTree(obj.any()).getAsJsonObject();
|
||||||
|
for (Map.Entry<String, JsonElement> entry : joadd.entrySet()) {
|
||||||
|
joall.add(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
// jopublic will override joadd if key conflict exists
|
||||||
|
JsonObject jopublic = gson.toJsonTree(obj).getAsJsonObject();
|
||||||
|
for (Map.Entry<String, JsonElement> entry : jopublic.entrySet()) {
|
||||||
|
Object fo = null;
|
||||||
|
try {
|
||||||
|
Field f = obj.getClass().getDeclaredField(entry.getKey());
|
||||||
|
f.setAccessible(true);
|
||||||
|
fo = f.get(obj);
|
||||||
|
} catch (Exception e) {
|
||||||
|
// this should never happen
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
if (fo instanceof AbstractModel) {
|
||||||
|
joall.add(entry.getKey(), toJsonObject((AbstractModel)fo));
|
||||||
|
} else {
|
||||||
|
joall.add(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return joall;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 序列化函数,根据传入的json格式的string实例化一个cls对象返回
|
||||||
|
*
|
||||||
|
* @param json
|
||||||
|
* json格式的string
|
||||||
|
* @param cls
|
||||||
|
* 与json匹配的类对象
|
||||||
|
* @return cls的实例
|
||||||
|
*/
|
||||||
|
public static <O> O fromJsonString(String json, Class<O> cls) {
|
||||||
|
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
|
||||||
|
return gson.fromJson(json, cls);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set any key value pair to this model.
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
public void set(String key, Object value) {
|
||||||
|
this.customizedParams.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get customized key value pairs from this model.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public HashMap<String, Object> any() {
|
||||||
|
return this.customizedParams;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 THL A29 Limited, a Tencent company. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.xinelu.common.utils.tencentcloudapi.common;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 认证相关信息类
|
||||||
|
*/
|
||||||
|
public class Credential {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* secretId,在控制台申请
|
||||||
|
*/
|
||||||
|
private String secretId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* secretKey,在控制台申请
|
||||||
|
*/
|
||||||
|
private String secretKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* token
|
||||||
|
*/
|
||||||
|
private String token;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param secretId 在控制台申请
|
||||||
|
* @param secretKey 在控制台申请
|
||||||
|
*/
|
||||||
|
public Credential(String secretId, String secretKey) {
|
||||||
|
this(secretId, secretKey, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param secretId 在控制台申请
|
||||||
|
* @param secretKey 在控制台申请
|
||||||
|
* @param token
|
||||||
|
*/
|
||||||
|
public Credential(String secretId, String secretKey, String token) {
|
||||||
|
this.secretId = secretId;
|
||||||
|
this.secretKey = secretKey;
|
||||||
|
this.token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置secretId
|
||||||
|
* @param secretId
|
||||||
|
*/
|
||||||
|
public void setSecretId(String secretId) {
|
||||||
|
this.secretId = secretId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置secretKey
|
||||||
|
* @param secretKey
|
||||||
|
*/
|
||||||
|
public void setSecretKey(String secretKey) {
|
||||||
|
this.secretKey = secretKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置token
|
||||||
|
* @param token
|
||||||
|
*/
|
||||||
|
public void setToken(String token) {
|
||||||
|
this.token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取secretId
|
||||||
|
* @return secretId
|
||||||
|
*/
|
||||||
|
public String getSecretId() {
|
||||||
|
return this.secretId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取secretKey
|
||||||
|
* @return secretKey
|
||||||
|
*/
|
||||||
|
public String getSecretKey() {
|
||||||
|
return this.secretKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取token
|
||||||
|
* @return token
|
||||||
|
*/
|
||||||
|
public String getToken() {
|
||||||
|
return this.token;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 THL A29 Limited, a Tencent company. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.xinelu.common.utils.tencentcloudapi.common;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.Expose;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* api 报错response类,用以格式化接收失败的http response
|
||||||
|
* @author Administrator
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class JsonResponseErrModel {
|
||||||
|
|
||||||
|
@SerializedName("RequestId")
|
||||||
|
@Expose
|
||||||
|
public String requestId;
|
||||||
|
|
||||||
|
@SerializedName("Error")
|
||||||
|
@Expose
|
||||||
|
public ErrorInfo error;
|
||||||
|
|
||||||
|
class ErrorInfo {
|
||||||
|
@SerializedName("Code")
|
||||||
|
@Expose
|
||||||
|
public String code;
|
||||||
|
|
||||||
|
@Expose
|
||||||
|
@SerializedName("Message")
|
||||||
|
public String message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 THL A29 Limited, a Tencent company. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.xinelu.common.utils.tencentcloudapi.common;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.Expose;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* api response类,用以格式化接收http response
|
||||||
|
* @param <T> 具体对应的response类
|
||||||
|
*/
|
||||||
|
public class JsonResponseModel <T> {
|
||||||
|
|
||||||
|
@SerializedName("Response")
|
||||||
|
@Expose
|
||||||
|
public T response;
|
||||||
|
}
|
||||||
@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 THL A29 Limited, a Tencent company. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.xinelu.common.utils.tencentcloudapi.common;
|
||||||
|
|
||||||
|
import com.xinelu.common.utils.tencentcloudapi.common.exception.TencentCloudSDKException;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
import javax.crypto.Mac;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
import javax.xml.bind.DatatypeConverter;
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名工具类
|
||||||
|
*/
|
||||||
|
public class Sign {
|
||||||
|
private final static Charset UTF8 = StandardCharsets.UTF_8;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param sigStr
|
||||||
|
* @param secretKey
|
||||||
|
* @param sigMethod
|
||||||
|
* @return string sign string
|
||||||
|
* @throws TencentCloudSDKException
|
||||||
|
*/
|
||||||
|
public static String sign(String secretKey, String sigStr, String sigMethod) throws TencentCloudSDKException
|
||||||
|
{
|
||||||
|
String sig = null;
|
||||||
|
try{
|
||||||
|
Mac mac = Mac.getInstance(sigMethod);
|
||||||
|
byte[] hash;
|
||||||
|
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(UTF8), mac.getAlgorithm());
|
||||||
|
|
||||||
|
mac.init(secretKeySpec);
|
||||||
|
hash = mac.doFinal(sigStr.getBytes(UTF8));
|
||||||
|
sig = DatatypeConverter.printBase64Binary(hash);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new TencentCloudSDKException(e.getClass().getName() + "-" + e.getMessage());
|
||||||
|
}
|
||||||
|
return sig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String makeSignPlainText(TreeMap<String, String> requestParams, String reqMethod, String host, String path) {
|
||||||
|
|
||||||
|
String retStr = "";
|
||||||
|
retStr += reqMethod;
|
||||||
|
retStr += host;
|
||||||
|
retStr += path;
|
||||||
|
retStr += buildParamStr(requestParams, reqMethod);
|
||||||
|
return retStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static String buildParamStr(TreeMap<String, String> requestParams, String requestMethod) {
|
||||||
|
|
||||||
|
String retStr = "";
|
||||||
|
for(String key: requestParams.keySet()) {
|
||||||
|
String value = requestParams.get(key).toString();
|
||||||
|
if (retStr.length() == 0) {
|
||||||
|
retStr += '?';
|
||||||
|
} else {
|
||||||
|
retStr += '&';
|
||||||
|
}
|
||||||
|
retStr += key.replace("_", ".") + '=' + value;
|
||||||
|
|
||||||
|
}
|
||||||
|
return retStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String sha256Hex(String s) throws TencentCloudSDKException {
|
||||||
|
MessageDigest md;
|
||||||
|
try {
|
||||||
|
md = MessageDigest.getInstance("SHA-256");
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new TencentCloudSDKException("SHA-256 is not supported." + e.getMessage());
|
||||||
|
}
|
||||||
|
byte[] d = md.digest(s.getBytes(UTF8));
|
||||||
|
return DatatypeConverter.printHexBinary(d).toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String sha256Hex(byte[] b) throws TencentCloudSDKException {
|
||||||
|
MessageDigest md;
|
||||||
|
try {
|
||||||
|
md = MessageDigest.getInstance("SHA-256");
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new TencentCloudSDKException("SHA-256 is not supported." + e.getMessage());
|
||||||
|
}
|
||||||
|
byte[] d = md.digest(b);
|
||||||
|
return DatatypeConverter.printHexBinary(d).toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] hmac256(byte[] key, String msg) throws TencentCloudSDKException {
|
||||||
|
Mac mac;
|
||||||
|
try {
|
||||||
|
mac = Mac.getInstance("HmacSHA256");
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new TencentCloudSDKException("HmacSHA256 is not supported." + e.getMessage());
|
||||||
|
}
|
||||||
|
SecretKeySpec secretKeySpec = new SecretKeySpec(key, mac.getAlgorithm());
|
||||||
|
try {
|
||||||
|
mac.init(secretKeySpec);
|
||||||
|
} catch (InvalidKeyException e) {
|
||||||
|
throw new TencentCloudSDKException(e.getClass().getName() + "-" + e.getMessage());
|
||||||
|
}
|
||||||
|
return mac.doFinal(msg.getBytes(UTF8));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 THL A29 Limited, a Tencent company. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.xinelu.common.utils.tencentcloudapi.common.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 腾讯云api sdk异常类
|
||||||
|
*/
|
||||||
|
public class TencentCloudSDKException extends Exception {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求Id,发起请求前的异常这个字段为空
|
||||||
|
*/
|
||||||
|
private String requestId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Error code, When API returns a failure, it must have an error code.
|
||||||
|
*/
|
||||||
|
private String errorCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param message 异常信息
|
||||||
|
*/
|
||||||
|
public TencentCloudSDKException(String message) {
|
||||||
|
this(message, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param message 异常信息
|
||||||
|
* @param requestId 请求id
|
||||||
|
*/
|
||||||
|
public TencentCloudSDKException(String message, String requestId) {
|
||||||
|
super(message);
|
||||||
|
this.requestId = requestId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TencentCloudSDKException(String message, String requestId, String errorCode) {
|
||||||
|
super(message);
|
||||||
|
this.requestId = requestId;
|
||||||
|
this.errorCode = errorCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取请求id
|
||||||
|
* @return requestId
|
||||||
|
*/
|
||||||
|
public String getRequestId() {
|
||||||
|
return requestId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get error code
|
||||||
|
* @return A string represents error code
|
||||||
|
*/
|
||||||
|
// public String getErrorCode() {
|
||||||
|
// return errorCode;
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化输出异常信息
|
||||||
|
* @return 异常信息
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
return "[TencentCloudSDKException]" + "message:" + this.getMessage() + " requestId:" + this.getRequestId();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 THL A29 Limited, a Tencent company. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.xinelu.common.utils.tencentcloudapi.common.http;
|
||||||
|
|
||||||
|
import com.squareup.okhttp.Headers;
|
||||||
|
import com.squareup.okhttp.MediaType;
|
||||||
|
import com.squareup.okhttp.OkHttpClient;
|
||||||
|
import com.squareup.okhttp.Request;
|
||||||
|
import com.squareup.okhttp.RequestBody;
|
||||||
|
import com.squareup.okhttp.Response;
|
||||||
|
import com.xinelu.common.utils.tencentcloudapi.common.exception.TencentCloudSDKException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* http连接类
|
||||||
|
*/
|
||||||
|
public class HttpConnection {
|
||||||
|
|
||||||
|
private OkHttpClient client;
|
||||||
|
|
||||||
|
public HttpConnection(Integer connTimeout, Integer readTimeout, Integer writeTimeout) {
|
||||||
|
this.client = new OkHttpClient();
|
||||||
|
this.client.setConnectTimeout(connTimeout, TimeUnit.SECONDS);
|
||||||
|
this.client.setReadTimeout(readTimeout, TimeUnit.SECONDS);
|
||||||
|
this.client.setWriteTimeout(writeTimeout, TimeUnit.SECONDS);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Response doRequest(Request request) throws TencentCloudSDKException {
|
||||||
|
Response response = null;
|
||||||
|
try {
|
||||||
|
response = this.client.newCall(request).execute();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new TencentCloudSDKException(e.getClass().getName() + "-" + e.getMessage());
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Response getRequest(String url) throws TencentCloudSDKException {
|
||||||
|
Request request = null;
|
||||||
|
try {
|
||||||
|
request = new Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.get()
|
||||||
|
.build();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new TencentCloudSDKException(e.getClass().getName() + "-" + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.doRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Response getRequest(String url, Headers headers) throws TencentCloudSDKException {
|
||||||
|
Request request = null;
|
||||||
|
try {
|
||||||
|
request = new Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.headers(headers)
|
||||||
|
.get()
|
||||||
|
.build();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new TencentCloudSDKException(e.getClass().getName() + "-" + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.doRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Response postRequest(String url, String body) throws TencentCloudSDKException {
|
||||||
|
MediaType contentType = MediaType.parse("application/x-www-form-urlencoded");
|
||||||
|
Request request = null;
|
||||||
|
try {
|
||||||
|
request = new Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.post(RequestBody.create(contentType, body))
|
||||||
|
.build();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new TencentCloudSDKException(e.getClass().getName() + "-" + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.doRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Response postRequest(String url, String body, Headers headers) throws TencentCloudSDKException {
|
||||||
|
MediaType contentType = MediaType.parse(headers.get("Content-Type"));
|
||||||
|
Request request = null;
|
||||||
|
try {
|
||||||
|
request = new Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.post(RequestBody.create(contentType, body))
|
||||||
|
.headers(headers)
|
||||||
|
.build();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new TencentCloudSDKException(e.getClass().getName() + "-" + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.doRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Response postRequest(String url, byte [] body, Headers headers) throws TencentCloudSDKException {
|
||||||
|
MediaType contentType = MediaType.parse(headers.get("Content-Type"));
|
||||||
|
Request request = null;
|
||||||
|
try {
|
||||||
|
request = new Request.Builder()
|
||||||
|
.url(url)
|
||||||
|
.post(RequestBody.create(contentType, body))
|
||||||
|
.headers(headers)
|
||||||
|
.build();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new TencentCloudSDKException(e.getClass().getName() + "-" + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.doRequest(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 THL A29 Limited, a Tencent company. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.xinelu.common.utils.tencentcloudapi.common.profile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* client选项类
|
||||||
|
* @author Administrator
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ClientProfile {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HmacSHA1签名方法
|
||||||
|
*/
|
||||||
|
public static final String SIGN_SHA1 = "HmacSHA1";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HmacSHA256签名方法
|
||||||
|
*/
|
||||||
|
public static final String SIGN_SHA256 = "HmacSHA256";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signature Version 3
|
||||||
|
*/
|
||||||
|
public static final String SIGN_TC3_256 = "TC3-HMAC-SHA256";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* http相关选项,请参考HttpProfile
|
||||||
|
*/
|
||||||
|
private HttpProfile httpProfile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 签名方法
|
||||||
|
*/
|
||||||
|
private String signMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If payload is NOT involved in signing process, true means will ignore payload,
|
||||||
|
* default is false.
|
||||||
|
*/
|
||||||
|
private boolean unsignedPayload;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param signMethod 签名方法
|
||||||
|
* @param httpProfile HttpProfile实例
|
||||||
|
*/
|
||||||
|
public ClientProfile(String signMethod, HttpProfile httpProfile) {
|
||||||
|
if (signMethod == null || signMethod.isEmpty()) {
|
||||||
|
signMethod = SIGN_TC3_256;
|
||||||
|
}
|
||||||
|
this.signMethod = signMethod;
|
||||||
|
this.httpProfile = httpProfile;
|
||||||
|
this.unsignedPayload = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClientProfile(String signMethod) {
|
||||||
|
this(signMethod, new HttpProfile());
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClientProfile() {
|
||||||
|
this(ClientProfile.SIGN_TC3_256, new HttpProfile());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置签名方法
|
||||||
|
* @param signMethod
|
||||||
|
*/
|
||||||
|
public void setSignMethod(String signMethod) {
|
||||||
|
this.signMethod = signMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置http选项
|
||||||
|
* @param httpProfile 参考HttpProfile
|
||||||
|
*/
|
||||||
|
public void setHttpProfile(HttpProfile httpProfile) {
|
||||||
|
this.httpProfile = httpProfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取签名方法
|
||||||
|
* @return 签名方法
|
||||||
|
*/
|
||||||
|
public String getSignMethod() {
|
||||||
|
return this.signMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取HttpProfile实例
|
||||||
|
* @return HttpProfile实例
|
||||||
|
*/
|
||||||
|
public HttpProfile getHttpProfile() {
|
||||||
|
return this.httpProfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the flag of whether payload should be ignored.
|
||||||
|
* Only has effect when request method is POST.
|
||||||
|
* @param flag
|
||||||
|
*/
|
||||||
|
public void setUnsignedPayload(boolean flag) {
|
||||||
|
this.unsignedPayload = flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the flag of whether payload is ignored.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean isUnsignedPayload() {
|
||||||
|
return this.unsignedPayload;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,185 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018 THL A29 Limited, a Tencent company. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.xinelu.common.utils.tencentcloudapi.common.profile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* http选项类
|
||||||
|
*/
|
||||||
|
public class HttpProfile {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* https协议
|
||||||
|
*/
|
||||||
|
public static final String REQ_HTTPS = "https://";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* http协议
|
||||||
|
*/
|
||||||
|
public static final String REQ_HTTP = "http://";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* post请求
|
||||||
|
*/
|
||||||
|
public static final String REQ_POST = "POST";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get请求
|
||||||
|
*/
|
||||||
|
public static final String REQ_GET = "GET";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时间单位,1分钟 60s
|
||||||
|
*/
|
||||||
|
public static final int TM_MINUTE = 60;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求方法
|
||||||
|
*/
|
||||||
|
private String reqMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求域名
|
||||||
|
*/
|
||||||
|
private String endpoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求协议
|
||||||
|
*/
|
||||||
|
private String protocol;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读超时时间(秒)
|
||||||
|
*/
|
||||||
|
private int readTimeout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 写超时时间(秒)
|
||||||
|
*/
|
||||||
|
private int writeTimeout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 连接超时时间(秒)
|
||||||
|
*/
|
||||||
|
private int connTimeout;
|
||||||
|
|
||||||
|
|
||||||
|
public HttpProfile() {
|
||||||
|
this.reqMethod = HttpProfile.REQ_POST;
|
||||||
|
this.endpoint = null;
|
||||||
|
this.protocol = HttpProfile.REQ_HTTPS;
|
||||||
|
this.readTimeout = 0;
|
||||||
|
this.writeTimeout = 0;
|
||||||
|
this.connTimeout = HttpProfile.TM_MINUTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置请求方法
|
||||||
|
* @param reqMethod 请求方法
|
||||||
|
*/
|
||||||
|
public void setReqMethod(String reqMethod) {
|
||||||
|
this.reqMethod = reqMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置请求域名
|
||||||
|
* @param endpoint 域名(xx.[region.]tencentcloudapi.com)
|
||||||
|
*/
|
||||||
|
public void setEndpoint(String endpoint) {
|
||||||
|
this.endpoint = endpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置读超时时间
|
||||||
|
* @param readTimeout 读超时时间
|
||||||
|
*/
|
||||||
|
public void setReadTimeout(int readTimeout) {
|
||||||
|
this.readTimeout = readTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置写超时时间
|
||||||
|
* @param writeTimeout 写超时时间
|
||||||
|
*/
|
||||||
|
public void setWriteTimeout(int writeTimeout) {
|
||||||
|
this.writeTimeout = writeTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置连接超时时间
|
||||||
|
* @param connTimeout 连接超时时间
|
||||||
|
*/
|
||||||
|
public void setConnTimeout(int connTimeout) {
|
||||||
|
this.connTimeout = connTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置请求协议
|
||||||
|
* @param protocol 请求协议(https:// http://)
|
||||||
|
*/
|
||||||
|
public void setProtocol(String protocol) {
|
||||||
|
this.protocol = protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取请求方法
|
||||||
|
* @return reqMethod
|
||||||
|
*/
|
||||||
|
public String getReqMethod() {
|
||||||
|
return this.reqMethod;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取请求域名
|
||||||
|
* @return endpoint
|
||||||
|
*/
|
||||||
|
public String getEndpoint() {
|
||||||
|
return this.endpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取读超时时间
|
||||||
|
* @return readTimeout
|
||||||
|
*/
|
||||||
|
public int getReadTimeout() {
|
||||||
|
return this.readTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取写超时时间
|
||||||
|
* @return writeTimeout
|
||||||
|
*/
|
||||||
|
public int getWriteTimeout() {
|
||||||
|
return this.writeTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取连接超时时间
|
||||||
|
* @return connTimeout
|
||||||
|
*/
|
||||||
|
public int getConnTimeout() {
|
||||||
|
return this.connTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取请求协议
|
||||||
|
* @return protocol
|
||||||
|
*/
|
||||||
|
public String getProtocol() {
|
||||||
|
return this.protocol;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package com.xinelu.common.utils.tencentcloudapi.trtc.v20190722;
|
||||||
|
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
public class Base64URL {
|
||||||
|
public static byte[] base64EncodeUrl(byte[] input) {
|
||||||
|
byte[] base64 = Base64.getEncoder().encode(input);
|
||||||
|
for (int i = 0; i < base64.length; ++i)
|
||||||
|
switch (base64[i]) {
|
||||||
|
case '+':
|
||||||
|
base64[i] = '*';
|
||||||
|
break;
|
||||||
|
case '/':
|
||||||
|
base64[i] = '-';
|
||||||
|
break;
|
||||||
|
case '=':
|
||||||
|
base64[i] = '_';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return base64;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,312 @@
|
|||||||
|
package com.xinelu.common.utils.tencentcloudapi.trtc.v20190722;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.zip.Deflater;
|
||||||
|
import javax.crypto.Mac;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
|
public class TLSSigAPIv2 {
|
||||||
|
final private long sdkappid;
|
||||||
|
final private String key;
|
||||||
|
|
||||||
|
public TLSSigAPIv2(long sdkappid, String key) {
|
||||||
|
this.sdkappid = sdkappid;
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【功能说明】用于签发 TRTC 和 IM 服务中必须要使用的 UserSig 鉴权票据
|
||||||
|
* <p>
|
||||||
|
* 【参数说明】
|
||||||
|
*
|
||||||
|
* @param userid - 用户id,限制长度为32字节,只允许包含大小写英文字母(a-zA-Z)、数字(0-9)及下划线和连词符。
|
||||||
|
* @param expire - UserSig 票据的过期时间,单位是秒,比如 86400 代表生成的 UserSig 票据在一天后就无法再使用了。
|
||||||
|
* @return usersig -生成的签名
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function: Used to issue UserSig that is required by the TRTC and IM services.
|
||||||
|
* <p>
|
||||||
|
* Parameter description:
|
||||||
|
*
|
||||||
|
* @param userid - User ID. The value can be up to 32 bytes in length and contain letters (a-z and A-Z), digits (0-9), underscores (_), and hyphens (-).
|
||||||
|
* @param expire - UserSig expiration time, in seconds. For example, 86400 indicates that the generated UserSig will expire one day after being generated.
|
||||||
|
* @return usersig - Generated signature.
|
||||||
|
*/
|
||||||
|
public String genUserSig(String userid, long expire) {
|
||||||
|
return genUserSig(userid, expire, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【功能说明】
|
||||||
|
* 用于签发 TRTC 进房参数中可选的 PrivateMapKey 权限票据。
|
||||||
|
* PrivateMapKey 需要跟 UserSig 一起使用,但 PrivateMapKey 比 UserSig 有更强的权限控制能力:
|
||||||
|
* - UserSig 只能控制某个 UserID 有无使用 TRTC 服务的权限,只要 UserSig 正确,其对应的 UserID 可以进出任意房间。
|
||||||
|
* - PrivateMapKey 则是将 UserID 的权限控制的更加严格,包括能不能进入某个房间,能不能在该房间里上行音视频等等。
|
||||||
|
* 如果要开启 PrivateMapKey 严格权限位校验,需要在【实时音视频控制台】/【应用管理】/【应用信息】中打开“启动权限密钥”开关。
|
||||||
|
* <p>
|
||||||
|
* 【参数说明】
|
||||||
|
*
|
||||||
|
* @param userid - 用户id,限制长度为32字节,只允许包含大小写英文字母(a-zA-Z)、数字(0-9)及下划线和连词符。
|
||||||
|
* @param expire - PrivateMapKey 票据的过期时间,单位是秒,比如 86400 生成的 PrivateMapKey 票据在一天后就无法再使用了。
|
||||||
|
* @param roomid - 房间号,用于指定该 userid 可以进入的房间号
|
||||||
|
* @param privilegeMap - 权限位,使用了一个字节中的 8 个比特位,分别代表八个具体的功能权限开关:
|
||||||
|
* - 第 1 位:0000 0001 = 1,创建房间的权限
|
||||||
|
* - 第 2 位:0000 0010 = 2,加入房间的权限
|
||||||
|
* - 第 3 位:0000 0100 = 4,发送语音的权限
|
||||||
|
* - 第 4 位:0000 1000 = 8,接收语音的权限
|
||||||
|
* - 第 5 位:0001 0000 = 16,发送视频的权限
|
||||||
|
* - 第 6 位:0010 0000 = 32,接收视频的权限
|
||||||
|
* - 第 7 位:0100 0000 = 64,发送辅路(也就是屏幕分享)视频的权限
|
||||||
|
* - 第 8 位:1000 0000 = 200,接收辅路(也就是屏幕分享)视频的权限
|
||||||
|
* - privilegeMap == 1111 1111 == 255 代表该 userid 在该 roomid 房间内的所有功能权限。
|
||||||
|
* - privilegeMap == 0010 1010 == 42 代表该 userid 拥有加入房间和接收音视频数据的权限,但不具备其他权限。
|
||||||
|
* @return usersig - 生成带userbuf的签名
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function:
|
||||||
|
* Used to issue PrivateMapKey that is optional for room entry.
|
||||||
|
* PrivateMapKey must be used together with UserSig but with more powerful permission control capabilities.
|
||||||
|
* - UserSig can only control whether a UserID has permission to use the TRTC service. As long as the UserSig is correct, the user with the corresponding UserID can enter or leave any room.
|
||||||
|
* - PrivateMapKey specifies more stringent permissions for a UserID, including whether the UserID can be used to enter a specific room and perform audio/video upstreaming in the room.
|
||||||
|
* To enable stringent PrivateMapKey permission bit verification, you need to enable permission key in TRTC console > Application Management > Application Info.
|
||||||
|
*
|
||||||
|
* Parameter description:
|
||||||
|
*
|
||||||
|
* @param userid - User ID. The value can be up to 32 bytes in length and contain letters (a-z and A-Z), digits (0-9), underscores (_), and hyphens (-).
|
||||||
|
* @param roomid - ID of the room to which the specified UserID can enter.
|
||||||
|
* @param expire - PrivateMapKey expiration time, in seconds. For example, 86400 indicates that the generated PrivateMapKey will expire one day after being generated.
|
||||||
|
* @param privilegeMap - Permission bits. Eight bits in the same byte are used as the permission switches of eight specific features:
|
||||||
|
* - Bit 1: 0000 0001 = 1, permission for room creation
|
||||||
|
* - Bit 2: 0000 0010 = 2, permission for room entry
|
||||||
|
* - Bit 3: 0000 0100 = 4, permission for audio sending
|
||||||
|
* - Bit 4: 0000 1000 = 8, permission for audio receiving
|
||||||
|
* - Bit 5: 0001 0000 = 16, permission for video sending
|
||||||
|
* - Bit 6: 0010 0000 = 32, permission for video receiving
|
||||||
|
* - Bit 7: 0100 0000 = 64, permission for substream video sending (screen sharing)
|
||||||
|
* - Bit 8: 1000 0000 = 200, permission for substream video receiving (screen sharing)
|
||||||
|
* - privilegeMap == 1111 1111 == 255: Indicates that the UserID has all feature permissions of the room specified by roomid.
|
||||||
|
* - privilegeMap == 0010 1010 == 42: Indicates that the UserID has only the permissions to enter the room and receive audio/video data.
|
||||||
|
* @return usersig - Generate signature with userbuf
|
||||||
|
*/
|
||||||
|
public String genPrivateMapKey(String userid, long expire, long roomid, long privilegeMap) {
|
||||||
|
byte[] userbuf = genUserBuf(userid, roomid, expire, privilegeMap, 0, ""); //生成userbuf
|
||||||
|
return genUserSig(userid, expire, userbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 【功能说明】
|
||||||
|
* 用于签发 TRTC 进房参数中可选的 PrivateMapKey 权限票据。
|
||||||
|
* PrivateMapKey 需要跟 UserSig 一起使用,但 PrivateMapKey 比 UserSig 有更强的权限控制能力:
|
||||||
|
* - UserSig 只能控制某个 UserID 有无使用 TRTC 服务的权限,只要 UserSig 正确,其对应的 UserID 可以进出任意房间。
|
||||||
|
* - PrivateMapKey 则是将 UserID 的权限控制的更加严格,包括能不能进入某个房间,能不能在该房间里上行音视频等等。
|
||||||
|
* 如果要开启 PrivateMapKey 严格权限位校验,需要在【实时音视频控制台】/【应用管理】/【应用信息】中打开“启动权限密钥”开关。
|
||||||
|
* <p>
|
||||||
|
* 【参数说明】
|
||||||
|
*
|
||||||
|
* @param userid - 用户id,限制长度为32字节,只允许包含大小写英文字母(a-zA-Z)、数字(0-9)及下划线和连词符。
|
||||||
|
* @param expire - PrivateMapKey 票据的过期时间,单位是秒,比如 86400 生成的 PrivateMapKey 票据在一天后就无法再使用了。
|
||||||
|
* @param roomstr - 字符串房间号,用于指定该 userid 可以进入的房间号
|
||||||
|
* @param privilegeMap - 权限位,使用了一个字节中的 8 个比特位,分别代表八个具体的功能权限开关:
|
||||||
|
* - 第 1 位:0000 0001 = 1,创建房间的权限
|
||||||
|
* - 第 2 位:0000 0010 = 2,加入房间的权限
|
||||||
|
* - 第 3 位:0000 0100 = 4,发送语音的权限
|
||||||
|
* - 第 4 位:0000 1000 = 8,接收语音的权限
|
||||||
|
* - 第 5 位:0001 0000 = 16,发送视频的权限
|
||||||
|
* - 第 6 位:0010 0000 = 32,接收视频的权限
|
||||||
|
* - 第 7 位:0100 0000 = 64,发送辅路(也就是屏幕分享)视频的权限
|
||||||
|
* - 第 8 位:1000 0000 = 200,接收辅路(也就是屏幕分享)视频的权限
|
||||||
|
* - privilegeMap == 1111 1111 == 255 代表该 userid 在该 roomid 房间内的所有功能权限。
|
||||||
|
* - privilegeMap == 0010 1010 == 42 代表该 userid 拥有加入房间和接收音视频数据的权限,但不具备其他权限。
|
||||||
|
* @return usersig - 生成带userbuf的签名
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function:
|
||||||
|
* Used to issue PrivateMapKey that is optional for room entry.
|
||||||
|
* PrivateMapKey must be used together with UserSig but with more powerful permission control capabilities.
|
||||||
|
* - UserSig can only control whether a UserID has permission to use the TRTC service. As long as the UserSig is correct, the user with the corresponding UserID can enter or leave any room.
|
||||||
|
* - PrivateMapKey specifies more stringent permissions for a UserID, including whether the UserID can be used to enter a specific room and perform audio/video upstreaming in the room.
|
||||||
|
* To enable stringent PrivateMapKey permission bit verification, you need to enable permission key in TRTC console > Application Management > Application Info.
|
||||||
|
*
|
||||||
|
* Parameter description:
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @param userid - User ID. The value can be up to 32 bytes in length and contain letters (a-z and A-Z), digits (0-9), underscores (_), and hyphens (-).
|
||||||
|
* @param roomid - ID of the room to which the specified UserID can enter.
|
||||||
|
* @param expire - PrivateMapKey expiration time, in seconds. For example, 86400 indicates that the generated PrivateMapKey will expire one day after being generated.
|
||||||
|
* @param privilegeMap - Permission bits. Eight bits in the same byte are used as the permission switches of eight specific features:
|
||||||
|
* - Bit 1: 0000 0001 = 1, permission for room creation
|
||||||
|
* - Bit 2: 0000 0010 = 2, permission for room entry
|
||||||
|
* - Bit 3: 0000 0100 = 4, permission for audio sending
|
||||||
|
* - Bit 4: 0000 1000 = 8, permission for audio receiving
|
||||||
|
* - Bit 5: 0001 0000 = 16, permission for video sending
|
||||||
|
* - Bit 6: 0010 0000 = 32, permission for video receiving
|
||||||
|
* - Bit 7: 0100 0000 = 64, permission for substream video sending (screen sharing)
|
||||||
|
* - Bit 8: 1000 0000 = 200, permission for substream video receiving (screen sharing)
|
||||||
|
* - privilegeMap == 1111 1111 == 255: Indicates that the UserID has all feature permissions of the room specified by roomid.
|
||||||
|
* - privilegeMap == 0010 1010 == 42: Indicates that the UserID has only the permissions to enter the room and receive audio/video data.
|
||||||
|
* @return usersig - Generate signature with userbuf
|
||||||
|
*/
|
||||||
|
public String genPrivateMapKeyWithStringRoomID(String userid, long expire, String roomstr, long privilegeMap) {
|
||||||
|
byte[] userbuf = genUserBuf(userid, 0, expire, privilegeMap, 0, roomstr); //生成userbuf
|
||||||
|
return genUserSig(userid, expire, userbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String hmacsha256(String identifier, long currTime, long expire, String base64Userbuf) {
|
||||||
|
String contentToBeSigned = "TLS.identifier:" + identifier + "\n"
|
||||||
|
+ "TLS.sdkappid:" + sdkappid + "\n"
|
||||||
|
+ "TLS.time:" + currTime + "\n"
|
||||||
|
+ "TLS.expire:" + expire + "\n";
|
||||||
|
if (null != base64Userbuf) {
|
||||||
|
contentToBeSigned += "TLS.userbuf:" + base64Userbuf + "\n";
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
byte[] byteKey = key.getBytes(StandardCharsets.UTF_8);
|
||||||
|
Mac hmac = Mac.getInstance("HmacSHA256");
|
||||||
|
SecretKeySpec keySpec = new SecretKeySpec(byteKey, "HmacSHA256");
|
||||||
|
hmac.init(keySpec);
|
||||||
|
byte[] byteSig = hmac.doFinal(contentToBeSigned.getBytes(StandardCharsets.UTF_8));
|
||||||
|
return (Base64.getEncoder().encodeToString(byteSig)).replaceAll("\\s*", "");
|
||||||
|
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String genUserSig(String userid, long expire, byte[] userbuf) {
|
||||||
|
|
||||||
|
long currTime = System.currentTimeMillis() / 1000;
|
||||||
|
|
||||||
|
JSONObject sigDoc = new JSONObject();
|
||||||
|
sigDoc.put("TLS.ver", "2.0");
|
||||||
|
sigDoc.put("TLS.identifier", userid);
|
||||||
|
sigDoc.put("TLS.sdkappid", sdkappid);
|
||||||
|
sigDoc.put("TLS.expire", expire);
|
||||||
|
sigDoc.put("TLS.time", currTime);
|
||||||
|
|
||||||
|
String base64UserBuf = null;
|
||||||
|
if (null != userbuf) {
|
||||||
|
base64UserBuf = Base64.getEncoder().encodeToString(userbuf).replaceAll("\\s*", "");
|
||||||
|
sigDoc.put("TLS.userbuf", base64UserBuf);
|
||||||
|
}
|
||||||
|
String sig = hmacsha256(userid, currTime, expire, base64UserBuf);
|
||||||
|
if (sig.length() == 0) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
sigDoc.put("TLS.sig", sig);
|
||||||
|
Deflater compressor = new Deflater();
|
||||||
|
compressor.setInput(sigDoc.toString().getBytes(StandardCharsets.UTF_8));
|
||||||
|
compressor.finish();
|
||||||
|
byte[] compressedBytes = new byte[2048];
|
||||||
|
int compressedBytesLength = compressor.deflate(compressedBytes);
|
||||||
|
compressor.end();
|
||||||
|
return (new String(Base64URL.base64EncodeUrl(Arrays.copyOfRange(compressedBytes,
|
||||||
|
0, compressedBytesLength)))).replaceAll("\\s*", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] genUserBuf(String account, long dwAuthID, long dwExpTime,
|
||||||
|
long dwPrivilegeMap, long dwAccountType, String RoomStr) {
|
||||||
|
//视频校验位需要用到的字段,按照网络字节序放入buf中
|
||||||
|
/*
|
||||||
|
cVer unsigned char/1 版本号,填0
|
||||||
|
wAccountLen unsigned short /2 第三方自己的帐号长度
|
||||||
|
account wAccountLen 第三方自己的帐号字符
|
||||||
|
dwSdkAppid unsigned int/4 sdkappid
|
||||||
|
dwAuthID unsigned int/4 群组号码
|
||||||
|
dwExpTime unsigned int/4 过期时间 ,直接使用填入的值
|
||||||
|
dwPrivilegeMap unsigned int/4 权限位,主播0xff,观众0xab
|
||||||
|
dwAccountType unsigned int/4 第三方帐号类型
|
||||||
|
*/
|
||||||
|
|
||||||
|
//The fields required for the video check digit are placed in buf according to the network byte order.
|
||||||
|
/*
|
||||||
|
cVer unsigned char/1 Version number, fill in 0
|
||||||
|
wAccountLen unsigned short /2 Third party's own account length
|
||||||
|
account wAccountLen Third party's own account characters
|
||||||
|
dwSdkAppid unsigned int/4 sdkappid
|
||||||
|
dwAuthID unsigned int/4 group number
|
||||||
|
dwExpTime unsigned int/4 Expiration time , use the filled value directly
|
||||||
|
dwPrivilegeMap unsigned int/4 Permission bits, host 0xff, audience 0xab
|
||||||
|
dwAccountType unsigned int/4 Third-party account type
|
||||||
|
*/
|
||||||
|
int accountLength = account.length();
|
||||||
|
int roomStrLength = RoomStr.length();
|
||||||
|
int offset = 0;
|
||||||
|
int bufLength = 1 + 2 + accountLength + 20 ;
|
||||||
|
if (roomStrLength > 0) {
|
||||||
|
bufLength = bufLength + 2 + roomStrLength;
|
||||||
|
}
|
||||||
|
byte[] userbuf = new byte[bufLength];
|
||||||
|
|
||||||
|
//cVer
|
||||||
|
if (roomStrLength > 0) {
|
||||||
|
userbuf[offset++] = 1;
|
||||||
|
} else {
|
||||||
|
userbuf[offset++] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//wAccountLen
|
||||||
|
userbuf[offset++] = (byte) ((accountLength & 0xFF00) >> 8);
|
||||||
|
userbuf[offset++] = (byte) (accountLength & 0x00FF);
|
||||||
|
|
||||||
|
//account
|
||||||
|
for (; offset < 3 + accountLength; ++offset) {
|
||||||
|
userbuf[offset] = (byte) account.charAt(offset - 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
//dwSdkAppid
|
||||||
|
userbuf[offset++] = (byte) ((sdkappid & 0xFF000000) >> 24);
|
||||||
|
userbuf[offset++] = (byte) ((sdkappid & 0x00FF0000) >> 16);
|
||||||
|
userbuf[offset++] = (byte) ((sdkappid & 0x0000FF00) >> 8);
|
||||||
|
userbuf[offset++] = (byte) (sdkappid & 0x000000FF);
|
||||||
|
|
||||||
|
//dwAuthId,房间号
|
||||||
|
//dwAuthId, room number
|
||||||
|
userbuf[offset++] = (byte) ((dwAuthID & 0xFF000000) >> 24);
|
||||||
|
userbuf[offset++] = (byte) ((dwAuthID & 0x00FF0000) >> 16);
|
||||||
|
userbuf[offset++] = (byte) ((dwAuthID & 0x0000FF00) >> 8);
|
||||||
|
userbuf[offset++] = (byte) (dwAuthID & 0x000000FF);
|
||||||
|
|
||||||
|
//expire,过期时间,当前时间 + 有效期(单位:秒)
|
||||||
|
//expire,Expiration time, current time + validity period (unit: seconds)
|
||||||
|
long currTime = System.currentTimeMillis() / 1000;
|
||||||
|
long expire = currTime + dwExpTime;
|
||||||
|
userbuf[offset++] = (byte) ((expire & 0xFF000000) >> 24);
|
||||||
|
userbuf[offset++] = (byte) ((expire & 0x00FF0000) >> 16);
|
||||||
|
userbuf[offset++] = (byte) ((expire & 0x0000FF00) >> 8);
|
||||||
|
userbuf[offset++] = (byte) (expire & 0x000000FF);
|
||||||
|
|
||||||
|
//dwPrivilegeMap,权限位
|
||||||
|
//dwPrivilegeMap,Permission bits
|
||||||
|
userbuf[offset++] = (byte) ((dwPrivilegeMap & 0xFF000000) >> 24);
|
||||||
|
userbuf[offset++] = (byte) ((dwPrivilegeMap & 0x00FF0000) >> 16);
|
||||||
|
userbuf[offset++] = (byte) ((dwPrivilegeMap & 0x0000FF00) >> 8);
|
||||||
|
userbuf[offset++] = (byte) (dwPrivilegeMap & 0x000000FF);
|
||||||
|
|
||||||
|
//dwAccountType,账户类型
|
||||||
|
//dwAccountType,account type
|
||||||
|
userbuf[offset++] = (byte) ((dwAccountType & 0xFF000000) >> 24);
|
||||||
|
userbuf[offset++] = (byte) ((dwAccountType & 0x00FF0000) >> 16);
|
||||||
|
userbuf[offset++] = (byte) ((dwAccountType & 0x0000FF00) >> 8);
|
||||||
|
userbuf[offset++] = (byte) (dwAccountType & 0x000000FF);
|
||||||
|
|
||||||
|
|
||||||
|
if (roomStrLength > 0) {
|
||||||
|
//roomStrLen
|
||||||
|
userbuf[offset++] = (byte) ((roomStrLength & 0xFF00) >> 8);
|
||||||
|
userbuf[offset++] = (byte) (roomStrLength & 0x00FF);
|
||||||
|
|
||||||
|
//roomStr
|
||||||
|
for (; offset < bufLength; ++offset) {
|
||||||
|
userbuf[offset] = (byte) RoomStr.charAt(offset - (bufLength - roomStrLength));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return userbuf;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017-2018 THL A29 Limited, a Tencent company. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.xinelu.common.utils.tencentcloudapi.trtc.v20190722;
|
||||||
|
|
||||||
|
import com.google.gson.JsonSyntaxException;
|
||||||
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
import com.xinelu.common.utils.tencentcloudapi.common.AbstractClient;
|
||||||
|
import com.xinelu.common.utils.tencentcloudapi.common.Credential;
|
||||||
|
import com.xinelu.common.utils.tencentcloudapi.common.JsonResponseModel;
|
||||||
|
import com.xinelu.common.utils.tencentcloudapi.common.exception.TencentCloudSDKException;
|
||||||
|
import com.xinelu.common.utils.tencentcloudapi.common.profile.ClientProfile;
|
||||||
|
import com.xinelu.common.utils.tencentcloudapi.trtc.v20190722.models.DissolveRoomRequest;
|
||||||
|
import com.xinelu.common.utils.tencentcloudapi.trtc.v20190722.models.DissolveRoomResponse;
|
||||||
|
import com.xinelu.common.utils.tencentcloudapi.trtc.v20190722.models.KickOutUserRequest;
|
||||||
|
import com.xinelu.common.utils.tencentcloudapi.trtc.v20190722.models.KickOutUserResponse;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
public class TrtcClient extends AbstractClient {
|
||||||
|
private static String endpoint = "trtc.tencentcloudapi.com";
|
||||||
|
private static String version = "2019-07-22";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造client
|
||||||
|
* @param credential 认证信息实例
|
||||||
|
* @param region 产品地域
|
||||||
|
*/
|
||||||
|
public TrtcClient(Credential credential, String region) {
|
||||||
|
this(credential, region, new ClientProfile());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造client
|
||||||
|
* @param credential 认证信息实例
|
||||||
|
* @param region 产品地域
|
||||||
|
* @param profile 配置实例
|
||||||
|
*/
|
||||||
|
public TrtcClient(Credential credential, String region, ClientProfile profile) {
|
||||||
|
super(TrtcClient.endpoint, TrtcClient.version, credential, region, profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*接口说明:把房间所有用户从房间踢出,解散房间。支持 TRTC SDK 6.6及以上版本,包括Android、iOS、Windows 和 macOS。
|
||||||
|
* @param req DissolveRoomRequest
|
||||||
|
* @return DissolveRoomResponse
|
||||||
|
* @throws TencentCloudSDKException
|
||||||
|
*/
|
||||||
|
public DissolveRoomResponse DissolveRoom(DissolveRoomRequest req) throws TencentCloudSDKException {
|
||||||
|
JsonResponseModel<DissolveRoomResponse> rsp = null;
|
||||||
|
try {
|
||||||
|
Type type = new TypeToken<JsonResponseModel<DissolveRoomResponse>>() {
|
||||||
|
}.getType();
|
||||||
|
rsp = gson.fromJson(this.internalRequest(req, "DissolveRoom"), type);
|
||||||
|
} catch (JsonSyntaxException e) {
|
||||||
|
throw new TencentCloudSDKException(e.getMessage());
|
||||||
|
}
|
||||||
|
return rsp.response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*接口说明:将用户从房间踢出。支持 TRTC SDK 6.6及以上版本,包括Android、iOS、Windows 和 macOS。
|
||||||
|
* @param req KickOutUserRequest
|
||||||
|
* @return KickOutUserResponse
|
||||||
|
* @throws TencentCloudSDKException
|
||||||
|
*/
|
||||||
|
public KickOutUserResponse KickOutUser(KickOutUserRequest req) throws TencentCloudSDKException{
|
||||||
|
JsonResponseModel<KickOutUserResponse> rsp = null;
|
||||||
|
try {
|
||||||
|
Type type = new TypeToken<JsonResponseModel<KickOutUserResponse>>() {
|
||||||
|
}.getType();
|
||||||
|
rsp = gson.fromJson(this.internalRequest(req, "KickOutUser"), type);
|
||||||
|
} catch (JsonSyntaxException e) {
|
||||||
|
throw new TencentCloudSDKException(e.getMessage());
|
||||||
|
}
|
||||||
|
return rsp.response;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017-2018 THL A29 Limited, a Tencent company. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.xinelu.common.utils.tencentcloudapi.trtc.v20190722.models;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.Expose;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
import com.xinelu.common.utils.tencentcloudapi.common.AbstractModel;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class DissolveRoomRequest extends AbstractModel {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TRTC的SDKAppId。
|
||||||
|
*/
|
||||||
|
@SerializedName("SdkAppId")
|
||||||
|
@Expose
|
||||||
|
private Long SdkAppId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 房间号。
|
||||||
|
*/
|
||||||
|
@SerializedName("RoomId")
|
||||||
|
@Expose
|
||||||
|
private Long RoomId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取TRTC的SDKAppId。
|
||||||
|
* @return SdkAppId TRTC的SDKAppId。
|
||||||
|
*/
|
||||||
|
public Long getSdkAppId() {
|
||||||
|
return this.SdkAppId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置TRTC的SDKAppId。
|
||||||
|
* @param SdkAppId TRTC的SDKAppId。
|
||||||
|
*/
|
||||||
|
public void setSdkAppId(Long SdkAppId) {
|
||||||
|
this.SdkAppId = SdkAppId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取房间号。
|
||||||
|
* @return RoomId 房间号。
|
||||||
|
*/
|
||||||
|
public Long getRoomId() {
|
||||||
|
return this.RoomId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置房间号。
|
||||||
|
* @param RoomId 房间号。
|
||||||
|
*/
|
||||||
|
public void setRoomId(Long RoomId) {
|
||||||
|
this.RoomId = RoomId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内部实现,用户禁止调用
|
||||||
|
*/
|
||||||
|
public void toMap(HashMap<String, String> map, String prefix) {
|
||||||
|
this.setParamSimple(map, prefix + "SdkAppId", this.SdkAppId);
|
||||||
|
this.setParamSimple(map, prefix + "RoomId", this.RoomId);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017-2018 THL A29 Limited, a Tencent company. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.xinelu.common.utils.tencentcloudapi.trtc.v20190722.models;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.Expose;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
import com.xinelu.common.utils.tencentcloudapi.common.AbstractModel;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class DissolveRoomResponse extends AbstractModel {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 唯一请求 ID,每次请求都会返回。定位问题时需要提供该次请求的 RequestId。
|
||||||
|
*/
|
||||||
|
@SerializedName("RequestId")
|
||||||
|
@Expose
|
||||||
|
private String RequestId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取唯一请求 ID,每次请求都会返回。定位问题时需要提供该次请求的 RequestId。
|
||||||
|
* @return RequestId 唯一请求 ID,每次请求都会返回。定位问题时需要提供该次请求的 RequestId。
|
||||||
|
*/
|
||||||
|
public String getRequestId() {
|
||||||
|
return this.RequestId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置唯一请求 ID,每次请求都会返回。定位问题时需要提供该次请求的 RequestId。
|
||||||
|
* @param RequestId 唯一请求 ID,每次请求都会返回。定位问题时需要提供该次请求的 RequestId。
|
||||||
|
*/
|
||||||
|
public void setRequestId(String RequestId) {
|
||||||
|
this.RequestId = RequestId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内部实现,用户禁止调用
|
||||||
|
*/
|
||||||
|
public void toMap(HashMap<String, String> map, String prefix) {
|
||||||
|
this.setParamSimple(map, prefix + "RequestId", this.RequestId);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017-2018 THL A29 Limited, a Tencent company. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.xinelu.common.utils.tencentcloudapi.trtc.v20190722.models;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.Expose;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
import com.xinelu.common.utils.tencentcloudapi.common.AbstractModel;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class KickOutUserRequest extends AbstractModel {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TRTC的SDKAppId。
|
||||||
|
*/
|
||||||
|
@SerializedName("SdkAppId")
|
||||||
|
@Expose
|
||||||
|
private Long SdkAppId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 房间号。
|
||||||
|
*/
|
||||||
|
@SerializedName("RoomId")
|
||||||
|
@Expose
|
||||||
|
private Long RoomId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 要踢的用户列表,最多10个。
|
||||||
|
*/
|
||||||
|
@SerializedName("UserIds")
|
||||||
|
@Expose
|
||||||
|
private String [] UserIds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取TRTC的SDKAppId。
|
||||||
|
* @return SdkAppId TRTC的SDKAppId。
|
||||||
|
*/
|
||||||
|
public Long getSdkAppId() {
|
||||||
|
return this.SdkAppId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置TRTC的SDKAppId。
|
||||||
|
* @param SdkAppId TRTC的SDKAppId。
|
||||||
|
*/
|
||||||
|
public void setSdkAppId(Long SdkAppId) {
|
||||||
|
this.SdkAppId = SdkAppId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取房间号。
|
||||||
|
* @return RoomId 房间号。
|
||||||
|
*/
|
||||||
|
public Long getRoomId() {
|
||||||
|
return this.RoomId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置房间号。
|
||||||
|
* @param RoomId 房间号。
|
||||||
|
*/
|
||||||
|
public void setRoomId(Long RoomId) {
|
||||||
|
this.RoomId = RoomId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取要踢的用户列表,最多10个。
|
||||||
|
* @return UserIds 要踢的用户列表,最多10个。
|
||||||
|
*/
|
||||||
|
public String [] getUserIds() {
|
||||||
|
return this.UserIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置要踢的用户列表,最多10个。
|
||||||
|
* @param UserIds 要踢的用户列表,最多10个。
|
||||||
|
*/
|
||||||
|
public void setUserIds(String [] UserIds) {
|
||||||
|
this.UserIds = UserIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内部实现,用户禁止调用
|
||||||
|
*/
|
||||||
|
public void toMap(HashMap<String, String> map, String prefix) {
|
||||||
|
this.setParamSimple(map, prefix + "SdkAppId", this.SdkAppId);
|
||||||
|
this.setParamSimple(map, prefix + "RoomId", this.RoomId);
|
||||||
|
this.setParamArraySimple(map, prefix + "UserIds.", this.UserIds);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2017-2018 THL A29 Limited, a Tencent company. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.xinelu.common.utils.tencentcloudapi.trtc.v20190722.models;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.Expose;
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
import com.xinelu.common.utils.tencentcloudapi.common.AbstractModel;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class KickOutUserResponse extends AbstractModel {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 唯一请求 ID,每次请求都会返回。定位问题时需要提供该次请求的 RequestId。
|
||||||
|
*/
|
||||||
|
@SerializedName("RequestId")
|
||||||
|
@Expose
|
||||||
|
private String RequestId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取唯一请求 ID,每次请求都会返回。定位问题时需要提供该次请求的 RequestId。
|
||||||
|
* @return RequestId 唯一请求 ID,每次请求都会返回。定位问题时需要提供该次请求的 RequestId。
|
||||||
|
*/
|
||||||
|
public String getRequestId() {
|
||||||
|
return this.RequestId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置唯一请求 ID,每次请求都会返回。定位问题时需要提供该次请求的 RequestId。
|
||||||
|
* @param RequestId 唯一请求 ID,每次请求都会返回。定位问题时需要提供该次请求的 RequestId。
|
||||||
|
*/
|
||||||
|
public void setRequestId(String RequestId) {
|
||||||
|
this.RequestId = RequestId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内部实现,用户禁止调用
|
||||||
|
*/
|
||||||
|
public void toMap(HashMap<String, String> map, String prefix) {
|
||||||
|
this.setParamSimple(map, prefix + "RequestId", this.RequestId);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
.antMatchers("/login", "/register", "/captchaImage").anonymous()
|
.antMatchers("/login", "/register", "/captchaImage").anonymous()
|
||||||
// 静态资源,可匿名访问
|
// 静态资源,可匿名访问
|
||||||
.antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
|
.antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
|
||||||
.antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**", "/nurseApplet/**", "/nurseApp/**").permitAll()
|
.antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**", "/nurseApplet/**", "/nurseApp/**", "/webSocket/**").permitAll()
|
||||||
// 除上面外的所有请求全部需要鉴权认证
|
// 除上面外的所有请求全部需要鉴权认证
|
||||||
.anyRequest().authenticated()
|
.anyRequest().authenticated()
|
||||||
.and()
|
.and()
|
||||||
|
|||||||
@ -0,0 +1,33 @@
|
|||||||
|
package com.xinelu.applet.controller.appletscreeningproject;
|
||||||
|
|
||||||
|
import com.xinelu.common.core.controller.BaseController;
|
||||||
|
import com.xinelu.common.core.domain.R;
|
||||||
|
import com.xinelu.manage.domain.screeningproject.ScreeningProject;
|
||||||
|
import com.xinelu.manage.service.screeningproject.IScreeningProjectService;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 项目控制器——小程序
|
||||||
|
* @author: haown
|
||||||
|
* @create: 2023-03-07 14:23
|
||||||
|
**/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/nurseApplet/screening/project")
|
||||||
|
@Api(tags = "项目控制器-小程序")
|
||||||
|
public class AppletScreeningProjectController extends BaseController {
|
||||||
|
@Resource
|
||||||
|
private IScreeningProjectService projectService;
|
||||||
|
|
||||||
|
@ApiOperation("筛查项目列表")
|
||||||
|
@GetMapping("list")
|
||||||
|
public R<List<ScreeningProject>> list(ScreeningProject project) {
|
||||||
|
List<ScreeningProject> list = projectService.findList(project);
|
||||||
|
return R.ok(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,131 @@
|
|||||||
|
package com.xinelu.applet.controller.appletscreeningrecord;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import com.xinelu.common.annotation.RepeatSubmit;
|
||||||
|
import com.xinelu.common.constant.ScreeningProjectConstants;
|
||||||
|
import com.xinelu.common.core.controller.BaseController;
|
||||||
|
import com.xinelu.common.core.domain.R;
|
||||||
|
import com.xinelu.common.core.page.TableDataInfo;
|
||||||
|
import com.xinelu.common.utils.DateUtils;
|
||||||
|
import com.xinelu.common.utils.StringUtils;
|
||||||
|
import com.xinelu.manage.dto.screeningrecord.ScreeningApplyDTO;
|
||||||
|
import com.xinelu.manage.dto.screeningrecord.ScreeningRecordDTO;
|
||||||
|
import com.xinelu.manage.service.patientinfo.IPatientInfoService;
|
||||||
|
import com.xinelu.manage.service.screeningrecord.IScreeningRecordService;
|
||||||
|
import com.xinelu.manage.vo.screeningrecord.ScreeningRecordVo;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Author mengkuiliang
|
||||||
|
* @Description 筛查预约控制器
|
||||||
|
* @Date 2023-01-29 13:57
|
||||||
|
* @Param
|
||||||
|
* @return
|
||||||
|
**/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/nurseApplet/screening/record")
|
||||||
|
@Api(tags = "筛查预约控制器-小程序")
|
||||||
|
public class AppletScreeningRecordController extends BaseController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IScreeningRecordService screeningRecordService;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IPatientInfoService patientService;
|
||||||
|
|
||||||
|
@GetMapping("/record")
|
||||||
|
@ApiOperation(value = "获取筛查结果记录")
|
||||||
|
public TableDataInfo record(ScreeningRecordDTO query) {
|
||||||
|
startPage();
|
||||||
|
query.setScreeningType("1");
|
||||||
|
query.setScreeningStatus("4");
|
||||||
|
return getDataTable(screeningRecordService.record(query));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/list")
|
||||||
|
@ApiOperation(value = "获取列表")
|
||||||
|
public TableDataInfo list(ScreeningRecordDTO query) {
|
||||||
|
startPage();
|
||||||
|
query.setScreeningType("1");
|
||||||
|
List<ScreeningRecordVo> list = screeningRecordService.list(query);
|
||||||
|
// 二维码返回
|
||||||
|
list.forEach(record -> {
|
||||||
|
StringUtils.isNotEmpty(record.getApplyBarcode());
|
||||||
|
// TODO 居民申请条码
|
||||||
|
//record.setApplyBarcode(patientService.getPicToBase64(record.getApplyBarcode()));
|
||||||
|
});
|
||||||
|
return getDataTable(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/save")
|
||||||
|
@ApiOperation(value = "预约")
|
||||||
|
@RepeatSubmit(interval = 2000, message = "请求过于频繁")
|
||||||
|
public R<String> save(@RequestBody ScreeningApplyDTO body) {
|
||||||
|
try {
|
||||||
|
if(!DateUtils.formatDate(body.getApplyStartTime(), "yyyy-MM-dd").equals(DateUtils.formatDate(body.getApplyEndTime(), "yyyy-MM-dd"))) {
|
||||||
|
return R.fail("预约日期请选择在同一天");
|
||||||
|
}
|
||||||
|
return R.ok(screeningRecordService.save(body));
|
||||||
|
} catch (Exception e) {
|
||||||
|
return R.fail(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/cancel/{screeningId}")
|
||||||
|
@ApiOperation(value = "取消预约")
|
||||||
|
public R<String> cancel(@PathVariable String screeningId) {
|
||||||
|
// 判断是否已登记
|
||||||
|
ScreeningRecordVo screeningRecordVo = screeningRecordService.detail(screeningId);
|
||||||
|
if (StringUtils.equals(screeningRecordVo.getScreeningStatus(), "3") || StringUtils.equals(screeningRecordVo.getScreeningStatus(), "4")) {
|
||||||
|
return R.fail("该预约已登记,不能取消");
|
||||||
|
}
|
||||||
|
screeningRecordService.cancel(screeningId);
|
||||||
|
return R.ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/detail/{screeningId}")
|
||||||
|
@ApiOperation(value = "获取预约详情")
|
||||||
|
public R<ScreeningRecordVo> detail(@PathVariable String screeningId) {
|
||||||
|
ScreeningRecordVo screeningRecordVo = screeningRecordService.detail(screeningId);
|
||||||
|
if (screeningRecordVo != null) {
|
||||||
|
// TODO 设置文件类型
|
||||||
|
//File fileInfo = sysFileService.getFile(screeningRecordVo.getAttachment());
|
||||||
|
//if (fileInfo != null) {
|
||||||
|
// screeningRecordVo.setFileType(fileInfo.getSuffix());
|
||||||
|
//}
|
||||||
|
if (!StringUtils.contains(screeningRecordVo.getProjectName(), ScreeningProjectConstants.ALZHEIMER)) {
|
||||||
|
screeningRecordService.getRecordDetail(screeningRecordVo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return R.ok(screeningRecordVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/getScreening/{registerId}")
|
||||||
|
@ApiOperation(value = "获取当前预约信息")
|
||||||
|
public R<ScreeningRecordVo> getScreeningByRegisterId(@PathVariable String registerId) {
|
||||||
|
return R.ok(screeningRecordService.getScreeningByRegisterId(registerId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/last/{registerId}/{projectId}")
|
||||||
|
@ApiOperation(value = "获取最新一次筛查结果")
|
||||||
|
public R<ScreeningRecordVo> last(@PathVariable String registerId, @PathVariable String projectId) {
|
||||||
|
ScreeningRecordVo screeningRecordVo = screeningRecordService.last(registerId, projectId);
|
||||||
|
return R.ok(screeningRecordVo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/getInfo/{assessRecordId}")
|
||||||
|
@ApiOperation(value = "推送筛查项目跳转查询推荐详情")
|
||||||
|
public R<JSONObject> getInfo(@PathVariable("assessRecordId") String assessRecordId) {
|
||||||
|
JSONObject jsonObject = screeningRecordService.getInfo(assessRecordId);
|
||||||
|
return R.ok(jsonObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,79 @@
|
|||||||
|
package com.xinelu.applet.controller.videoconsultation;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.RandomUtil;
|
||||||
|
import com.xinelu.common.core.domain.R;
|
||||||
|
import com.xinelu.common.core.dto.MessageTemplate;
|
||||||
|
import com.xinelu.common.enums.MessageContentType;
|
||||||
|
import com.xinelu.common.socket.WebSocketUtils;
|
||||||
|
import com.xinelu.common.utils.tencentcloudapi.common.Credential;
|
||||||
|
import com.xinelu.common.utils.tencentcloudapi.common.exception.TencentCloudSDKException;
|
||||||
|
import com.xinelu.common.utils.tencentcloudapi.common.profile.ClientProfile;
|
||||||
|
import com.xinelu.common.utils.tencentcloudapi.common.profile.HttpProfile;
|
||||||
|
import com.xinelu.common.utils.tencentcloudapi.trtc.v20190722.TLSSigAPIv2;
|
||||||
|
import com.xinelu.common.utils.tencentcloudapi.trtc.v20190722.TrtcClient;
|
||||||
|
import com.xinelu.common.utils.tencentcloudapi.trtc.v20190722.models.DissolveRoomRequest;
|
||||||
|
import com.xinelu.common.utils.tencentcloudapi.trtc.v20190722.models.DissolveRoomResponse;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import java.util.Date;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author gaoyu
|
||||||
|
* @description 远程会诊控制器
|
||||||
|
* @date 2022-12-07 9:49
|
||||||
|
*/
|
||||||
|
@Api(tags = "远程会诊控制器")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/nurseApplet/consultation")
|
||||||
|
public class VideoConsultationController {
|
||||||
|
|
||||||
|
@Value("${trtc.sdkappid}")
|
||||||
|
private String sdkappid;
|
||||||
|
@Value("${trtc.secretid}")
|
||||||
|
private String secretid;
|
||||||
|
@Value("${trtc.secretkey}")
|
||||||
|
private String secretkey;
|
||||||
|
private final static String ENDPOINT = "trtc.tencentcloudapi.com";
|
||||||
|
private final static String REGION = "ap-beijing";
|
||||||
|
|
||||||
|
@ApiOperation("获取userSig")
|
||||||
|
@GetMapping("getUserSig/{userId}")
|
||||||
|
public R<String> getUserSig(@PathVariable String userId) {
|
||||||
|
TLSSigAPIv2 sigAPIv2 = new TLSSigAPIv2(1600003294, "6b8b57a7eedb92b6646d1c81bd68681ab924e53b52069cd20b0f53c8e3801a18");
|
||||||
|
String userSig = sigAPIv2.genUserSig(userId, 36000);
|
||||||
|
return R.ok(userSig);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("开始会诊")
|
||||||
|
@GetMapping("start/{applyId}")
|
||||||
|
public R<String> start(@PathVariable String applyId) {
|
||||||
|
int roomId = RandomUtil.randomInt(1, 1000);
|
||||||
|
MessageTemplate msg = new MessageTemplate();
|
||||||
|
msg.setMessage(String.valueOf(roomId));
|
||||||
|
msg.setToKey(applyId);
|
||||||
|
msg.setMsgType(MessageContentType.CONSULTATION.name());
|
||||||
|
msg.setSendTime(new Date());
|
||||||
|
WebSocketUtils.sendMessage(applyId, msg);
|
||||||
|
return R.ok(String.valueOf(roomId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@ApiOperation("解散房间")
|
||||||
|
@GetMapping("dissolveRoom/{roomId}")
|
||||||
|
public R<?> dissolveRoom(@PathVariable String roomId) throws TencentCloudSDKException {
|
||||||
|
Credential cred = new Credential(secretid, secretkey);
|
||||||
|
HttpProfile httpProfile = new HttpProfile();
|
||||||
|
httpProfile.setEndpoint(ENDPOINT);
|
||||||
|
ClientProfile clientProfile = new ClientProfile();
|
||||||
|
clientProfile.setHttpProfile(httpProfile);
|
||||||
|
TrtcClient client = new TrtcClient(cred, REGION, clientProfile);
|
||||||
|
String params = "{\"SdkAppId\":" + sdkappid + ",\"RoomId\":" + roomId + "}";
|
||||||
|
DissolveRoomRequest req = DissolveRoomRequest.fromJsonString(params, DissolveRoomRequest.class);
|
||||||
|
DissolveRoomResponse resp = client.DissolveRoom(req);
|
||||||
|
return R.ok(resp.getRequestId());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
package com.xinelu.manage.controller.schedule;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description: 排班班次控制器
|
||||||
|
* @author: haown
|
||||||
|
* @create: 2023-09-21 17:25
|
||||||
|
**/
|
||||||
|
@ApiModel(value = "排班班次控制器")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/system/schedule")
|
||||||
|
public class ScheduleController {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -29,7 +29,7 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
* @create: 2023-01-19 10:49
|
* @create: 2023-01-19 10:49
|
||||||
**/
|
**/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/business/project")
|
@RequestMapping("/system/screening/project")
|
||||||
@Api(tags = "项目控制器")
|
@Api(tags = "项目控制器")
|
||||||
public class ScreeningProjectController extends BaseController {
|
public class ScreeningProjectController extends BaseController {
|
||||||
@Resource
|
@Resource
|
||||||
|
|||||||
@ -33,7 +33,7 @@ import org.springframework.web.bind.annotation.RestController;
|
|||||||
* @return
|
* @return
|
||||||
**/
|
**/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/business/screening")
|
@RequestMapping("/system/screening/record")
|
||||||
@Api(tags = "筛查预约控制器")
|
@Api(tags = "筛查预约控制器")
|
||||||
public class ScreeningRecordController extends BaseController {
|
public class ScreeningRecordController extends BaseController {
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,85 @@
|
|||||||
|
package com.xinelu.manage.domain.scheduleplan;
|
||||||
|
|
||||||
|
import com.xinelu.common.core.domain.BaseEntity;
|
||||||
|
import java.util.Date;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 医生排班计划表
|
||||||
|
* @TableName schedule_plan
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class SchedulePlan extends BaseEntity {
|
||||||
|
/**
|
||||||
|
* 主键
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 医院主键
|
||||||
|
*/
|
||||||
|
private Long hospitalId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 医院名称
|
||||||
|
*/
|
||||||
|
private String hospitalName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所属部门id
|
||||||
|
*/
|
||||||
|
private Long departmentId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所属部门名称
|
||||||
|
*/
|
||||||
|
private String departmentName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 班次主键
|
||||||
|
*/
|
||||||
|
private Long scheduleId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 班次名称
|
||||||
|
*/
|
||||||
|
private String scheduleName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 医生主键
|
||||||
|
*/
|
||||||
|
private Long doctorId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 医生姓名
|
||||||
|
*/
|
||||||
|
private String doctorName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排班开始日期
|
||||||
|
*/
|
||||||
|
private Date scheduleStartDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排班结束日期
|
||||||
|
*/
|
||||||
|
private Date scheduleEndDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每人可预约分钟数
|
||||||
|
*/
|
||||||
|
private Integer minutesPerPatient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 每天可预约人数
|
||||||
|
*/
|
||||||
|
private Integer patientsPerDay;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 出诊地点
|
||||||
|
*/
|
||||||
|
private String scheduleAddress;
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,55 @@
|
|||||||
|
package com.xinelu.manage.domain.scheduleplandetail;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 医生排班计划明细表
|
||||||
|
* @TableName schedule_plan_detail
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class SchedulePlanDetail implements Serializable {
|
||||||
|
/**
|
||||||
|
* 主键
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排班计划主键
|
||||||
|
*/
|
||||||
|
private Long schedulePlanId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 医生主键
|
||||||
|
*/
|
||||||
|
private Long doctorId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 医生姓名
|
||||||
|
*/
|
||||||
|
private String doctorName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排班日期
|
||||||
|
*/
|
||||||
|
private Date scheduleDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始时间
|
||||||
|
*/
|
||||||
|
private Date scheduleStartTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结束时间
|
||||||
|
*/
|
||||||
|
private Date scheduleEndTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 预约状态(0:未预约,1:已预约)
|
||||||
|
*/
|
||||||
|
private String applyState;
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
package com.xinelu.manage.mapper.scheduleplan;
|
||||||
|
|
||||||
|
import com.xinelu.manage.domain.scheduleplan.SchedulePlan;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author haown
|
||||||
|
* @description 针对表【schedule_plan(医生排班计划表)】的数据库操作Mapper
|
||||||
|
* @createDate 2023-09-21 17:17:23
|
||||||
|
* @Entity com.xinelu.manage.domain.scheduleplan.SchedulePlan
|
||||||
|
*/
|
||||||
|
public interface SchedulePlanMapper {
|
||||||
|
|
||||||
|
int deleteByPrimaryKey(Long id);
|
||||||
|
|
||||||
|
int insert(SchedulePlan record);
|
||||||
|
|
||||||
|
int insertSelective(SchedulePlan record);
|
||||||
|
|
||||||
|
SchedulePlan selectByPrimaryKey(Long id);
|
||||||
|
|
||||||
|
int updateByPrimaryKeySelective(SchedulePlan record);
|
||||||
|
|
||||||
|
int updateByPrimaryKey(SchedulePlan record);
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,25 @@
|
|||||||
|
package com.xinelu.manage.mapper.scheduleplandetail;
|
||||||
|
|
||||||
|
import com.xinelu.manage.domain.scheduleplandetail.SchedulePlanDetail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author haown
|
||||||
|
* @description 针对表【schedule_plan_detail(医生排班计划明细表)】的数据库操作Mapper
|
||||||
|
* @createDate 2023-09-21 17:22:22
|
||||||
|
* @Entity com.xinelu.manage.domain.scheduleplandetail.SchedulePlanDetail
|
||||||
|
*/
|
||||||
|
public interface SchedulePlanDetailMapper {
|
||||||
|
|
||||||
|
int deleteByPrimaryKey(Long id);
|
||||||
|
|
||||||
|
int insert(SchedulePlanDetail record);
|
||||||
|
|
||||||
|
int insertSelective(SchedulePlanDetail record);
|
||||||
|
|
||||||
|
SchedulePlanDetail selectByPrimaryKey(Long id);
|
||||||
|
|
||||||
|
int updateByPrimaryKeySelective(SchedulePlanDetail record);
|
||||||
|
|
||||||
|
int updateByPrimaryKey(SchedulePlanDetail record);
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
package com.xinelu.manage.service.scheduleplan;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author haown
|
||||||
|
* @description 针对表【schedule_plan(医生排班计划表)】的数据库操作Service
|
||||||
|
* @createDate 2023-09-21 17:16:40
|
||||||
|
*/
|
||||||
|
public interface SchedulePlanService {
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
package com.xinelu.manage.service.scheduleplan.impl;
|
||||||
|
|
||||||
|
import com.xinelu.manage.service.scheduleplan.SchedulePlanService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author haown
|
||||||
|
* @description 针对表【schedule_plan(医生排班计划表)】的数据库操作Service实现
|
||||||
|
* @createDate 2023-09-21 17:16:40
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class SchedulePlanServiceImpl implements SchedulePlanService{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
package com.xinelu.manage.service.scheduleplandetail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author haown
|
||||||
|
* @description 针对表【schedule_plan_detail(医生排班计划明细表)】的数据库操作Service
|
||||||
|
* @createDate 2023-09-21 17:21:38
|
||||||
|
*/
|
||||||
|
public interface SchedulePlanDetailService {
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
package com.xinelu.manage.service.scheduleplandetail.impl;
|
||||||
|
|
||||||
|
import com.xinelu.manage.service.scheduleplandetail.SchedulePlanDetailService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author haown
|
||||||
|
* @description 针对表【schedule_plan_detail(医生排班计划明细表)】的数据库操作Service实现
|
||||||
|
* @createDate 2023-09-21 17:21:38
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class SchedulePlanDetailServiceImpl implements SchedulePlanDetailService{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,187 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.xinelu.manage.mapper.scheduleplan.SchedulePlanMapper">
|
||||||
|
|
||||||
|
<resultMap id="BaseResultMap" type="com.xinelu.manage.domain.scheduleplan.SchedulePlan">
|
||||||
|
<id property="id" column="id" jdbcType="BIGINT"/>
|
||||||
|
<result property="hospitalId" column="hospital_id" jdbcType="BIGINT"/>
|
||||||
|
<result property="hospitalName" column="hospital_name" jdbcType="VARCHAR"/>
|
||||||
|
<result property="departmentId" column="department_id" jdbcType="BIGINT"/>
|
||||||
|
<result property="departmentName" column="department_name" jdbcType="VARCHAR"/>
|
||||||
|
<result property="scheduleId" column="schedule_id" jdbcType="BIGINT"/>
|
||||||
|
<result property="scheduleName" column="schedule_name" jdbcType="VARCHAR"/>
|
||||||
|
<result property="doctorId" column="doctor_id" jdbcType="BIGINT"/>
|
||||||
|
<result property="doctorName" column="doctor_name" jdbcType="VARCHAR"/>
|
||||||
|
<result property="scheduleStartDate" column="schedule_start_date" jdbcType="DATE"/>
|
||||||
|
<result property="scheduleEndDate" column="schedule_end_date" jdbcType="DATE"/>
|
||||||
|
<result property="minutesPerPatient" column="minutes_per_patient" jdbcType="INTEGER"/>
|
||||||
|
<result property="patientsPerDay" column="patients_per_day" jdbcType="INTEGER"/>
|
||||||
|
<result property="scheduleAddress" column="schedule_address" jdbcType="VARCHAR"/>
|
||||||
|
<result property="createBy" column="create_by" jdbcType="VARCHAR"/>
|
||||||
|
<result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
|
||||||
|
<result property="updateBy" column="update_by" jdbcType="VARCHAR"/>
|
||||||
|
<result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<sql id="Base_Column_List">
|
||||||
|
id,hospital_id,hospital_name,
|
||||||
|
department_id,department_name,schedule_id,
|
||||||
|
schedule_name,doctor_id,doctor_name,
|
||||||
|
schedule_start_date,schedule_end_date,minutes_per_patient,
|
||||||
|
patients_per_day,schedule_address,create_by,
|
||||||
|
create_time,update_by,update_time
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
|
||||||
|
select
|
||||||
|
<include refid="Base_Column_List" />
|
||||||
|
from schedule_plan
|
||||||
|
where id = #{id,jdbcType=BIGINT}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
|
||||||
|
delete from schedule_plan
|
||||||
|
where id = #{id,jdbcType=BIGINT}
|
||||||
|
</delete>
|
||||||
|
<insert id="insert" keyColumn="id" keyProperty="id" parameterType="com.xinelu.manage.domain.scheduleplan.SchedulePlan" useGeneratedKeys="true">
|
||||||
|
insert into schedule_plan
|
||||||
|
( id,hospital_id,hospital_name
|
||||||
|
,department_id,department_name,schedule_id
|
||||||
|
,schedule_name,doctor_id,doctor_name
|
||||||
|
,schedule_start_date,schedule_end_date,minutes_per_patient
|
||||||
|
,patients_per_day,schedule_address,create_by
|
||||||
|
,create_time,update_by,update_time
|
||||||
|
)
|
||||||
|
values (#{id,jdbcType=BIGINT},#{hospitalId,jdbcType=BIGINT},#{hospitalName,jdbcType=VARCHAR}
|
||||||
|
,#{departmentId,jdbcType=BIGINT},#{departmentName,jdbcType=VARCHAR},#{scheduleId,jdbcType=BIGINT}
|
||||||
|
,#{scheduleName,jdbcType=VARCHAR},#{doctorId,jdbcType=BIGINT},#{doctorName,jdbcType=VARCHAR}
|
||||||
|
,#{scheduleStartDate,jdbcType=DATE},#{scheduleEndDate,jdbcType=DATE},#{minutesPerPatient,jdbcType=INTEGER}
|
||||||
|
,#{patientsPerDay,jdbcType=INTEGER},#{scheduleAddress,jdbcType=VARCHAR},#{createBy,jdbcType=VARCHAR}
|
||||||
|
,#{createTime,jdbcType=TIMESTAMP},#{updateBy,jdbcType=VARCHAR},#{updateTime,jdbcType=TIMESTAMP}
|
||||||
|
)
|
||||||
|
</insert>
|
||||||
|
<insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="com.xinelu.manage.domain.scheduleplan.SchedulePlan" useGeneratedKeys="true">
|
||||||
|
insert into schedule_plan
|
||||||
|
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||||
|
<if test="id != null">id,</if>
|
||||||
|
<if test="hospitalId != null">hospital_id,</if>
|
||||||
|
<if test="hospitalName != null">hospital_name,</if>
|
||||||
|
<if test="departmentId != null">department_id,</if>
|
||||||
|
<if test="departmentName != null">department_name,</if>
|
||||||
|
<if test="scheduleId != null">schedule_id,</if>
|
||||||
|
<if test="scheduleName != null">schedule_name,</if>
|
||||||
|
<if test="doctorId != null">doctor_id,</if>
|
||||||
|
<if test="doctorName != null">doctor_name,</if>
|
||||||
|
<if test="scheduleStartDate != null">schedule_start_date,</if>
|
||||||
|
<if test="scheduleEndDate != null">schedule_end_date,</if>
|
||||||
|
<if test="minutesPerPatient != null">minutes_per_patient,</if>
|
||||||
|
<if test="patientsPerDay != null">patients_per_day,</if>
|
||||||
|
<if test="scheduleAddress != null">schedule_address,</if>
|
||||||
|
<if test="createBy != null">create_by,</if>
|
||||||
|
<if test="createTime != null">create_time,</if>
|
||||||
|
<if test="updateBy != null">update_by,</if>
|
||||||
|
<if test="updateTime != null">update_time,</if>
|
||||||
|
</trim>
|
||||||
|
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||||
|
<if test="id != null">#{id,jdbcType=BIGINT},</if>
|
||||||
|
<if test="hospitalId != null">#{hospitalId,jdbcType=BIGINT},</if>
|
||||||
|
<if test="hospitalName != null">#{hospitalName,jdbcType=VARCHAR},</if>
|
||||||
|
<if test="departmentId != null">#{departmentId,jdbcType=BIGINT},</if>
|
||||||
|
<if test="departmentName != null">#{departmentName,jdbcType=VARCHAR},</if>
|
||||||
|
<if test="scheduleId != null">#{scheduleId,jdbcType=BIGINT},</if>
|
||||||
|
<if test="scheduleName != null">#{scheduleName,jdbcType=VARCHAR},</if>
|
||||||
|
<if test="doctorId != null">#{doctorId,jdbcType=BIGINT},</if>
|
||||||
|
<if test="doctorName != null">#{doctorName,jdbcType=VARCHAR},</if>
|
||||||
|
<if test="scheduleStartDate != null">#{scheduleStartDate,jdbcType=DATE},</if>
|
||||||
|
<if test="scheduleEndDate != null">#{scheduleEndDate,jdbcType=DATE},</if>
|
||||||
|
<if test="minutesPerPatient != null">#{minutesPerPatient,jdbcType=INTEGER},</if>
|
||||||
|
<if test="patientsPerDay != null">#{patientsPerDay,jdbcType=INTEGER},</if>
|
||||||
|
<if test="scheduleAddress != null">#{scheduleAddress,jdbcType=VARCHAR},</if>
|
||||||
|
<if test="createBy != null">#{createBy,jdbcType=VARCHAR},</if>
|
||||||
|
<if test="createTime != null">#{createTime,jdbcType=TIMESTAMP},</if>
|
||||||
|
<if test="updateBy != null">#{updateBy,jdbcType=VARCHAR},</if>
|
||||||
|
<if test="updateTime != null">#{updateTime,jdbcType=TIMESTAMP},</if>
|
||||||
|
</trim>
|
||||||
|
</insert>
|
||||||
|
<update id="updateByPrimaryKeySelective" parameterType="com.xinelu.manage.domain.scheduleplan.SchedulePlan">
|
||||||
|
update schedule_plan
|
||||||
|
<set>
|
||||||
|
<if test="hospitalId != null">
|
||||||
|
hospital_id = #{hospitalId,jdbcType=BIGINT},
|
||||||
|
</if>
|
||||||
|
<if test="hospitalName != null">
|
||||||
|
hospital_name = #{hospitalName,jdbcType=VARCHAR},
|
||||||
|
</if>
|
||||||
|
<if test="departmentId != null">
|
||||||
|
department_id = #{departmentId,jdbcType=BIGINT},
|
||||||
|
</if>
|
||||||
|
<if test="departmentName != null">
|
||||||
|
department_name = #{departmentName,jdbcType=VARCHAR},
|
||||||
|
</if>
|
||||||
|
<if test="scheduleId != null">
|
||||||
|
schedule_id = #{scheduleId,jdbcType=BIGINT},
|
||||||
|
</if>
|
||||||
|
<if test="scheduleName != null">
|
||||||
|
schedule_name = #{scheduleName,jdbcType=VARCHAR},
|
||||||
|
</if>
|
||||||
|
<if test="doctorId != null">
|
||||||
|
doctor_id = #{doctorId,jdbcType=BIGINT},
|
||||||
|
</if>
|
||||||
|
<if test="doctorName != null">
|
||||||
|
doctor_name = #{doctorName,jdbcType=VARCHAR},
|
||||||
|
</if>
|
||||||
|
<if test="scheduleStartDate != null">
|
||||||
|
schedule_start_date = #{scheduleStartDate,jdbcType=DATE},
|
||||||
|
</if>
|
||||||
|
<if test="scheduleEndDate != null">
|
||||||
|
schedule_end_date = #{scheduleEndDate,jdbcType=DATE},
|
||||||
|
</if>
|
||||||
|
<if test="minutesPerPatient != null">
|
||||||
|
minutes_per_patient = #{minutesPerPatient,jdbcType=INTEGER},
|
||||||
|
</if>
|
||||||
|
<if test="patientsPerDay != null">
|
||||||
|
patients_per_day = #{patientsPerDay,jdbcType=INTEGER},
|
||||||
|
</if>
|
||||||
|
<if test="scheduleAddress != null">
|
||||||
|
schedule_address = #{scheduleAddress,jdbcType=VARCHAR},
|
||||||
|
</if>
|
||||||
|
<if test="createBy != null">
|
||||||
|
create_by = #{createBy,jdbcType=VARCHAR},
|
||||||
|
</if>
|
||||||
|
<if test="createTime != null">
|
||||||
|
create_time = #{createTime,jdbcType=TIMESTAMP},
|
||||||
|
</if>
|
||||||
|
<if test="updateBy != null">
|
||||||
|
update_by = #{updateBy,jdbcType=VARCHAR},
|
||||||
|
</if>
|
||||||
|
<if test="updateTime != null">
|
||||||
|
update_time = #{updateTime,jdbcType=TIMESTAMP},
|
||||||
|
</if>
|
||||||
|
</set>
|
||||||
|
where id = #{id,jdbcType=BIGINT}
|
||||||
|
</update>
|
||||||
|
<update id="updateByPrimaryKey" parameterType="com.xinelu.manage.domain.scheduleplan.SchedulePlan">
|
||||||
|
update schedule_plan
|
||||||
|
set
|
||||||
|
hospital_id = #{hospitalId,jdbcType=BIGINT},
|
||||||
|
hospital_name = #{hospitalName,jdbcType=VARCHAR},
|
||||||
|
department_id = #{departmentId,jdbcType=BIGINT},
|
||||||
|
department_name = #{departmentName,jdbcType=VARCHAR},
|
||||||
|
schedule_id = #{scheduleId,jdbcType=BIGINT},
|
||||||
|
schedule_name = #{scheduleName,jdbcType=VARCHAR},
|
||||||
|
doctor_id = #{doctorId,jdbcType=BIGINT},
|
||||||
|
doctor_name = #{doctorName,jdbcType=VARCHAR},
|
||||||
|
schedule_start_date = #{scheduleStartDate,jdbcType=DATE},
|
||||||
|
schedule_end_date = #{scheduleEndDate,jdbcType=DATE},
|
||||||
|
minutes_per_patient = #{minutesPerPatient,jdbcType=INTEGER},
|
||||||
|
patients_per_day = #{patientsPerDay,jdbcType=INTEGER},
|
||||||
|
schedule_address = #{scheduleAddress,jdbcType=VARCHAR},
|
||||||
|
create_by = #{createBy,jdbcType=VARCHAR},
|
||||||
|
create_time = #{createTime,jdbcType=TIMESTAMP},
|
||||||
|
update_by = #{updateBy,jdbcType=VARCHAR},
|
||||||
|
update_time = #{updateTime,jdbcType=TIMESTAMP}
|
||||||
|
where id = #{id,jdbcType=BIGINT}
|
||||||
|
</update>
|
||||||
|
</mapper>
|
||||||
@ -0,0 +1,106 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE mapper
|
||||||
|
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
|
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||||
|
<mapper namespace="com.xinelu.manage.mapper.scheduleplandetail.SchedulePlanDetailMapper">
|
||||||
|
|
||||||
|
<resultMap id="BaseResultMap" type="com.xinelu.manage.domain.scheduleplandetail.SchedulePlanDetail">
|
||||||
|
<id property="id" column="id" jdbcType="BIGINT"/>
|
||||||
|
<result property="schedulePlanId" column="schedule_plan_id" jdbcType="BIGINT"/>
|
||||||
|
<result property="doctorId" column="doctor_id" jdbcType="BIGINT"/>
|
||||||
|
<result property="doctorName" column="doctor_name" jdbcType="VARCHAR"/>
|
||||||
|
<result property="scheduleDate" column="schedule_date" jdbcType="DATE"/>
|
||||||
|
<result property="scheduleStartTime" column="schedule_start_time" jdbcType="TIME"/>
|
||||||
|
<result property="scheduleEndTime" column="schedule_end_time" jdbcType="TIME"/>
|
||||||
|
<result property="applyState" column="apply_state" jdbcType="VARCHAR"/>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<sql id="Base_Column_List">
|
||||||
|
id,schedule_plan_id,doctor_id,
|
||||||
|
doctor_name,schedule_date,schedule_start_time,
|
||||||
|
schedule_end_time,apply_state
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
|
||||||
|
select
|
||||||
|
<include refid="Base_Column_List" />
|
||||||
|
from schedule_plan_detail
|
||||||
|
where id = #{id,jdbcType=BIGINT}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
|
||||||
|
delete from schedule_plan_detail
|
||||||
|
where id = #{id,jdbcType=BIGINT}
|
||||||
|
</delete>
|
||||||
|
<insert id="insert" keyColumn="id" keyProperty="id" parameterType="com.xinelu.manage.domain.scheduleplandetail.SchedulePlanDetail" useGeneratedKeys="true">
|
||||||
|
insert into schedule_plan_detail
|
||||||
|
( id,schedule_plan_id,doctor_id
|
||||||
|
,doctor_name,schedule_date,schedule_start_time
|
||||||
|
,schedule_end_time,apply_state)
|
||||||
|
values (#{id,jdbcType=BIGINT},#{schedulePlanId,jdbcType=BIGINT},#{doctorId,jdbcType=BIGINT}
|
||||||
|
,#{doctorName,jdbcType=VARCHAR},#{scheduleDate,jdbcType=DATE},#{scheduleStartTime,jdbcType=TIME}
|
||||||
|
,#{scheduleEndTime,jdbcType=TIME},#{applyState,jdbcType=VARCHAR})
|
||||||
|
</insert>
|
||||||
|
<insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="com.xinelu.manage.domain.scheduleplandetail.SchedulePlanDetail" useGeneratedKeys="true">
|
||||||
|
insert into schedule_plan_detail
|
||||||
|
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||||
|
<if test="id != null">id,</if>
|
||||||
|
<if test="schedulePlanId != null">schedule_plan_id,</if>
|
||||||
|
<if test="doctorId != null">doctor_id,</if>
|
||||||
|
<if test="doctorName != null">doctor_name,</if>
|
||||||
|
<if test="scheduleDate != null">schedule_date,</if>
|
||||||
|
<if test="scheduleStartTime != null">schedule_start_time,</if>
|
||||||
|
<if test="scheduleEndTime != null">schedule_end_time,</if>
|
||||||
|
<if test="applyState != null">apply_state,</if>
|
||||||
|
</trim>
|
||||||
|
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||||
|
<if test="id != null">#{id,jdbcType=BIGINT},</if>
|
||||||
|
<if test="schedulePlanId != null">#{schedulePlanId,jdbcType=BIGINT},</if>
|
||||||
|
<if test="doctorId != null">#{doctorId,jdbcType=BIGINT},</if>
|
||||||
|
<if test="doctorName != null">#{doctorName,jdbcType=VARCHAR},</if>
|
||||||
|
<if test="scheduleDate != null">#{scheduleDate,jdbcType=DATE},</if>
|
||||||
|
<if test="scheduleStartTime != null">#{scheduleStartTime,jdbcType=TIME},</if>
|
||||||
|
<if test="scheduleEndTime != null">#{scheduleEndTime,jdbcType=TIME},</if>
|
||||||
|
<if test="applyState != null">#{applyState,jdbcType=VARCHAR},</if>
|
||||||
|
</trim>
|
||||||
|
</insert>
|
||||||
|
<update id="updateByPrimaryKeySelective" parameterType="com.xinelu.manage.domain.scheduleplandetail.SchedulePlanDetail">
|
||||||
|
update schedule_plan_detail
|
||||||
|
<set>
|
||||||
|
<if test="schedulePlanId != null">
|
||||||
|
schedule_plan_id = #{schedulePlanId,jdbcType=BIGINT},
|
||||||
|
</if>
|
||||||
|
<if test="doctorId != null">
|
||||||
|
doctor_id = #{doctorId,jdbcType=BIGINT},
|
||||||
|
</if>
|
||||||
|
<if test="doctorName != null">
|
||||||
|
doctor_name = #{doctorName,jdbcType=VARCHAR},
|
||||||
|
</if>
|
||||||
|
<if test="scheduleDate != null">
|
||||||
|
schedule_date = #{scheduleDate,jdbcType=DATE},
|
||||||
|
</if>
|
||||||
|
<if test="scheduleStartTime != null">
|
||||||
|
schedule_start_time = #{scheduleStartTime,jdbcType=TIME},
|
||||||
|
</if>
|
||||||
|
<if test="scheduleEndTime != null">
|
||||||
|
schedule_end_time = #{scheduleEndTime,jdbcType=TIME},
|
||||||
|
</if>
|
||||||
|
<if test="applyState != null">
|
||||||
|
apply_state = #{applyState,jdbcType=VARCHAR},
|
||||||
|
</if>
|
||||||
|
</set>
|
||||||
|
where id = #{id,jdbcType=BIGINT}
|
||||||
|
</update>
|
||||||
|
<update id="updateByPrimaryKey" parameterType="com.xinelu.manage.domain.scheduleplandetail.SchedulePlanDetail">
|
||||||
|
update schedule_plan_detail
|
||||||
|
set
|
||||||
|
schedule_plan_id = #{schedulePlanId,jdbcType=BIGINT},
|
||||||
|
doctor_id = #{doctorId,jdbcType=BIGINT},
|
||||||
|
doctor_name = #{doctorName,jdbcType=VARCHAR},
|
||||||
|
schedule_date = #{scheduleDate,jdbcType=DATE},
|
||||||
|
schedule_start_time = #{scheduleStartTime,jdbcType=TIME},
|
||||||
|
schedule_end_time = #{scheduleEndTime,jdbcType=TIME},
|
||||||
|
apply_state = #{applyState,jdbcType=VARCHAR}
|
||||||
|
where id = #{id,jdbcType=BIGINT}
|
||||||
|
</update>
|
||||||
|
</mapper>
|
||||||
Loading…
Reference in New Issue
Block a user