Push.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2016~2020 https://www.crmeb.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  8. // +----------------------------------------------------------------------
  9. // | Author: CRMEB Team <admin@crmeb.com>
  10. // +----------------------------------------------------------------------
  11. namespace app\push\controller;
  12. use app\admin\model\system\SystemGroupData;
  13. use app\wap\model\live\LiveGift;
  14. use app\wap\model\live\LiveReward;
  15. use app\wap\model\live\LiveStudio;
  16. use app\wap\model\live\LiveUser;
  17. use app\wap\model\user\UserBill;
  18. use GatewayWorker\Lib\Gateway;
  19. use app\wap\model\live\LiveHonouredGuest;
  20. use app\wap\model\user\User;
  21. use app\wap\model\live\LiveBarrage;
  22. use service\SystemConfigService;
  23. use think\Log;
  24. class Push
  25. {
  26. /**
  27. * @var array 消息内容
  28. * */
  29. protected $message_data = [
  30. 'type' => '',
  31. 'message' => '',
  32. ];
  33. /**
  34. * @var string 消息类型
  35. * */
  36. protected $message_type = '';
  37. /**
  38. * @var string $client_id
  39. * */
  40. protected $client_id = '';
  41. /**
  42. * @var int 当前登陆用户
  43. * */
  44. protected $uid = null;
  45. /**
  46. * @var null 本类实例化结果
  47. * */
  48. protected static $instance = null;
  49. /**
  50. *
  51. * */
  52. protected function __construct($message_data = [])
  53. {
  54. }
  55. /**
  56. * 实例化本类
  57. * */
  58. public static function instance()
  59. {
  60. if (is_null(self::$instance)) self::$instance = new static();
  61. return self::$instance;
  62. }
  63. /**
  64. * 检测参数并返回
  65. * @param array || string $keyValue 需要提取的键值
  66. * @param null || bool $value
  67. * @return array;
  68. * */
  69. protected function checkValue($keyValue = null, $value = null)
  70. {
  71. if (is_null($keyValue))
  72. $message_data = $this->message_data;
  73. if (is_string($keyValue))
  74. $message_data = isset($this->message_data[$keyValue]) ? $this->message_data[$keyValue] : (is_null($value) ? '' : $value);
  75. if (is_array($keyValue))
  76. $message_data = array_merge($keyValue, $this->message_data);
  77. if (is_bool($value) && $value === true && is_array($message_data) && is_array($keyValue)) {
  78. $newData = [];
  79. foreach ($keyValue as $key => $item) {
  80. $newData [] = $message_data[$key];
  81. }
  82. return $newData;
  83. }
  84. return $message_data;
  85. }
  86. /**
  87. * 开始设置回调
  88. * @param string $typeFnName 回调函数名
  89. * @param string $client_id
  90. * @param array $message_data
  91. *
  92. * */
  93. public function start($typeFnName, $client_id, $message_data)
  94. {
  95. $this->message_type = $typeFnName;
  96. $this->message_data = $message_data;
  97. $this->client_id = $client_id;
  98. $uid=$this->checkValue('uid');
  99. if($uid){
  100. Gateway::bindUid($client_id, $uid);
  101. }
  102. $this->uid = Gateway::getUidByClientId($client_id);
  103. //记录用户上线
  104. if ($this->uid && Gateway::isOnline($client_id) && ($live_id = $this->checkValue('room'))) {
  105. LiveUser::setLiveUserOnline($live_id, $this->uid, 1);
  106. $error['uid'] = $this->uid;
  107. $error['is_line'] = Gateway::isOnline($client_id);
  108. $error['live_id'] = $this->checkValue('room');
  109. }else{
  110. $error['uid'] = $this->uid;
  111. $error['is_line'] = Gateway::isOnline($client_id);
  112. $error['live_id'] = $this->checkValue('room');
  113. Log::write(json_encode($error));
  114. }
  115. if (method_exists($this, $typeFnName)){
  116. call_user_func([$this, $typeFnName]);
  117. }else{
  118. throw new \Exception('缺少回调方法');
  119. }
  120. }
  121. /**
  122. * 心跳检测
  123. *
  124. * */
  125. protected function ping()
  126. {
  127. Gateway::sendToClient($this->client_id, json_encode(['ping' => 'ok']));
  128. }
  129. /**
  130. * 绑定用户相应客户端
  131. * @param string $client_id
  132. * @param array $message_data
  133. * @return
  134. * */
  135. protected function handshake()
  136. {
  137. $message_data = $this->checkValue(['uid' => 0, 'room' => 0]);
  138. if (!$message_data['uid']){
  139. Gateway::closeClient($this->client_id);
  140. throw new \Exception("缺少用户uid,无法绑定用户");
  141. }
  142. $new_message = [
  143. 'type' => $this->message_type,
  144. 'uid' => $message_data['uid'],
  145. 'room' => $message_data['room'],
  146. 'client_id' => $this->client_id,
  147. 'time' => date('H:i:s'),
  148. 'msg' => '绑定成功!'
  149. ];
  150. Log::write(json_encode($new_message));
  151. Gateway::bindUid($this->client_id, $message_data['uid']);
  152. //如果有群组id加入群组
  153. if ($message_data['room']) {
  154. // 加入某个群组(可调用多次加入多个群组) 将clientid加入roomid分组中
  155. Gateway::joinGroup($this->client_id, $message_data['room']);
  156. Gateway::sendToGroup($message_data['room'], json_encode([
  157. 'type' => 'join_Group',
  158. ]));
  159. }
  160. Gateway::sendToClient($this->client_id, json_encode($new_message));
  161. }
  162. /**
  163. * 接受客户端发送的消息
  164. * @param string $client_id 客户端client_id
  165. * @param array $message_data 发送的数据
  166. * @return
  167. *
  168. * */
  169. protected function send()
  170. {
  171. list($toUid, $message, $room, $type) = $this->checkValue(['uid' => 0, 'content' => '', 'room' => false, 'ms_type' => 0], true);
  172. $client_id = $this->client_id;
  173. if (!$this->uid) {
  174. //认证用户信息失败,关闭用户链接
  175. Gateway::closeClient($client_id);
  176. throw new \Exception("缺少用户uid");
  177. }
  178. $userInfo = User::get($this->uid);
  179. if (!$userInfo) {
  180. //认证用户信息失败,关闭用户链接
  181. Gateway::closeClient($client_id);
  182. throw new \Exception("用户信息缺少");
  183. }
  184. if ($room && Gateway::getClientIdCountByGroup($room)) {
  185. $user_type = LiveHonouredGuest::where(['uid' => $this->uid, 'live_id' => $room])->value('type');
  186. if (is_null($user_type)) $user_type = 2;
  187. $res = LiveBarrage::set([
  188. 'live_id' => $room,
  189. 'uid' => $this->uid,
  190. 'type' => $type,
  191. 'barrage' => $message,
  192. 'add_time' => time(),
  193. 'is_show' => 1
  194. ]);
  195. if (!$res) throw new \Exception("写入历史记录失败");
  196. Gateway::sendToGroup($room, json_encode([
  197. 'message' => $message,
  198. 'm_type' => $type,
  199. 'type' => 'message',
  200. 'user_type' => $user_type,
  201. 'userInfo' => $userInfo,
  202. 'id' => $res['id']
  203. ]));
  204. } else {
  205. $new_message = [
  206. 'type' => 'reception',
  207. 'content' => $message,
  208. 'time' => date('H:i:s'),
  209. 'timestamp' => time(),
  210. ];
  211. if (Gateway::isUidOnline($toUid)) return Gateway::sendToUid($toUid, json_encode($new_message));
  212. }
  213. }
  214. /**
  215. * 消息撤回
  216. * @param string $client_id
  217. * @param array $message_data
  218. * */
  219. protected function recall()
  220. {
  221. list($id, $room) = $this->checkValue(['id' => 0, 'room' => ''], true);
  222. if (!$id) throw new \Exception('缺少撤回消息的id');
  223. if (!$room) throw new \Exception('缺少房间号');
  224. if (LiveBarrage::del($id)) {
  225. Gateway::sendToGroup($room, json_encode([
  226. 'type' => 'recall',
  227. 'id' => $id
  228. ]), Gateway::getClientIdByUid($this->uid));
  229. }
  230. }
  231. /**更新直播间人数
  232. * @throws \think\Exception
  233. */
  234. protected function room_user_count(){
  235. list($room, $uid) = $this->checkValue(['room' => '', 'uid' => 0], true);
  236. $onLine_user_count = LiveUser::where(['is_open_ben' => 0, 'live_id' => $room, 'is_online' => 1])->count();
  237. $onLine_num = LiveStudio::where(['id' => $room])->value('online_num');
  238. $user_type = 3;
  239. if (!$uid || $uid == 0) {
  240. Gateway::closeClient( $this->client_id);
  241. $notice_content = "<span style='color: darkred'>欢迎新朋友进入直播间</span>";
  242. }else{
  243. $user_type = LiveHonouredGuest::where(['uid' => $uid, 'live_id' => $room])->field('type')->find();
  244. $user_type = (isset($user_type['type']) && $user_type) ? $user_type['type'] : 3;
  245. $user_info = User::where(['uid' => $uid])->field('uid, account, nickname, phone, avatar')->find();
  246. $user_name = $user_info['nickname'] ? $user_info['nickname'] : ($user_info['account'] ? $user_info['account'] : "新游客");
  247. $notice_content = $user_name. " 来了";
  248. }
  249. Gateway::sendToGroup($room, json_encode(['onLine_user_count' => $onLine_user_count + $onLine_num, 'type' => 'room_user_count', 'notice_content' => $notice_content, 'user_type' => $user_type]));
  250. }
  251. /**打赏接口
  252. * @throws \think\Exception
  253. * @throws \think\db\exception\DataNotFoundException
  254. * @throws \think\db\exception\ModelNotFoundException
  255. * @throws \think\exception\DbException
  256. */
  257. protected function live_reward()
  258. {
  259. list($uid, $live_gift_id, $live_gift_num, $live_id, $special_id) = $this->checkValue(['uid' => 0, 'live_gift_id' => 0, 'live_gift_num' => 0, 'live_id' => 0, 'special_id' => 0], true);
  260. if (!$uid || $uid == 0) throw new \Exception('用户id缺失');
  261. if (!$live_gift_id || !is_numeric($live_gift_id) || $live_gift_id == 0) throw new \Exception('礼物id缺失');
  262. if (!$live_id || !is_numeric($live_id) || $live_id == 0) throw new \Exception('直播间号缺失');
  263. if (!$special_id || !is_numeric($special_id) || $special_id == 0) throw new \Exception('直播专题ID缺失');
  264. $user_info = User::where(['uid' => $uid])->find();
  265. $user_info = $user_info ? $user_info->toArray() : [];
  266. if ($uid != $user_info['uid'] || !$user_info) throw new \Exception('非法用户');
  267. if (!$live_gift_num || !is_numeric($live_gift_num) || $live_gift_num < 0) throw new \Exception('请选择礼物数量');
  268. //获取礼物配置列表
  269. $live_gift = LiveGift::liveGiftOne($live_gift_id);
  270. if (!$live_gift) throw new \Exception('礼物不存在');
  271. //查看直播间是否存在
  272. $live_studio = LiveStudio::where(['id' => $live_id])->find();
  273. if (!$live_studio) throw new \Exception('直播间不存在');
  274. $live_studio = $live_studio->toarray();
  275. if ($live_studio['special_id'] != $special_id) throw new \Exception('直播专题有误');
  276. //看金币是否足够
  277. $gift_price = $live_gift['live_gift_price'] * $live_gift_num;
  278. $gold_name = SystemConfigService::get('gold_name');
  279. $user_type = LiveHonouredGuest::where(['uid' => $uid, 'live_id' => $live_id])->value('type');
  280. if (is_null($user_type)) $user_type = 2;
  281. if ($user_info['gold_num'] <= 0 || $gift_price > $user_info['gold_num']){
  282. $new_message = [
  283. 'type' => 'live_reward',
  284. 'content' => '您当前'.$gold_name.'不够,请充值',
  285. 'time' => date('H:i:s'),
  286. 'timestamp' => time(),
  287. 'user_type' => $user_type,
  288. 'recharge_status' => 0,
  289. ];
  290. if (Gateway::isUidOnline($uid)) return Gateway::sendToUid($uid, json_encode($new_message));
  291. }
  292. try{
  293. User::beginTrans();
  294. //插入打赏数据
  295. $add_gift['uid'] = $uid;
  296. $add_gift['live_id'] = $live_studio['id'];
  297. $add_gift['nickname'] = $user_info['nickname'];
  298. $add_gift['gift_id'] = $live_gift_id;
  299. $add_gift['gift_name'] = $live_gift['live_gift_name'];
  300. $add_gift['gift_price'] = $live_gift['live_gift_price'];
  301. $add_gift['total_price'] = $gift_price;
  302. $add_gift['gift_num'] = $live_gift_num;
  303. $add_gift['add_time'] = time();
  304. $live_reward_id = LiveReward::insertLiveRewardData($add_gift);
  305. //插入聊天记录
  306. $add_barrage['uid'] = $uid;
  307. $add_barrage['to_uid'] = 0;
  308. $add_barrage['type'] = 4;//礼物
  309. $add_barrage['barrage'] = $live_reward_id;//礼物ID
  310. $add_barrage['live_id'] = $live_studio['id'];
  311. $add_barrage['is_show'] = 1;
  312. $add_barrage['add_time'] = time();
  313. LiveBarrage::set($add_barrage);
  314. //插入虚拟货币支出记录(资金监管记录表)
  315. $gold_name = SystemConfigService::get("gold_name");
  316. $mark = '用户赠送'.$live_studio['stream_name']."号直播间".$live_gift_num.'个'.$live_gift["live_gift_name"].',扣除'.$gold_name.$gift_price.'金币';
  317. UserBill::expend('用户打赏扣除金币',$uid,'gold_num','live_reward',$gift_price,0,$user_info['gold_num'],$mark);
  318. User::bcDec($uid,'gold_num',$gift_price,'uid');
  319. User::commitTrans();
  320. Gateway::sendToGroup($live_id, json_encode(['uid' => $uid, 'username' => $user_info['nickname'], 'type' => 'live_reward', 'live_gift_num' => $live_gift_num, 'live_gift_id' => $live_gift_id, 'user_avatar' => $user_info['avatar'], 'user_type' => $user_type, 'recharge_status' => 1]));
  321. }catch (\Exception $e){
  322. User::rollbackTrans();
  323. throw new \Exception($e->getMessage);
  324. }
  325. }
  326. }