472 lines
17 KiB
PHP
472 lines
17 KiB
PHP
<?php
|
||
|
||
include_once "endecrypt/wxBizMsgCrypt.php";
|
||
|
||
class KefuController {
|
||
|
||
protected function getRedis($accountid)
|
||
{
|
||
$redis_conf = getRedisConfig(crc32($accountid));
|
||
$r = new phpcommon\Redis(array(
|
||
'host' => $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;
|
||
}
|
||
}
|
||
|
||
protected function delOvertimeOpenid($accountid)
|
||
{
|
||
$conn = $this->getMysql($accountid);
|
||
error_log('del:' . $accountid);
|
||
$ret = $conn->execScript('DELETE FROM accounts ' .
|
||
'WHERE accountid=:accountid;',
|
||
array(
|
||
':accountid' => $accountid,
|
||
));
|
||
}
|
||
|
||
private function sendKefuMsg($accountid, $data)
|
||
{
|
||
try {
|
||
$gameid = phpcommon\extractGameId($accountid);
|
||
$access_token = $this->getAccessToken($gameid);
|
||
$url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=" . urlencode($access_token);
|
||
|
||
$response = '';
|
||
error_log('kefu_openid');
|
||
error_log(json_encode($data, JSON_UNESCAPED_UNICODE));
|
||
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 || $ret_info['errcode'] == 40003 || $ret_info['errcode'] == 41001)) {
|
||
if ($ret_info['errcode'] == 40003) {
|
||
//无效的openid,(更换appid appkey导致之前的openid失效)
|
||
//从db里删除这种过期的openid
|
||
$this->delOvertimeOpenid($accountid);
|
||
return true;
|
||
}
|
||
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=". urlencode($access_token);
|
||
|
||
$response = '';
|
||
error_log(json_encode($data, JSON_UNESCAPED_UNICODE));
|
||
if (!phpcommon\HttpClient::post($url,
|
||
json_encode($data, JSON_UNESCAPED_UNICODE),
|
||
$response)
|
||
) {
|
||
phpcommon\sendError(ERR_RETRY, '系统繁忙');
|
||
return;
|
||
}
|
||
error_log('retry:' . $response);
|
||
$ret_info = json_decode($response, true);
|
||
}
|
||
return !empty($ret_info) && $ret_info['errcode'] == 0;
|
||
} catch (Exception $e) {
|
||
error_log($e->getMessage());
|
||
return false;
|
||
}
|
||
}
|
||
|
||
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, activetime ' .
|
||
' FROM accounts WHERE activetime > :time AND idx > :last_idx LIMIT 0, 1000;',
|
||
array(
|
||
':last_idx' => $last_idx,
|
||
':time' => time() - 3600 * 24
|
||
));
|
||
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)
|
||
{
|
||
$this->createUser($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, activetime ' .
|
||
' 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;
|
||
}
|
||
$this->updateActiveTime($conn);
|
||
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') {
|
||
$this->createUser($accountid);
|
||
}
|
||
}
|
||
|
||
private function createUser($accountid) {
|
||
$conn = $this->getMysql($accountid);
|
||
$ret = $conn->execScript('INSERT INTO accounts(accountid, channel, gameid, openid, awardtime, activetime) ' .
|
||
'SELECT :accountid, :channel, :gameid, :openid, :awardtime, :activetime ' .
|
||
'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,
|
||
':activetime' => 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 {
|
||
error_log('getAccessToken:' . $response);
|
||
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 '';
|
||
}
|
||
}
|
||
|
||
protected function updateActiveTime($conn)
|
||
{
|
||
$ret = $conn->execScript('UPDATE accounts SET ' .
|
||
' activetime=:activetime ' .
|
||
' WHERE accountid=:accountid; ',
|
||
array(
|
||
':accountid' => $accountid,
|
||
':activetime' => time()
|
||
));
|
||
}
|
||
|
||
}
|