最近项目中用到了腾讯IM,写篇文章记录一下。
1.对接方法代码
@Slf4j
public class IMUtil {
private static Logger logger = LogManager.getLogger(IMUtil.class);
//创建应用时即时通信 IM 控制台分配的 SDKAppID
private static long sdkappid = ImConfig.sdkappid;
//App 管理员帐号
private static String identifier = ImConfig.identifier;
//账号秘钥,用于生成签名
private static String key = ImConfig.key;
//签名过期时间
private static String expire = ImConfig.expire;
//服务器域名
private static String host= ImConfig.host;
/**
* 获取用户签名
*
* @return
*/
public static String getSign(String identifier) {
//TLSSigAPIv2这个类就是官方给的,直接拿过来就是了
TLSSigAPIv2 tlsSigAPIv2 = new TLSSigAPIv2(sdkappid, key);
//这两行可以忽略,因为我存在properties文件中的格式是24*3600*180
String[] time = expire.split("\\*");
long expireTime = Long.valueOf(time[0]) * Long.valueOf(time[1]) * Long.valueOf(time[2]);
return tlsSigAPIv2.genSig(identifier, expireTime);
}
/**
* 调用接口
*
* @param url
* @param json
* @return
*/
public static String doPostJson(String url, String json) {
//获取签名
String userSig = getSign(identifier);
//请求地址
String address = "https://console.tim.qq.com/" + url + "?sdkappid=" +
sdkappid + "&identifier=" + identifier + "&usersig=" +
userSig + "&random=99999999&contenttype=json";
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";
try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(address);
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(5000).setConnectionRequestTimeout(1000)
.setSocketTimeout(5000).build();
httpPost.setConfig(requestConfig);
// 创建请求内容
StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
httpPost.setEntity(entity);
// 执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
JSONObject jsonObject = new JSONObject(resultString);
if (jsonObject.get("ActionStatus").equals("FAIL")) {
logger.error("IM发送异常 jsonObject=" + jsonObject);
throw new BizException("腾讯IM校验失败,请重试!");
}
return resultString;
}
/**
* 修改头像、姓名
*
* @param id
* @param head
* @param name
* @return
*/
public static String updateHeadOrName(String id, String head, String name) {
JSONArray list = new JSONArray();
if (StringUtils.isNotBlank(head)) {
JSONObject headJson = new JSONObject();
headJson.put("Tag", "Tag_Profile_IM_Image");
if (head.startsWith("/pic")) {
headJson.put("Value", host + head);
} else {
headJson.put("Value", head);
}
list.put(headJson);
}
if (StringUtils.isNotBlank(name)) {
JSONObject nameJson = new JSONObject();
nameJson.put("Tag", "Tag_Profile_IM_Nick");
nameJson.put("Value", name);
list.put(nameJson);
}
JSONObject json = new JSONObject();
json.put("From_Account", id);
json.put("ProfileItem", list);
String result = doPostJson("v4/profile/portrait_set", json.toString());
return result;
}
/**
* 加入群组
*
* @param imIdentifier
* @param groupId
* @return
*/
public static String joinGroup(String imIdentifier, String groupId) {
JSONObject stuJson = new JSONObject();
stuJson.put("Member_Account", imIdentifier);
JSONArray stuArray = new JSONArray();
stuArray.put(stuJson);
JSONObject json = new JSONObject();
json.put("GroupId", groupId);
json.put("Silence", 1);
json.put("MemberList", stuArray);
return doPostJson("v4/group_open_http_svc/add_group_member", json.toString());
}
/**
* 发送系统通知
*
* @param groupId
* @param content
* @return
*/
public static String sendGroupNotice(String groupId, String content) {
JSONObject msg = new JSONObject();
msg.put("Text", content);
JSONObject msgJson = new JSONObject();
msgJson.put("MsgType", "TIMTextElem");
msgJson.put("MsgContent", msg);
JSONArray msgArr = new JSONArray();
msgArr.put(msgJson);
JSONObject json = new JSONObject();
json.put("GroupId", groupId);
json.put("Random", 8912345);
json.put("MsgBody", msgArr);
return IMUtil.doPostJson("v4/group_open_http_svc/send_group_msg", json.toString());
}
/**
* 注册im账号
*
* @param imIdentifier
* @param name
* @return
*/
public static String register(String imIdentifier, String name, String headUrl) {
JSONObject json = new JSONObject();
json.put("Identifier", imIdentifier);
json.put("Nick", name);
if (StringUtils.isNotBlank(headUrl)) {
//pic是我本地服务器存放图片的目录,这里可以根据自己情况改一下
if (headUrl.startsWith("/pic")) {
json.put("FaceUrl",host + headUrl);
} else {
json.put("FaceUrl", headUrl);
}
}
return IMUtil.doPostJson("v4/im_open_login_svc/account_import", json.toString());
}
/**
* 设置用户角色
*
* @param imIdentifier
* @param role
* @return
*/
public static String setRole(String imIdentifier, int role) {
JSONObject json = new JSONObject();
JSONObject keyJson = new JSONObject();
keyJson.put("Tag", "Tag_Profile_IM_Role");
keyJson.put("Value", role);
JSONArray keyArr = new JSONArray();
keyArr.put(keyJson);
json.put("From_Account", imIdentifier);
json.put("ProfileItem", keyArr);
return IMUtil.doPostJson("v4/profile/portrait_set", json.toString());
}
/**
* 删除群组信息
*
* @return
*/
public static String deleteGroup(String groupId) {
JSONObject json = new JSONObject();
json.put("GroupId", groupId);
String result = IMUtil.doPostJson("v4/group_open_http_svc/destroy_group", json.toString());
return result;
}
/**
* 获取群组信息
*
* @return
*/
public static String getGroupInfo(String groupId) {
JSONObject json = new JSONObject();
List<String> list = Lists.newArrayList();
list.add(groupId);
json.put("GroupIdList", list);
json.put("GroupBaseInfoFilter", "GroupBaseInfoFilter");
String result = IMUtil.doPostJson("v4/group_open_http_svc/get_group_info", json.toString());
result = result.substring(result.indexOf("Name") + 7, result.indexOf("NextMsgSeq") - 3);
System.out.println("[------------" + result + "-----------------]");
return result;
}
/**
* 更新群组名称
*
* @return
*/
public static String updateGroupInfo(String groupId, String name) {
JSONObject json = new JSONObject();
json.put("GroupId", groupId);
json.put("Name", name);
String result = IMUtil.doPostJson("v4/group_open_http_svc/modify_group_base_info", json.toString());
return result;
}
/**
* 帐号检查接口
*
* @param userId
* @return
*/
public static Boolean accountCheck(String userId) {
JSONObject userJson = new JSONObject();
userJson.put("UserID", userId);
JSONObject json = new JSONObject();
List list = new ArrayList();
list.add(userJson);
json.put("CheckItem", list);
String result = IMUtil.doPostJson("v4/im_open_login_svc/account_check", json.toString());
JSONObject jsonResult = new JSONObject(result);
JSONArray jsonArray = (JSONArray) jsonResult.get("ResultItem");
JSONObject jsonObject = (JSONObject) jsonArray.get(0);
return (Integer) jsonObject.get("ResultCode") == 0 && "Imported".equals(jsonObject.get("AccountStatus"));
}
}
2.碰到的一些坑
- 类找不到异常:sun.misc.BASE64Encoder
使用官方文档中生成签名的方法中用到这个类,一开始在本地可以,部署到服务器却一直报类找不到,看了一眼这个类是jdk里的呀,怎么会找不到,难道是jdk中有猫腻?
马上查了一下本地和服务器jdk的版本,果然不一样,本地1.8,服务器11,11中就删了?
百度了一下,果然,从jdk9开始删除了rt.jar,而这个类正好在这个jar中,解决办法就是换一种base64的解密类,有很多,我换成了:
java.util.Base64
加密:Base64.getEncoder().encodeToString
解密:Base64.getDecoder().decode
- 注册好的用户无法登录
我们这边具体的聊天是直接在前端调用腾讯IM的,要传ID和用户签名,ID我直接用的我们数据库的ID,问题就出在签名上。
一开始自己用的注册的那个签名,最后发现不是,那个签名是管理员的签名,每个用户自己的签名还需要调用一次生成签名的方法生成签名,每个人都不一样的。 - 头像无法显示
一开始自己直接把服务器上的头像地址直接给了腾讯IM,发现那边无法访问,需要在这个基础前面再加上你服务器的域名前缀,像http://xx.xx.xx:8080这种,如果直接用的第三方的头像就不用加了,所以我在代码加了个判断。