?请先配置appKey和appSecret? ? ?本demo实现了服务端和web的联调(系统通知)
服务端参考文档:开发者中心
WEB参考文档:开发者中心
目录
?1.公共类 Common.php
2. ?Nim.php?需要继承Common
3.?HTML 测试demo页面? js文件请在官方网站自行下载
?1.公共类 Common.php
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2022/1/25
* Time: 14:11
*/
namespace app\nim\controller;
use \think\Controller;
class Common extends Controller{
public $appKey="";//开发者平台分配的 appkey
public $appSecret="";//开发者平台分配的 appSecret
public $accid;//IM 账号
public $nim_name;//redis键名
public $input;
public $nonce;//随机数(最大长度128个字符)
public $checkSum;//SHA1(AppSecret + Nonce + CurTime),三个参数拼接的字符串,进行SHA1哈希计算,转化成16进制字符(String,小写)
public $time;//当前时间戳
public function _initialize()
{
if (session_status() === PHP_SESSION_NONE) {
session_start();
}
$this->input=input('');
$this->accid=session_id();
$this->nim_name='nim_token_'.$this->accid;
$this->nonce=$this->rand_code(16);
$this->time=time();
$this->checkSum=$this->nim_hearder_init($this->time,$this->nonce);
}
/**
* Notes:生成 checkSum 请求头初始化
* User: ZHOU WEI YUN
* Date: 2022/1/24 0024
* Time: 下午 2:04
* @param $curtime int 当前UTC时间戳
* @param $nonce string 随机数(最大长度128个字符)
* @return string
*/
public function nim_hearder_init($curtime,$nonce){
$appSecret=$this->appSecret;
return strtolower(sha1($appSecret.$nonce.$curtime,false));
}
/* 随机字符串
* $strlen 随机数长度
*/
public function rand_code($strlen=4){
$result='';
$str='abcdefghijklmnopqrstuvwxyz0123456789';//ABCDEFGHIJKLMNOPQRSTUVWXYZ
for($i=0;$i<$strlen;$i++){
$result.=$str[random_int(0,strlen($str)-$i)];
}
return $result;
}
public function post_url($url,$urlencodedStr)
{
$arr=[
'Content-type:application/x-www-form-urlencoded',
'AppKey:'. $this->appKey,
'Nonce:'. $this->nonce,
'CurTime:'. $this->time,
'CheckSum:'. $this->checkSum,
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($urlencodedStr));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);//去掉https验证
curl_setopt($ch, CURLOPT_HTTPHEADER, $arr);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
}
2. ?Nim.php?需要继承Common
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2022/1/25
* Time: 14:10
*/
namespace app\nim\controller;
class Nim extends Common
{
//https://doc.yunxin.163.com/docs/TM5MzM5Njk/DEwMTE3NzQ?platformId=60353 文档
//产生网易云通信ID
public function create_accid()
{
$return=[
'code'=>400,
'msg'=>'请求失败',
'data'=>[
'appkey'=>$this->appKey,
'token'=>'',
'account'=>$this->accid
],
];
$redis=get_redis();
if(!$redis){
return $return['msg']='redis连接失败';
}
$token=$redis->get($this->nim_name);
if(empty($token)){
$url = "https://api.netease.im/nimserver/user/create.action";//获取
$urlencodedStr_arr=array();
$urlencodedStr_arr['accid']=$this->accid;//自定义(传入即可)
$re=json_decode($this->post_url($url,$urlencodedStr_arr),true);
if($re['code']===200){
$return['msg']='请求成功';
$return['code']=200;
$return['data']['token']=$re['info']['token'];
$redis->set($this->nim_name,$re['info']['token'],600);
}else{
return $this->refresh_token();//重置token
}
}else{
$return['msg']='请求成功';
$return['code']=200;
$return['data']['token']=$token;
}
return $return;
}
/**
* Notes:主动更新 token
* User: ZHOU WEI YUN
* Date: 2022/1/24 0024
* Time: 下午 3:43
* @param array
* @return array|string
*/
public function refresh_token()
{
$return=[
'code'=>400,
'msg'=>'请求失败',
'data'=>[
'appkey'=>$this->appKey,
'token'=>'',
'account'=>$this->accid
],
];
$redis=get_redis();
if(!$redis){
return $return['msg']='redis连接失败';
}
$token=$redis->get($this->nim_name);
if(empty($token)){
$url='https://api.netease.im/nimserver/user/refreshToken.action';//重置IMtoken
$urlencodedStr_arr=array();
$urlencodedStr_arr['accid']=$this->accid;//自定义(传入即可)
$re=json_decode($this->post_url($url,$urlencodedStr_arr),true);
if($re['code']===200){
$return['msg']='请求成功';
$return['code']=200;
$return['data']['token']=$re['info']['token'];
$redis->set($this->nim_name,$re['info']['token'],6000);
}
}else{
$return['msg']='请求成功';
$return['code']=200;
$return['data']['token']=$token;
}
return $return;
}
/**
* Notes:测试页面
* User: ZHOU WEI YUN
* Date: 2022/1/25 0025
* Time: 下午 2:54
* @param array
* @return array
* @return mixed
*/
public function test_nim()
{
$data=$this->create_accid();
$this->assign('info',$data);
return $this->fetch();
}
/**
* Notes:发送消息 需要先加好友
* User: ZHOU WEI YUN
* Date: 2022/1/24 0024
* Time: 下午 3:56
* @param array
* @return bool|void
*/
public function nim_send_msg()
{
$url='https://api.netease.im/nimserver/msg/sendMsg.action';
$body='{"msg":"hello"}';//JSON格式
$urlencodedStr_arr=[
'from'=>$this->input['account']??'',// 发送者accid,用户帐号,最大32字符,必须保证一个APP内唯一
'ope'=>0,//0:点对点个人消息,1:群消息(高级群),其他返回414
'to'=>$this->input['to']??'',//ope==0是表示accid即用户id,ope==1表示tid即群id
'type'=>0,//0 表示文本消息,
'body'=>$body,//最大长度5000字符,JSON格式。
];
return json_decode($this->post_url($url,$urlencodedStr_arr),true);
}
/**
* Notes:发送自定义系统通知
* User: ZHOU WEI YUN
* Date: 2022/1/25 0025
* Time: 上午 10:22
* @param array
* @return array
*/
public function nim_send_attachmsg()
{
$url='https://api.netease.im/nimserver/msg/sendAttachMsg.action';
$body='{"myattach":"test"}';//JSON格式
$urlencodedStr_arr=[
'from'=>$this->input['account']??'',//发送者accid,用户帐号,最大32字符,APP内唯一
//'ope'=>0,//0:点对点个人消息,1:群消息(高级群),其他返回414
'to'=>$this->input['to']??'',//msgtype==0是表示accid即用户id,msgtype==1表示tid即群id
'msgtype'=>0,//0:点对点自定义通知,1:群消息自定义通知,其他返回414
'attach'=>$body,//自定义通知内容,第三方组装的字符串,建议是JSON串,最大长度4096字符
];
return json_decode($this->post_url($url,$urlencodedStr_arr),true);
}
/**
* Notes:批量发送点对点自定义系统通知
* User: ZHOU WEI YUN
* Date: 2022/1/25 0025
* Time: 上午 11:29
* @param array
* @return array|mixed|object
*/
public function nim_send_batch_attachmsg()
{
$url='https://api.netease.im/nimserver/msg/sendBatchAttachMsg.action';
$body='{"myattach":"test"}';//JSON格式
$toAccids=["utcoh9motcrrp1ivd7ba89b894",'ida8ichlrtfdpbljfim2dfjdpa'];//,"bm7m1veull2aul13b3uapsr22p"
$urlencodedStr_arr=[
'fromAccid'=>$this->input['account']??'',//发送者accid,用户帐号,最大32字符,APP内唯一
'toAccids'=>json_encode($toAccids),//["aaa","bbb"](JSONArray对应的accid,如果解析出错,会报414错误),最大限500人
'attach'=>$body,//自定义通知内容,第三方组装的字符串,建议是JSON串,最大长度4096字符
];
return json_decode($this->post_url($url,$urlencodedStr_arr),true);
}
/***
* Notes:广播消息 需要申请开通才能使用
* User: ZHOU WEI YUN
* Date: 2022/1/25 0025
* Time: 下午 2:23
* @param array
* @return array|mixed|object
*/
public function nim_broadcast_msg_action()
{
$url='https://api.netease.im/nimserver/msg/broadcastMsg.action';
$urlencodedStr_arr=[
'from'=>$this->input['account']??'',//发送者accid, 用户帐号,最大长度32字符,必须保证一个APP内唯一
'body'=>'test',//广播消息内容,最大4096字符
'isOffline'=>'true',//是否存离线,true或false,默认false
'ttl'=>'',//存离线状态下的有效期,单位小时,默认7天
'targetOs'=>json_encode(["ios","pc","web"]),//目标客户端,默认所有客户端,jsonArray,格式:["ios","aos","pc","web","mac"]
];
return json_decode($this->post_url($url,$urlencodedStr_arr),true);
}
}
3.?HTML 测试demo页面? js文件请在官方网站自行下载
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>IM测试</title>
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
</head>
<body>
<div class="layui-inline">
<input type="type" name="account" value="{$info['data']['account']}"/>
<input type="type" name="to" value=""/>
<input type="submit" name="tj" value="发送" onclick="sed_msg()"/>
</div>
</div>
<script src="/static/admin/js/jquery.js"></script>
<script src="/static/nim/js/NIM_Web_NIM_v8.11.2.js"></script>
<!-- 注意:如果你直接复制所有代码到本地,上述js路径需要改成你本地的 -->
<script>
// 注意这里, 当引入的SDK文件是NIM_Web_NIM_v.js时,请通过 NIM.getInstance 来初始化;
var data = {};
var nim = NIM.getInstance({
debug: true, // 是否开启日志,将其打印到console。集成开发阶段建议打开。
appKey: "{$info['data']['appkey']}",
account: "{$info['data']['account']}",//网易云信 IM 账号,最大长度 32 字符
token: "{$info['data']['token']}",//您可以指定 accid 对应的 IM token 值,最大长度 128 字符,
db:false, //若不要开启数据库请设置false。SDK默认为true。
// privateConf: {}, // 私有化部署方案所需的配置
onconnect: onConnect,
onwillreconnect: onWillReconnect,
ondisconnect: onDisconnect,
onerror: onError,
onofflinesysmsgs: onOfflineSysMsgs,//消息接收 监听
onsysmsg: onSysMsg,
onupdatesysmsg: onUpdateSysMsg,
onsysmsgunread: onSysMsgUnread,
onupdatesysmsgunread: onUpdateSysMsgUnread,
onofflinecustomsysmsgs: onOfflineCustomSysMsgs,
oncustomsysmsg: onCustomSysMsg,
syncBroadcastMsgs: true, // 是否同步离线广播消息,默认false
onbroadcastmsg: onBroadcastMsg, // 收到广播消息的回调
onbroadcastmsgs: onBroadcastMsgs, // 登录后同步到离线广播消息的回调
});
function onConnect() {
console.log('连接成功');
}
function onWillReconnect(obj) {
// 此时说明 SDK 已经断开连接, 请开发者在界面上提示用户连接已断开, 而且正在重新建立连接
console.log('即将重连');
console.log(obj.retryCount);
console.log(obj.duration);
}
function onDisconnect(error) {
// 此时说明 SDK 处于断开状态, 开发者此时应该根据错误码提示相应的错误信息, 并且跳转到登录页面
console.log('丢失连接');
console.log(error);
if (error) {
switch (error.code) {
// 账号或者密码错误, 请跳转到登录页面并提示错误
case 302:
break;
// 重复登录, 已经在其它端登录了, 请跳转到登录页面并提示错误
case 417:
break;
// 被踢, 请提示错误后跳转到登录页面
case 'kicked':
break;
default:
break;
}
}
}
function onError(error) {
console.log(error);
}
//系统消息接收 监听
function onOfflineSysMsgs(sysMsgs) {
console.log('收到离线系统通知', sysMsgs);
pushSysMsgs(sysMsgs);
}
function onSysMsg(sysMsg) {
console.log('收到系统通知', sysMsg)
pushSysMsgs(sysMsg);
}
function onUpdateSysMsg(sysMsg) {
pushSysMsgs(sysMsg);
}
function pushSysMsgs(sysMsgs) {
data.sysMsgs = nim.mergeSysMsgs(data.sysMsgs, sysMsgs);
refreshSysMsgsUI();
}
function onSysMsgUnread(obj) {
console.log('收到系统通知未读数', obj);
data.sysMsgUnread = obj;
refreshSysMsgsUI();
}
function onUpdateSysMsgUnread(obj) {
console.log('系统通知未读数更新了', obj);
data.sysMsgUnread = obj;
refreshSysMsgsUI();
}
function refreshSysMsgsUI() {
// 刷新界面
}
function onOfflineCustomSysMsgs(sysMsgs) {
console.log('收到离线自定义系统通知', sysMsgs);
}
function onCustomSysMsg(sysMsg) {
console.log('收到自定义系统通知', sysMsg);
}
function onBroadcastMsg(msg) {
console.log('收到广播消息', msg);
}
function onBroadcastMsgs(msgs) {
console.log('收到广播消息', msgs);
}
//发送消息 发送人/接收人:不能为空
function sed_msg(){
let account=$('input[name="account"]').val();
let to=$('input[name="to"]').val();
if(account && to){
$.ajax({
type:'post',
url:"{:url('nim/nim/nim_send_batch_attachmsg')}",
data:{'account':account,'to':to},
success:function(info){
console.log(info);
}
});
}
}
</script>
</body>
</html>
|