$redis_conf['host'], 'port' => $redis_conf['port'], 'passwd' => $redis_conf['passwd'] )); return $r; } protected function getMysql($accountid) { $mysql_conf = getMysqlConfig(crc32($accountid)); $conn = new phpcommon\Mysql(array( 'host' => $mysql_conf['host'], 'port' => $mysql_conf['port'], 'user' => $mysql_conf['user'], 'passwd' => $mysql_conf['passwd'], 'dbname' => 'kefudb' . $mysql_conf['instance_id'] )); return $conn; } private function translateAttachments($config) { $attachments = ''; foreach ($config as $attachment) { $attachments .= $attachment['item_id'] . ':' . $attachment['count'] . ';'; } return $attachments; } private function getAwardConfig($gameid, $condition) { $url = ''; if (SERVER_ENV != _ONLINE) { $url = 'https://center-test.kingsome.cn/api/replays/'; } else { $url = 'https://center.kingsome.cn/api/replays/'; } $url .= $gameid . '/' . $condition; $response = ''; $params = array(); if (!phpcommon\HttpClient::get($url, $params, $response)) { die(); return; } error_log($response); $ret = json_decode($response, true); if ($ret['errcode'] == 0) { if ($gameid >= 2001 && $gameid < 3000) { if (count($ret['items']) > 0) { $item = $ret['items'][rand() % count($ret['items'])]; error_log(json_encode($item)); return array($item); } else { return $ret['items']; } } else { return $ret['items']; } } else { return; } } private function sendAwardMail($accountid, $config) { if (SERVER_ENV != _ONLINE) { $url = 'https://gamemail-test.kingsome.cn/webapp/index.php?'; } else { $url = 'https://gamemail.kingsome.cn/webapp/index.php?'; } $attachments = ''; error_log(time()); foreach ($config as $attachment) { $attachments .= $attachment['item_id'] . ':' . $attachment['count'] . ';'; } $params = array( 'to' => $accountid, 'game_id' => phpcommon\extractGameId($accountid), 'from' => '客服', 'mail_type' => 1, 'mail_subtype' => 0, 'subject' => '领奖', 'content' => '领取奖励', 'sendtime' => time(), 'ext' => '', 'expire_time' => time() + 3600 * 24, 'attachments' => $this->translateAttachments($config) ); $params['c'] = 'Mail'; $params['a'] = 'sendMail'; $params['timestamp'] = time(); $params['sign'] = phpcommon\md5Sign($params, '14e1b600b1fd579f47433b88e8d85291', $params['timestamp']); $response = ''; if (!phpcommon\HttpClient::get($url, $params, $response)) { return false; } $data = json_decode($response, true); return $data && $data['errcode'] == 0; } public function checkServer() // 校验服务器地址URL { $gameid = $_REQUEST['gameid']; $config_name = "../config/game$gameid/weixin/config.php"; require $config_name; if (isset($_REQUEST['echostr'])) { if ($this->checkSignature()) { echo $_REQUEST['echostr']; } else { echo 'signature error'; } die(); return; } $msg_str = ''; $pc = new WXBizMsgCrypt(WEIXIN_TOKEN, WEIXIN_MSG_KEY, WEIXIN_APP_ID); $errcode = $pc->decryptJsonMsg($_REQUEST['msg_signature'], $_REQUEST['timestamp'], $_REQUEST['nonce'], file_get_contents('php://input'), $msg_str); if ($errcode == 0) { $msg = json_decode($msg_str, true); error_log(json_encode($msg)); $accountid = phpcommon\createAccountId(WEIXIN_CHANNEL, $_REQUEST['gameid'], $msg['FromUserName']); switch ($msg['MsgType']) { case 'event': { // 进入客服动作 $this->processEvent($msg, $accountid); break; } case 'text': { // 文本消息 $this->processText($msg, $accountid); break; } case 'image': { // 图文消息 die('not implement'); break; } case 'miniprogrampage': { // 小程序消息 $this->processText($msg, $accountid); break; } } } else { #error_log($errcode . "\n"); } } public function notifyAllUser() { error_log('notifyAllUser'); set_time_limit(1800); $media_conf = array(); $dbconfs = require('../config/kefu.mysql.cluster.php');; foreach($dbconfs as $dbconf) { $conn = new phpcommon\Mysql(array( 'host' => $dbconf['host'], 'port' => $dbconf['port'], 'user' => $dbconf['user'], 'passwd' => $dbconf['passwd'], 'dbname' => 'kefudb' . $dbconf['instance_id'] )); $this->sendOneDBInfo($conn, $media_conf); } echo json_encode(array( 'errcode' => 0, 'errmsg' => '', )); } private function checkSignature() { $signature = $_REQUEST["signature"]; $timestamp = $_REQUEST["timestamp"]; $nonce = $_REQUEST["nonce"]; $token = WEIXIN_TOKEN; $tmpArr = array ($token, $timestamp, $nonce); sort($tmpArr , SORT_STRING); $tmpStr = implode($tmpArr); $tmpStr = sha1($tmpStr); if ($tmpStr == $signature){ return true; } else { return false; } } private function sendKefuMsg($accountid, $data) { $gameid = phpcommon\extractGameId($accountid); $access_token = $this->getAccessToken($gameid); $url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=$access_token"; $response = ''; if (!phpcommon\HttpClient::post($url, json_encode($data, JSON_UNESCAPED_UNICODE), $response) ) { phpcommon\sendError(ERR_RETRY, '系统繁忙'); return; } $ret_info = json_decode($response, true); error_log(json_encode($response)); if (isset($ret_info['errcode']) && $ret_info['errcode'] == 40001) { error_log('重新获取access_token'); $r = $this->getRedis($gameid); $r->del('kf_token:' . $gameid . ':'); $access_token = $this->getAccessToken($gameid); $url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=$access_token"; $response = ''; if (!phpcommon\HttpClient::post($url, json_encode($data, JSON_UNESCAPED_UNICODE), $response) ) { phpcommon\sendError(ERR_RETRY, '系统繁忙'); return; } $ret_info = json_decode($response, true); } return !empty($ret_info) && $ret_info['errcode'] == 0; } private function sendOneDBInfo($conn, &$media_conf) { $last_idx = 0; $share_conf = require('../config/kefu.share.config.php'); while (true) { $rows = $conn->execQuery('SELECT idx, accountid, openid, awardtime, gameid ' . "FROM accounts WHERE idx > :last_idx LIMIT 0, 1000;", array( ':last_idx' => $last_idx, )); if (!$rows || count($rows) <= 0) { break; } foreach ($rows as $row) { if (isset($share_conf[$row['gameid']])) { $game_conf = $share_conf[$row['gameid']]; if (!isset($media_conf[$row['gameid']])) { $media_conf[$row['gameid']] = $this->getMediaId($row['gameid']); } $game_conf['thumb_media_id'] = $media_conf[$row['gameid']]; $this->sendKefuMsg($row['accountid'], array ( "touser" => $row['openid'], "msgtype" => "miniprogrampage", "miniprogrampage" => $game_conf )); } if ($row['idx'] > $last_idx) { $last_idx = $row['idx']; } } } } private function processText($msg, $accountid) { $openid = $msg['FromUserName']; $CreateTime = $msg['CreateTime']; //$text = $msg['Content']; $text = ''; $gameid = phpcommon\extractGameId($accountid); if (strcmp($msg['MsgType'], 'miniprogrampage') == 0) { $text = 1; } else { $text = $msg['Content']; } //error_log(json_encode($gameid)); $awardConfig = $this->getAwardConfig($gameid, $text); if (!isset($awardConfig)) { $this->sendKefuMsg($accountid, array ( "touser" => $openid, "msgtype" => "text", "text" => array ("content" => '回复指定文字领取奖励!') )); return; } $conn = $this->getMysql($accountid); $row = $conn->execQueryOne('SELECT awardtime ' . "FROM accounts WHERE accountid = :accountid;", array( ':accountid' => $accountid, )); if (!$row) { $this->sendKefuMsg($accountid, array ( "touser" => $openid, "msgtype" => "text", "text" => array ("content" => "请从游戏进入客服!") )); return; } date_default_timezone_set('Asia/Shanghai'); if ($row && date("y-m-d", time()) == date("y-m-d", $row['awardtime'])) { $this->sendKefuMsg($accountid, array ( "touser" => $openid, "msgtype" => "text", "text" => array ("content" => "一天内只能领取一次奖励!\n请明天再来!") )); return; } if ($this->sendAwardMail($accountid, $awardConfig)) { $ret = $conn->execScript("UPDATE accounts SET " . ' awardtime=:awardtime ' . 'WHERE accountid=:accountid; ', array( ':accountid' => $accountid, ':awardtime' => time() )); if ($ret) { $this->sendKefuMsg($accountid, array ( "touser" => $openid, "msgtype" => "text", "text" => array ("content" => '奖励领取成功,请查收邮件!') )); } } } private function processEvent($msg, $accountid) { if ($msg['Event'] == 'user_enter_tempsession') { $conn = $this->getMysql($accountid); $ret = $conn->execScript('INSERT INTO accounts(accountid, channel, gameid, openid, awardtime) ' . 'SELECT :accountid, :channel, :gameid, :openid, :awardtime ' . 'FROM DUAL ' . 'WHERE NOT EXISTS(SELECT accountid FROM accounts WHERE accountid=:accountid);', array( ':accountid' => $accountid, ':channel' => WEIXIN_CHANNEL, ':gameid' => phpcommon\extractGameId($accountid), ':openid' => $msg['FromUserName'], ':awardtime' => 0 )); if ($ret) { $this->sendKefuMsg($accountid, array( "touser" => $msg['FromUserName'], "msgtype" => "text", //"text" => array("content" => "您好,有什么能帮助你? \n ") )); } } } private function getAccessToken($gameid) { $r = $this->getRedis($gameid); $access_token = $r->get('kf_token:' . $gameid . ':'); if (!empty($access_token)) { return $access_token; } $config_name = "../config/game$gameid/weixin/config.php"; @require $config_name; $response = ''; if (!phpcommon\HttpClient::get('https://api.weixin.qq.com/cgi-bin/token', array( 'grant_type' => 'client_credential', 'appid' => WEIXIN_APP_ID, 'secret' => WEIXIN_APP_SECRET ), $response)) { phpcommon\sendError(ERR_INTERNAL, '系统繁忙'); return; } $respobj = json_decode($response, true); if (isset($respobj['access_token'])) { $r->set('kf_token:' . $gameid . ':', $respobj['access_token']); $r->pexpire('kf_token:' . $gameid . ':', 1000 * ($respobj['expires_in'] - 60 * 1)); return $respobj['access_token']; } else { return ''; } } private function getMediaId($gameid) { error_log('getMediaId ' . $gameid); $type = "image"; $filepath = "../config/game$gameid/share.png"; $filedata = array( "media" => "@" . $filepath ); $access_token = $this->getAccessToken($gameid); $url = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=$access_token&type=$type"; $response = ''; if (phpcommon\HttpClient::upload($url, $filedata, $response)) { error_log('getMediaId ' . $response); $jsonobj = json_decode($response, true); if(isset($jsonobj['media_id'])) { return $jsonobj['media_id']; } else { return ''; } } else { return ''; } } }