谈谈微信小程序中首次对接融云WebIM SDK经验

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/likun_li/article/details/89331080

多读多写多记录,多学多练多思考。----------- Banana.Banuit Gang(香柚帮)


  最近在做一个项目,其中需要实现一个咨询的即时通信功能,于是就使用了融云WebIM SDK来实现这个功能,融云那边有一整套demo,可以直接拿来用,也很容易上手,拿来修修改改几乎就能实现简单的文字消息和图片等等,不过这特么感觉有点贵。

首先来说一下项目的流程思路:

  1. 我的项目小程序下方的Tab切换主要有三个菜单【首页】、【咨询】(展示和自己相关的会话列表)、【我的】。
  2. 用户进入【我的】点击授权登录后,在这一步可以把自己的一些相关信息存到数据库,比如融云token,小程序openid,开放平台unionid等
  3. 用户在首页的咨询模块可以提交一个表单来说明自己想要咨询的问题。提交之后进入到自己咨询问题的详情页,这时候显示的是待处理
  4. 当管理员进入小程序的待处理问题里边,找到刚刚用户提交的问题,点击确认受理,这时,这个用户和这个管理员建立起了关联(融云也有说,好友关系由自己维护),这个时候用户进入问题详情页变成待处理变成联系管理员,而管理员进入后确认受理变成联系用户,这时他们就可以点击按钮进行首次交流了,交流之后这个会话就会显示在双方的咨询里边。
  5. 接下来就是直接利用融云小程序的demo,显示会话列表,可以通过会话列表再次进行聊天(这里需要注意,融云文档中有说,只有进行了一次消息会话之后,才会在会话列表中显示这个会话,而融云demo是直接给我们了一个会话列表,可以直接进行聊天,并没有给出首次聊天的逻辑,所以首次进入聊天窗口,由我们根据自己的项目具体解决,比如第4步)

下边是融云小程序的项目文件里列表和目录说明,写的也很清楚。

把这些pages下边的文件整体拉到自己项目的pages目录下,把config.js复制到根目录下,然后在我们的app.js 中添加如下两项

//app.js最顶部
const Config = require('./config.js');//引入融云IMSDK配置
const Service = require('./pages/services.js')(Config);//引入service层,主要负责数据交换,收发消息
//app.js
globalData: {
    Service: Service
}

其他几个文件app.json,把"pages/conversation/list",放在第一个,首先测试一下植入到自己项目中的demo是否能走通,如果走通了,接下来就可以把config.js中的appkey换成我们自己的进行开发测试了。

我的问题详情页的代码display_info.js,进入这个页面后连接融云服务器

//display_info.js
const utils = require('../utils/utils.js');//融云辅助工具js
const { UserList, GroupList, MusicList } = require('../mock.js');//假数据
const RongIMLib = require('../lib/RongIMLib.miniprogram-1.0.8.js');//引入融云IMSDK
const RongIMClient = RongIMLib.RongIMClient;//实例化


const { globalData } = getApp();
const { Service: { Status, Conversation } } = globalData;//定义Status,Conversation
//请求用户验证,判断是否授权
const requestUserAuth = () => {
  return new Promise((resolve, reject) => {
    wx.getSetting({
      success: function (res) {
        resolve(!!res.authSetting['scope.userInfo'])
      },
      fail: function (error) {
        console.log(error);
        reject(error)
      }
    })
  });
};
//检查状态
const watchStatus = () => {
  Status.watch((status) => {
    if (status == 3) {
      wx.getUserInfo({
        success: (user) => {
          Status.connect(user.userInfo);
        }
      });
    }
  })
}
//连接融云服务器
const connect = (context) => {
  //watchConversation(context);
  watchStatus();
  wx.getUserInfo({
    success: (user) => {
      Status.connect(user.userInfo).then(() => {//此处会去services.js找相应的方法
        console.log('connect successfully ' + user.userInfo.nickName);
      }, (error) => {
        wx.showToast({
          title: error.msg,
          icon: 'none',
          duration: 3000
        })
      })
    },
    fail: (error) => {
      console.log(error);
      wx.showToast({
        title: '换个网络试试,只能帮你到这了~',
        icon: 'none',
        duration: 3000
      })
    }
  })
};
//通过接收人id去mock.js的UserList中获取到该接收人名字和头像
let getUserById = (id) => {
  let { name, avatar } = utils.find(UserList, (user) => {
    return (id == user.id);
  });
  return {
    name,
    avatar
  };
};

Page({
  data: {
    hasUserAuth: true//是否授权
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function(options) {
      //一进入次详情页就连接融云服务器,从list.js中复制
    //融云用户验证并连接融云服务器
    requestUserAuth().then((hasUserAuth) => {
      this.setData({
        hasUserAuth
      });
      if (hasUserAuth) {
        connect(this);//如果已经授权就开始连接
      }
    });
  },
  //从list.js中复制修改
  gotoChat: function () {
    
    var type = 1;
    var targetId = 1;
    console.log(targetId)
    var target = getUserById(targetId);

    let url = '../conversation/chat?type={type}&targetId={targetId}&title={title}';
    url = utils.tplEngine(url, {
      type,
      targetId,
      title:target.name
    });
    wx.navigateTo({
      url: url,
    });

   

  },
  
  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function() {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function() {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function() {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function() {

  }
})

下边说说mock.js假数据

/*
 * 开发者后台: https://developer.rongcloud.cn
 * 集成开发获取 Token: 请前往开发者后台 -> 应用 -> API 调试 -> 点击 `获取 Token` -> 输入对应信息得到用户 Token
 * 生产应用获取 Token: 在开发者自己的应用服务器通过融云 Server SDK 获取用户 Token,并缓存在应用服务器
 * Server SDK: http://www.rongcloud.cn/docs/server_sdk_api/index.html
*/

module.exports = {
  UserList: [
    {
      "name": "用户1",
      "type": 1,
      "token": "24iKWfmwZW7k6sg8KGMcGQx9HvrbHrVQ4rpKxO5Sn4hdQ17mXuw+dYZC1vJ6YDTQqpMqlWInhNVid7IrE7f5lg==",
      "id": "4",
      "avatar": 'https://rongcloud-image.cn.ronghub.com/o_1chv06qgdmlil2p1fsjoud2p2j.png?e=2147483647&token=livk5rb3__JZjCtEiMxXpQ8QscLxbNLehwhHySnX:OwYp2XRN_rODjcj_-3tCTmHj31I='
    },
{
      "name": "用户2",
      "type": 1,
      "token": "24iKWfmwZW7k6sg8KGMcGQx9HvrbHrVQ4rpKxO5Sn4hdQ17mXuw+dYZC1vJ6YDTQqpMqlWInhNVid7IrE7f5lg==",
      "id": "3",
      "avatar": 'https://rongcloud-image.cn.ronghub.com/o_1chv06qgdmlil2p1fsjoud2p2j.png?e=2147483647&token=livk5rb3__JZjCtEiMxXpQ8QscLxbNLehwhHySnX:OwYp2XRN_rODjcj_-3tCTmHj31I='
    },
    {
      "name": "管理员",
      "type": 1,
      "token": "OftOMqgj2MZPpeVRzohJaJ/SPh0aROIrpMTJZ4Hw3ISsmqDrj1RlGWrxWnq3urbZuepbCh5J3pQ=",
      "id": "5",
      "avatar": 'https://rongcloud-image.cn.ronghub.com/o_1chv06qgdmlil2p1fsjoud2p2j.png?e=2147483647&token=livk5rb3__JZjCtEiMxXpQ8QscLxbNLehwhHySnX:OwYp2XRN_rODjcj_-3tCTmHj31I='
    }
    ]
}

你到时候可以根据自己的好友关系,动态的改变这个列表,这个用户列表的最后一项取的是当前用户的信息,在你连接融云服务器的时候他会去找这个列表里边的最后一项,作为当前登录用户,所以这个用户列表不仅仅要列出来你的好友信息,还要把你的信息也插入到最后一项,方法是在services.js

//services.js
//获取用户
let getUser = (user) => {
  user = utils.rename(user, {avatarUrl: 'avatar', nickName: 'name'});
  let maxIndex = UserList.length - 1;
  let index = getUserIndex(user.name,  maxIndex);
  let _user = UserList[index];
  // utils.extend(_user, user);
  return _user
};
//获取当前用户token
User.getToken = (user) => {
  currentUser = getUser(user);
  return Promise.resolve(currentUser);
};
Status.connect = (user) => {
  console.log(user);
  RongIMClient.setConnectionStatusListener({
    onChanged: (status) => {
      Status.watcher.notify(status);
    }
  });

  let receiveMessage = (message) => {
    console.log(message);
      let {messageType} = message;
      let messageCtrol = {
        otherMessage: () => {
          Message._push(message);
        }
      };
      let messageHandler = messageCtrol[messageType] || messageCtrol.otherMessage;
      messageHandler();
  };
  RongIMClient.setOnReceiveMessageListener({
    onReceived: receiveMessage
  });

  return User.getToken(user).then((user) => {
    return new Promise((resolve, reject) => {
      RongIMClient.connect(user.token, {
        onSuccess: (userId) => {
          console.log(user);
          console.log(userId);
          resolve(userId);//解析
        },
        onTokenIncorrect: () => {
          var msg = ErrorInfo[RongIMLib.ConnectionState.TOKEN_INCORRECT];
          reject(msg);
        },
        onError: (error) => {
          console.log('eeeeaaaa', error);
          var msg = ErrorInfo[RongIMLib.ConnectionState.TOKEN_INCORRECT] || {
            code: error,
            msg: error
          };
          reject(msg);
        }
      });
    });
  });
};

做完之后就像这样

下边附上获取融云token的代码

/**
	 * 获取融云token
	 * 方法名:getToken
	 * @param userId:司机 Id, userName:司机车牌号, portraitUri: 头像空值
	 * @return {"code":200, "userId":"jlk456j5", "token":"sfd9823ihufi"}
	 */
	function getToken( $userId, $userName, $portraitUri = '') {

		// 请求url
		$url = 'https://api.cn.rong.io/user/getToken.json';

		$postData = 'userId='.$userId.'&name='.$userName.'&portraitUri='.$portraitUri;

		// post提交-推送
		$row = json_decode($this->request_post_push($url, $postData),true);

		if($row['code'] == '200' ){ // 返回码200 为正常
			return $row['token'];
		}else{
			return '';
		}
	}

	/**
	 * curl-提交推送
	 * @param url:请求地址, postData:请求参数
	 */
	function request_post_push($url = "", $postData = "") {

		// 参数为空返回状态
		if (empty($url) || empty($postData)) {
			return false;
		}

		//参数初始化
		$appKey = 'xxxxxxxx';
		$appSecret = 'xxxxxxxxx';

		$nonce = mt_rand(); // 获取随机数。

		$timeStamp = time();// 获取时间戳。

		$signature = sha1($appSecret.$nonce.$timeStamp);

		$httpHeader = array(

			'App-Key:'.$appKey, //	平台分配

			'Nonce:'.$nonce, //	随机数

			'Timestamp:'.$timeStamp, //	时间戳

			'Signature:'.$signature, //	签名

			'Content-Type: application/x-www-form-urlencoded',

		);

		// 初始化curl
		$ch = curl_init();
		// 设置你需要抓取的URL
		curl_setopt($ch, CURLOPT_URL, $url);
		// post提交方式
		curl_setopt($ch, CURLOPT_POST, 1);

		curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
		// 设置cURL 参数,要求结果保存到字符串中还是输出到屏幕上。
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		// 设置header
		curl_setopt($ch, CURLOPT_HEADER, false);
		// 增加 HTTP Header(头)里的字段
		curl_setopt($ch, CURLOPT_HTTPHEADER, $httpHeader);

		curl_setopt($ch, CURLOPT_TIMEOUT, 30);
		// 终止从服务端进行验证
		curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,false);
		// 运行curl
		$data = curl_exec($ch);
		// 关闭URL请求
		curl_close($ch);

		return $data ;
	}

猜你喜欢

转载自blog.csdn.net/likun_li/article/details/89331080