getTokenType($redpack); if ($redpack['code'] == 'eosio.token' && in_array($tokenType, ['EOS', 'MEETONE'])) { return true; } // 检查是否乱发红包 $parts = explode('-', $redpack['session_id']); if (count($parts) > 1) { // 个人转账只能转EOS return false; } $group_id = (int) $redpack['session_id']; $objGroupEos = new TableHelper('group_eos', 'dw_chat'); $row = $objGroupEos->getRow(compact('group_id')); if ($row['token_code'] == $redpack['code'] && $row['token'] == $tokenType) { return true; } else { return false; } } /** * 初始化红包 * @author solu * @param $redpack Redpack * @param null $objRedis * @param $netId * @return bool */ public function initReward($redpack, $objRedis = null, $netId = Eos::NET_EOS) { $trxId = $redpack['transfer_trx_id']; $total = $redpack['quantity_total_int']; $num = $redpack['num_total']; // 检查红包类型是否正确 $flag = $this->checkValidType($redpack); if (!$flag) { alermErrorMsg("trxId:{$trxId}, quantity_total:{$redpack['quantity_total']}, num:{$num} 发送的红包类型错误"); return false; } !$objRedis && $objRedis = dwRedis::init(Eos::REDIS_SERV); $key = self::getRewardListKey($trxId); if (($total/$num) < self::MONEY_MIN_AVG) { alermErrorMsg("trxId:{$trxId}, total:{$total}, num:{$num} 平均红包金额太小"); return false; } $objRedis->del($key); $total -= $total * self::TEAM_DEDUCT; $list = self::_makeRandomArr($total, $num); array_unshift($list, $key); call_user_func_array([$objRedis, 'lPush'], $list); $objRedis->expire($key, self::REWARD_LIST_TTL); $tokenType = $this->getTokenType($redpack); self::redpackEvent($redpack['session_id'], $redpack['sender'], $trxId, $redpack['memo'], $tokenType, $netId); return true; } private static function redpackEvent($sessionId, $sender, $trxId, $title, $tokenType = 'EOS', $netId = Eos::NET_EOS) { $objUserBindInfo = new UserBindInfo(); $accountType = Eos::getNetAccount($netId); $userId = $objUserBindInfo->getUserIdBy($sender, $accountType); $objSession = new Session(); $se = explode('-', $sessionId); $data = json_encode(compact('title', 'trxId', 'tokenType')); $data = Utils::encodeRC4($data); if (count($se) > 1) { // 发给个人 $to = 0; foreach ($se as $_u) { if ($_u != $userId) { $to = $_u; break; } } // 插入一条聊天消息 $ret = $objSession->sendPersonMsg($userId, $sessionId, Session::MSG_TYPE_REDPACK, $data, true); $nickName = User::getUserNameById($userId); $eventData = [ 'type' => 'new_redpack', 'msg_type' => Session::MSG_TYPE_REDPACK, 'from' => (int) $userId, 'to' => (int) $to, 'name' => $nickName, 'nick_name' => $nickName, 'hash' => $ret['hash'], 'content' => $data // 'content' => Utils::encodeRC4($title), // 'ext' => compact('trxId'), ]; ThirdApi::pushPersonEvent($userId, $eventData); ThirdApi::pushPersonEvent($to, $eventData); } else { // 插入一条聊天消息 $ret = $objSession->sendGroupMsg($userId, $sessionId, Session::MSG_TYPE_REDPACK, $data, true); // 发给群组 $groupId = current($se); $eventData = [ 'type' => 'new_redpack', 'msg_type' => Session::MSG_TYPE_REDPACK, 'group_id' => $groupId, 'from' => $userId, 'name' => GroupInfo::getGroupNameById($groupId), 'nick_name' => User::getUserNameById($userId), 'hash' => $ret['hash'], 'content' => $data, 'userMap' => $ret['userMap'], // 'content' => Utils::encodeRC4($title), // 'ext' => compact('trxId'), ]; ThirdApi::pushGroupEvent($groupId, $eventData); } } private static function _makeRandomArr($money, $num, $min = 1) { $list = []; while ($num > 0) { if ($num == 1) { $list[] = $money; break; } else { $max = ($money / $num) * 2; $_tmp = rand($min, $max); $_tmp <= $min && $_tmp = $min; $list[] = $_tmp; $money -= $_tmp; } $num--; } return $list; } /** * 抢红包 * @author solu * @param $trxId * @param $userId * @return array * @throws Exception */ public function grab($trxId, $userId) { $row = $this->objTable->getRow(['transfer_trx_id' => $trxId]); if (!$row) { throw new Exception('miss redpack', CODE_NORMAL_ERROR); } $parts = explode('-', $row['session_id']); // 判断权限 if (count($parts) > 1) { // 私聊 $can = in_array($userId, $parts); } else { $c = (new UserGroup())->objTable->getCount(['user_id' => $userId, 'group_id' => $row['session_id'], 'state' => UserGroup::STATE_IN_GROUP]); $can = $c > 0; } if (!$can) { throw new Exception('no permission', CODE_NO_PERMITION); } if (self::STATUS_PLAYING != $row['status']) { throw new Exception('Too Late', -1001); } $netId = (int)$row['net_id']; $accountType = Eos::getNetAccount($netId); $objUserBindInfo = new UserBindInfo(); $account = $objUserBindInfo->getAccountByUserId($userId, $accountType); if (!$account) { $accountTypeName = Account::getTypeName($accountType); throw new Exception("not bind {$accountTypeName} account", CODE_NORMAL_ERROR); } $objLog = new TableHelper('redpack_log', 'dw_chat'); if ($objLog->getCount(['redpack_trx_id' => $trxId, 'user_id' => $userId])) { throw new Exception('repeat grab', CODE_NORMAL_ERROR); } $key = self::getRewardListKey($trxId); $objRedis = dwRedis::init(Eos::REDIS_SERV); $quantity = $objRedis->rPop($key); if (false === $quantity) { throw new Exception('Too Late', CODE_NORMAL_ERROR); } $tokenType = $this->getTokenType($row); $strQuantity = Eos::toDisplayFormat($quantity, $tokenType); $redpackId = $row['id']; $data = [ 'redpack_id' => $redpackId, 'redpack_trx_id' => $trxId, 'player' => $account, 'quantity' => $strQuantity, 'quantity_int' => $quantity, 'create_time' => NOW, 'user_id' => $userId, 'net_id' => $netId, ]; $objLog->addObject($data); $logId = $objLog->getInsertId(); if (!$logId) { throw new Exception('log error', CODE_NORMAL_ERROR); } $from = $objUserBindInfo->getUserIdBy($row['sender'], $accountType); $eventData = [ 'type' => 'grab_redpack', 'from' => (int) $from, 'to' => (int) $userId, 'content' => [ 'title' => $row['memo'], 'redpack_id' => $redpackId, 'redpack_trx_id' => $trxId, 'quantity' => $strQuantity, ], ]; $objSession = new Session(); $extInfo = $eventData; $extInfo['event_type'] = $eventData['type']; unset($extInfo['type']); try { if (count($parts) == 1) { // 抢红包的信息,要发给发红包的人 $groupId = current($parts); $extInfo['group_id'] = $groupId; $objSession->sendGroupMsg($userId, $groupId, Session::MSG_TYPE_EVENT, '', false, true, $extInfo); } else { $objSession->sendPersonMsg($userId, $row['session_id'], Session::MSG_TYPE_EVENT, '', false, $extInfo); } } catch (Exception $e) { var_log($e->getMessage()); } Eos::grabRedpack($redpackId, $trxId, $logId, $account, $strQuantity, $netId); $team = round($row['quantity_total_int'] * self::TEAM_DEDUCT); // 团队提成 $ret = [ 'from' => $from, 'quantity' => $quantity, 'type' => 'eos', 'tokenType' => $this->getTokenType($row), 'num_total' => $row['num_total'], 'num_left' => $row['num_left'] - 1, 'quantity_total' => $row['quantity_total_int'] - $team, 'quantity_left' => $row['quantity_left_int'] - $quantity, 'logs' => (new RedpackLog())->getByTrxId($trxId), ]; return $ret; } /** * 红包详情 * @author solu * @param $trxId * @return array */ public function detail($trxId) { $row = $this->objTable->getRow(['transfer_trx_id' => $trxId]); if (!$row) { return []; } $team = round($row['quantity_total_int'] * self::TEAM_DEDUCT); // 团队提成 $ret = [ 'from' => $row['sender_id'], 'title' => $row['memo'], 'tokenType' => $this->getTokenType($row), 'type' => 'EOS', 'redpack_status' => $row['status'], 'num_total' => $row['num_total'], 'num_left' => $row['num_left'], 'quantity_total' => $row['quantity_total_int'] - $team, 'quantity_left' => $row['quantity_left_int'], 'logs' => (new RedpackLog())->getByTrxId($trxId), ]; return $ret; } /** * 发出的红包 * @author solu * @param $userId * @param int $offset * @param int $size * @return array */ public function sendList($userId, $offset = 0, $size = 20) { if (!$userId) { return []; } $list = $this->objTable->getAll(['sender_id' => $userId], [ '_field' => 'id, session_id, num_total, num_left, quantity_total_int, quantity_left_int, memo as title, status, transfer_trx_id, create_time', '_sortKey' => 'id DESC', '_limit' => "{$offset}, {$size}", ]); $total_count = 0; $total_quantity = 0; if (0 == $offset) { $row = $this->objTable->getRow(['sender_id' => $userId], [ '_field' => 'sum(quantity_total_int) as total_quantity, count(1) as c', ]); $total_count = (int)$row['c']; $total_quantity = (int)$row['total_quantity']; } return [$list, $total_count, $total_quantity]; } /** * 收到的红包 * @author solu * @param $userId * @param int $offset * @param int $size * @return array */ public function receiveList($userId, $offset = 0, $size = 20) { if (!$userId) { return []; } $objRedpackLog = new RedpackLog(); $list = $objRedpackLog->objTable->getAll(['user_id' => $userId], [ '_field' => 'id, redpack_trx_id, quantity_int, create_time, status, best', '_sortKey' => 'id DEsc', '_limit' => "{$offset}, {$size}", ]); $trxIds = array_column($list, 'redpack_trx_id'); $redpacks = $this->objTable->getAll(['transfer_trx_id' => $trxIds], [ '_field' => 'id, transfer_trx_id, sender_id, memo, status', ]); $redpacks = arrayFormatKey($redpacks, 'transfer_trx_id'); $senderIds = array_column($redpacks, 'sender_id'); $objUser = new TableHelper('user_info', 'dw_chat'); $users = $objUser->getAll(['user_id' => $senderIds], ['_field' => 'user_id, nick_name, cover_photo']); $users = arrayFormatKey($users, 'user_id', 'nick_name'); foreach ($list as $k => $v) { $redpack = $redpacks[$v['redpack_trx_id']]; $senderNick = $users[$redpack['sender_id']]; $v['sender'] = $senderNick; $v['title'] = $redpack['memo']; $list[$k] = $v; } $total_count = 0; $best_count = 0; $total_quantity = 0; if (0 == $offset) { $row = $this->objTable->getRow(['sender_id' => $userId], [ '_field' => 'sum(quantity_int) as total_quantity, count(1) as c, sum(best) best_count', ]); $total_count = (int)$row['c']; $total_quantity = (int)$row['total_quantity']; $best_count = (int)$row['best_count']; } return [$list, $total_count, $total_quantity, $best_count]; } }