融雲java伺服器端--好友關係
官方提供的伺服器端程式碼是用nodejs寫的(地址https://github.com/sealtalk/sealtalk-server),我需要改成用spring-boot實現。
也是費了好大的功夫。
融雲【單聊】的機制在於,只要知道 兩個人的 id,就能互相傳送訊息,不管是不是好友,所以就需要 我們自己寫的後臺 來 限制下:不是好友就不能互相聊天。
注意:如果使用者 A 把 B 給刪了,但在B 的app上還有對話視窗存在的話,此時按照融雲的機制, B 還是可以和 A聊天的,這個時候 就需要使用【融雲API】把 B 新增到 A 的【黑名單】裡面,這樣二者就無法通訊了。
這裡得廢話一句:進入融雲後臺,右上角找到【我的控制檯】點選進去,
左下角找到【API呼叫】,先再這裡面除錯程式,能起到事半功倍的效果!!
一、資料庫表rongcloud_friendship
CREATE TABLE `rongcloud_friendship` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `user_id` varchar(25) NOT NULL COMMENT '當前使用者id', `friend_id` varchar(25) NOT NULL COMMENT '好友id', `display_name` varchar(32) DEFAULT '' COMMENT '備註名', `message` varchar(64) DEFAULT NULL COMMENT '加好友時的“請求資訊”', `status` int(10) unsigned DEFAULT NULL COMMENT '10: 請求, 11: 被請求, 20: 同意, 21: 忽略, 30: 被刪除', `create_time` datetime DEFAULT NULL COMMENT '建立時間', `update_time` datetime DEFAULT NULL COMMENT '更新時間', PRIMARY KEY (`id`), UNIQUE KEY `friendship_user_id_friend_id` (`user_id`,`friend_id`) ) ENGINE=InnoDB AUTO_INCREMENT=34 DEFAULT CHARSET=utf8;
二、status定義
好友之間的關係
status值 |
欄位 |
說明 |
10 |
REQUESTING |
請求 |
11 |
REQUESTED |
被請求 |
20 |
AGREED |
同意 |
21 |
IGNORED |
忽略 |
30 |
DELETED |
被刪除 |
一張圖瞭解:
三、返回格式定義:
public class RongCloudResultDataObject<T> {
/***錯誤程式碼**/
private Integer code;
/**訊息**/
private String msg;
/**訊息體**/
private T result;
/**此處是getter和setter*/
}
public class RongCloudResultUtil {
public static RongCloudResultDataObject success(int code, String msg, Object object){
RongCloudResultDataObject resultObject = new RongCloudResultDataObject();
resultObject.setCode(code);
resultObject.setMsg(msg);
resultObject.setResult(object);
return resultObject;
}
/**
* 定義錯誤返回格式
* @param code
* @param msg
* @return
*/
public static RongCloudResultDataObject error(Integer code , String msg){
RongCloudResultDataObject resultObject = new RongCloudResultDataObject();
resultObject.setCode(code);
resultObject.setMsg(msg);
return resultObject;
}
}
引入maven:
<dependency>
<groupId>cn.rongcloud.im</groupId>
<artifactId>server-sdk-java</artifactId>
<version>3.0.1</version>
</dependency>
四、傳送融雲系統訊息,單聊訊息(這裡主要是小灰條),封裝成工具類
public class CommonUtil {
/**你的key和secret*/
public static final String appKey = "";
public static final String appSecret = "";
//預設空頭像(使用者)
public static final String DEFAULT_IMAGE = "112.jpg";
private static RongCloud rongCloud = RongCloud.getInstance(appKey,appSecret);
/**
* 通過融雲傳送系統資訊,詳見https://www.rongcloud.cn/docs/message_architecture.html#group_notification_message
* @param senderId 傳送人
* @param targetIds 接收人(陣列)
* @param baseMessage 訊息內容
* @param pushContent 推送內容
* @param pushData 推送資料
*/
public static void sendSystemMessage(String senderId, String[] targetIds, BaseMessage baseMessage, String pushContent, String pushData){
SystemMessage systemMessage = new SystemMessage()
.setSenderId(senderId)
.setTargetId(targetIds)
.setObjectName(baseMessage.getType())
.setContent(baseMessage)
.setPushContent(pushContent)
.setPushData(pushData)
.setIsPersisted(0)
.setIsCounted(0)
.setContentAvailable(0);
try {
rongCloud.message.system.send(systemMessage);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 通過融雲傳送單聊訊息
*/
public static void sendPrivateMsg(String senderId, String targetId, BaseMessage baseMessage){
PrivateMessage privateMessage = new PrivateMessage()
.setSenderId(senderId)
.setTargetId(new String[]{targetId})
.setObjectName(baseMessage.getType())
.setContent(baseMessage)
.setPushContent("")
.setPushData("")
.setCount("")
.setVerifyBlacklist(0)
.setIsPersisted(0)
.setIsCounted(0)
.setIsIncludeSender(0);
//傳送單聊方法
try {
rongCloud.message.msgPrivate.send(privateMessage);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 移除黑名單
*/
public static void removeBlackList(String userId,String friendId){
UserModel user = getUserModel(userId,friendId);
try {
rongCloud.user.blackList.remove(user);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 新增黑名單
*/
public static void addBlackList(String userId,String friendId){
UserModel user = getUserModel(userId,friendId);
try {
rongCloud.user.blackList.add(user);
} catch (Exception e) {
e.printStackTrace();
}
}
private static UserModel getUserModel(String userId,String friendId){
UserModel blackUser = new UserModel().setId(userId);
UserModel[] blacklist = {blackUser};
UserModel user = new UserModel()
.setId(friendId)
.setBlacklist(blacklist);
return user;
}
}
五、/invite 發起好友請求:(其實主要就是 判斷 status 的值,再更改status的值 )
/**
* @param userId 請求者
* @param friendId 被請求者
* @param message 請求者發出的“驗證訊息”
* @param pushContent 推送
* @param pushData 推送內容
*/
@PostMapping("/invite")
public RongCloudResultDataObject invite(@RequestBody Map<String,Object> map){
if(map.get("userId") == null || map.get("friendId") == null){
return RongCloudResultUtil.error(1001,"userId,friendId不能為null");
}
String userId = map.get("userId").toString(); //當前使用者id
String friendId = map.get("friendId").toString(); //要新增的好友id
if(Objects.equals(userId, "") || Objects.equals(friendId, "")){
return RongCloudResultUtil.error(1001,"userId,friendId必需有值");
}
String message = map.get("message") == null ? "我是 "+ userId : map.get("message").toString();//新增好友的驗證資訊 的預設值
String pushContent = map.get("pushContent") == null ? "": map.get("pushContent").toString(); //推送
String pushData = map.get("pushData") == null ? "" : map.get("pushData").toString(); //推送內容
//該方法執行的sql語句是:select * from rongcloud_friendship where user_id = ?1 and friend_id = ?2
//資料庫有兩條記錄,檢視這兩個使用者之間的關係
//請求者
FriendShip fg = friendShipService.findByUserIdAndFriendId(userId, friendId);
//被請求者
FriendShip fd = friendShipService.findByUserIdAndFriendId(friendId,userId);
int fgStatus,fdStatus;
String action = "Added";
String resultMessage = "無需對方確認,已成功新增好友";
//獲得使用者的暱稱
User user = userService.findByAccount(userId);
String extra = "{sourceUserNickname:"+ user.getNickname() + ",version:123456}";
//資料庫沒有這兩條記錄,說明是第一次新增(後面刪掉好友的時候,僅僅是改變status的值)
if(fg != null && fd != null){
//status都為20表示已經是好友,無需再申請新增
if(fg.getStatus() == AGREED && fd.getStatus() == AGREED){
return RongCloudResultUtil.error(400, "你們已經是好友了");
}
if(fd.getStatus() == AGREED || fd.getStatus() == REQUESTING){
fgStatus = REQUESTING;
fdStatus = REQUESTED;
action = "Sent";
resultMessage = "請求已傳送";
}else if((fg.getStatus() == DELETED && fd.getStatus() == DELETED) || (fg.getStatus() == AGREED && fd.getStatus() == DELETED) || (fg.getStatus() == REQUESTING && fd.getStatus() == IGNORED) || (fg.getStatus() == REQUESTING && fd.getStatus() == REQUESTED)){
fgStatus = REQUESTING;
fdStatus = REQUESTED;
action = "Sent";
resultMessage = "請求已傳送";
}else{
return msg(200, "什麼都不做.","None");
}
//更新狀態
fg.setStatus(fgStatus);
fd.setStatus(fdStatus);
fd.setMessage(message);
fg.setUpdateTime(new Date());
fd.setUpdateTime(new Date());
//這裡執行的sql語句就是update語句
friendShipService.update(fg);
friendShipService.update(fd);
//通過融雲傳送系統訊息,提醒對方**請求新增您為好友
if(fd.getStatus() == REQUESTED){
sendContactMessage(CONTACT_OPERATION_REQUEST,userId,friendId,message,pushContent
,pushData,extra);
}
return RongCloudUtils.success(resultMessage,action);
}else{
//之前沒有加過好友
//更新請求者的 status為 requesting 10
saveFriendShip(userId,friendId, "", REQUESTING);
//更新被請求者的 status 為 requested 11
saveFriendShip(friendId,userId,message,REQUESTED);
sendContactMessage(CONTACT_OPERATION_REQUEST,userId,friendId,message,pushContent
,pushData,extra);
return msg(200, "請求已傳送","Sent");
}
}
}
private void sendContactMessage(String contact,String senderId,String targetId,String message,String pushContent,String pushData,String extra){
ContactNtfMessage contactNtfMessage = new ContactNtfMessage(contact,extra,senderId,targetId,message);
CommonUtil.sendSystemMessage(senderId,new String[]{targetId},contactNtfMessage,pushContent,pushData);
}
六、/agree 同意好友請求
主要在於小灰條,可檢視 融雲控制檯裡面的 API呼叫
/**
* 同意好友請求
* @param userId 同意新增 friendId為好友
*/
@PostMapping("/agree")
public RongCloudResultDataObject agree(@RequestBody Map<String,Object> map){
if(map.get("userId") == null || map.get("friendId") == null){
return RongCloudResultUtil.error(1001,"userId,friendId不能為null");
}
String userId = map.get("userId").toString(); //當前使用者id (被請求者)
String friendId = map.get("friendId").toString(); //請求者
if(Objects.equals(userId, "") || Objects.equals(friendId, "")){
return RongCloudResultUtil.error(1001,"userId,friendId必需有值");
}
//更新雙方的 status為 AGREE
//該方法執行的sql語句是:select * from rongcloud_friendship where user_id = ?1 and friend_id = ?2
FriendShip fg = friendShipService.findByUserIdAndFriendId(friendId,userId);
FriendShip fd = friendShipService.findByUserIdAndFriendId(userId,friendId);
if(fg.getStatus() != REQUESTING && fg.getStatus() != AGREED && fg.getStatus() != REQUESTED){
return RongCloudResultUtil.error(404,"無效的好友請求,或者未知好友");
}
friendShipService.updateStatus(userId,friendId,AGREED,new Date(),"");
friendShipService.updateStatus(friendId,userId,AGREED,new Date(),"");
//給請求者 發一條訊息說,我同意你的請求了
User user = userService.findByAccount(userId);
User friend = userService.findByAccount(friendId);
String extra = "{sourceUserNickname:"+ user.getNickname() + ",version:123456}";
sendContactMessage(CONTACT_OPERATION_ACCEPT_RESPONSE,userId,friendId,"我是"+userId+",我已經同意你的好友請求了","","",extra);
//小灰條通知
CommonUtil.sendPrivateMsg(userId,friendId,new InformationNtfMessage("你已添加了"+ friend.getNickname() +",現在可以開始聊天了。",""));
//傳送文字訊息
CommonUtil.sendPrivateMsg(userId,friendId,new TxtMessage("我通過了你的朋友驗證請求,現在我們可以開始聊天了",""));
CommonUtil.sendPrivateMsg(friendId,userId,new TxtMessage(fd.getMessage(),""));
//移除黑名單
CommonUtil.removeBlackList(userId,friendId);
CommonUtil.removeBlackList(friendId,userId);
return RongCloudResultUtil.success();
}
例如: 【十月】請求新增【實話實說】為好友,傳送的驗證請求內容是“我是十月,通過下”。
【實話實說】同意請求。 此時,【十月】會給【實話實說】發一條 TxtMsg文字訊息 (傳送的內容就是 它請求的驗證訊息)
【實話實說】也會發一條訊息給【十月】來通知對方我同意了請求(這裡有小灰條)
七、/delete 刪除好友
注意 只需要 將一方的 status 改為 30 就可以了,並且需要加入融雲提供的黑名單,兩人才不能通訊(不然只要聊天介面還在,兩人還是可以聊天的)!
/**
* 邏輯刪除(修改status為30)
* @param map
* @return
*/
@PostMapping("/delete")
public RongCloudResultDataObject delete(@RequestBody Map<String,Object> map){
if(map.get("userId") == null || map.get("friendId") == null){
return RongCloudResultUtil.error(1001,"userId,friendId欄位是必需的");
}
String userId = map.get("userId").toString(); //當前id
String friendId = map.get("friendId").toString(); //好友id
if(Objects.equals(userId, "") || Objects.equals(friendId, "")){
return RongCloudResultUtil.error(1001,"userId,friendId必需有值");
}
FriendShip fg = friendShipService.findByUserIdAndFriendId(userId,friendId);
if(fg == null || fg.getStatus() != AGREED){
return RongCloudResultUtil.error(405,"你們不是好友關係,不能執行相關操作");
}
//把好友備註給清空下
fg.setDisplayName("");
fg.setMessage("");
fg.setStatus(DELETED);
fg.setUpdateTime(new Date());
friendShipService.update(fg);
//新增到黑名單
CommonUtil.addBlackList(userId,friendId);
CommonUtil.addBlackList(friendId,userId);
return RongCloudResultUtil.success();
}
其它方法不貼了,主要的難點在於,傳送融雲提供的系統訊息,通知對方我要加你為好友了,以及小灰條~