This commit is contained in:
aozhiwei 2020-04-30 10:17:31 +08:00
parent b8949f0b9a
commit 2843a2b477
6 changed files with 638 additions and 2 deletions

View File

@ -52,6 +52,33 @@ CREATE TABLE `accounts` (
KEY `channel_index` (`channel`),
KEY `gameid_index` (`gameid`)
) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
DROP TABLE IF EXISTS `subscribe`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `subscribe` (
`idx` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`accountid` varchar(60) DEFAULT '' COMMENT '账号id(channel + "_" + gameid + "_" + openid)',
`channel` int(11) NOT NULL COMMENT 'channel',
`gameid` int(11) NOT NULL COMMENT 'gameid',
`openid` varchar(50) NOT NULL COMMENT '平台',
`signorder` int(11) NOT NULL DEFAULT '0' COMMENT '是否订阅签到',
`boxorder` int(11) NOT NULL DEFAULT '0' COMMENT '是否订阅宝箱',
`diaorder` int(11) NOT NULL DEFAULT '0' COMMENT '是否订阅钻石',
`seaorder` int(11) NOT NULL DEFAULT '0' COMMENT '是否订阅赛季',
`signtime` int(11) NOT NULL DEFAULT '0' COMMENT '最后签到订阅时间',
`boxtime` int(11) NOT NULL DEFAULT '0' COMMENT '最后宝箱订阅时间',
`diatime` int(11) NOT NULL DEFAULT '0' COMMENT '最后钻石订阅时间',
`seatime` int(11) NOT NULL DEFAULT '0' COMMENT '最后赛季订阅时间',
PRIMARY KEY (`idx`),
UNIQUE KEY `accountid` (`accountid`),
UNIQUE KEY `channel_gameid_openid_index` (`channel`,`gameid`,`openid`),
KEY `openid_index` (`openid`),
KEY `channel_index` (`channel`),
KEY `gameid_index` (`gameid`)
) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
/*!40101 SET character_set_client = @saved_cs_client */;

View File

@ -0,0 +1,30 @@
begin;
DROP TABLE IF EXISTS `subscribe`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `subscribe` (
`idx` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`accountid` varchar(60) DEFAULT '' COMMENT '账号id(channel + "_" + gameid + "_" + openid)',
`channel` int(11) NOT NULL COMMENT 'channel',
`gameid` int(11) NOT NULL COMMENT 'gameid',
`openid` varchar(50) NOT NULL COMMENT '平台',
`signorder` int(11) NOT NULL DEFAULT '0' COMMENT '是否订阅签到',
`boxorder` int(11) NOT NULL DEFAULT '0' COMMENT '是否订阅宝箱',
`diaorder` int(11) NOT NULL DEFAULT '0' COMMENT '是否订阅钻石',
`seaorder` int(11) NOT NULL DEFAULT '0' COMMENT '是否订阅赛季',
`signtime` int(11) NOT NULL DEFAULT '0' COMMENT '最后签到订阅时间',
`boxtime` int(11) NOT NULL DEFAULT '0' COMMENT '最后宝箱订阅时间',
`diatime` int(11) NOT NULL DEFAULT '0' COMMENT '最后钻石订阅时间',
`seatime` int(11) NOT NULL DEFAULT '0' COMMENT '最后赛季订阅时间',
PRIMARY KEY (`idx`),
UNIQUE KEY `accountid` (`accountid`),
UNIQUE KEY `channel_gameid_openid_index` (`channel`,`gameid`,`openid`),
KEY `openid_index` (`openid`),
KEY `channel_index` (`channel`),
KEY `gameid_index` (`gameid`)
) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
insert into version (version) values(2020043001);
commit;

15
tools/nohup.out Normal file
View File

@ -0,0 +1,15 @@
start!
1588176000
1588176000
1588176000
1588176000
1588176000
1588176000
2020-04-30 08:00:1588204800
sendNotifySubscribe start
sendNotify end
1588262400
2020-04-30 09:00:1588208400
sendNotifySubscribe start
sendNotify end
1588262400

89
tools/subscribe_robot.py Normal file
View File

@ -0,0 +1,89 @@
# -*- coding: utf-8 -*-
import os
import json
import time
import datetime
import hashlib
import urllib.request
import tornado.ioloop
import tornado.web
def md5Sign(params, secret, timestamp, connstr = '&', secret_connstr = ':'):
params_str = ''
for key in sorted(params.keys()):
params_str = params_str + key + '=' + str(params[key]) + connstr
if params_str != '' and connstr != '':
params_str = params_str[0:-1]
str1 = params_str + secret_connstr + str(timestamp) + secret
try:
m5 = hashlib.md5()
m5.update(str1.encode('utf-8'))
return m5.hexdigest()
except Exception as e:
print('md5Sign error: ' + str(e), flush=True)
def getDaySeconds(time_val, incdays):
time_zone = 8
dayseconds = int((time_val + time_zone * 3600)/3600/24 + incdays) * 3600 * 24 - 3600 * time_zone;
print(dayseconds, flush=True)
return dayseconds
def sendNotify(conf, sendtime):
try:
print(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%s"), flush=True)
print('sendNotifySubscribe start', flush=True)
params = {'key' : 'kingsome'}
secret = 'fc38349c5d084e920925e614c420be9f'
timestamp = time.time()
md5signstr = md5Sign(params, secret, timestamp)
url = conf['notify_url'] + '&timestamp=' + str(timestamp) + '&sign=' + md5signstr
req = urllib.request.Request(url)
data = urllib.request.urlopen(req).read()
print('sendNotify end', flush=True)
except Exception as e:
print('sendNotiSubscribe error: ' + str(e), flush=True)
#进入下一次循环
tornado.ioloop.IOLoop.current().call_at(getDaySeconds(time.time(), 1) + sendtime,
lambda : sendNotify(conf, sendtime))
class SelfCheckingHandler(tornado.web.RequestHandler):
def get(self):
self.write(json.dumps({
'errcode': 0,
'errmsg': '',
'healthy': 1,
'max_rundelay': 10
},
separators=(',', ':')))
def make_app():
return tornado.web.Application([
(r"/webapp/index[\.]php", SelfCheckingHandler),
])
if __name__ == "__main__":
print('start!', flush=True)
conf = json.loads(open('../config/subscribe_robot.json', 'r').read())
app = make_app()
app.listen(conf['listen_port'])
#sendNotify(conf, conf['signtime'])
tornado.ioloop.IOLoop.current().call_at(getDaySeconds(time.time(), 1) + conf['signtime'],
lambda : sendNotify(conf, conf['signtime']))
tornado.ioloop.IOLoop.current().call_at(getDaySeconds(time.time(), 1) + conf['boxtime'],
lambda : sendNotify(conf, conf['boxtime']))
tornado.ioloop.IOLoop.current().call_at(getDaySeconds(time.time(), 1) + conf['diamondtime1'],
lambda : sendNotify(conf, conf['diamondtime1']))
tornado.ioloop.IOLoop.current().call_at(getDaySeconds(time.time(), 1) + conf['diamondtime2'],
lambda : sendNotify(conf, conf['diamondtime2']))
tornado.ioloop.IOLoop.current().call_at(getDaySeconds(time.time(), 1) + conf['diamondtime3'],
lambda : sendNotify(conf, conf['diamondtime3']))
tornado.ioloop.IOLoop.current().call_at(getDaySeconds(time.time(), 1) + conf['seasontime'],
lambda : sendNotify(conf, conf['seasontime']))
tornado.ioloop.IOLoop.current().start()

View File

@ -271,6 +271,7 @@ class KefuController {
}
}
private function sendOneDBInfo($conn, &$media_conf)
{
$last_idx = 0;
@ -410,8 +411,8 @@ class KefuController {
return $access_token;
}
$config_name = "../config/game$gameid/weixin/config.php";
@require $config_name;
require $config_name;
echo('zzz4');
$response = '';
if (!phpcommon\HttpClient::get('https://api.weixin.qq.com/cgi-bin/token',
array(

View File

@ -0,0 +1,474 @@
<?php
include_once "endecrypt/wxBizMsgCrypt.php";
class SubscribeController {
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 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;
echo('zzz4');
$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 '';
}
}
public function sendOrderMsg($accountid, $data)
{
error_log($accountid);
try {
$gameid = phpcommon\extractGameId($accountid);
$access_token = $this->getAccessToken($gameid);
error_log($access_token);
$url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" . urlencode($access_token);
$response = '';
error_log('kefu_openid');
echo(json_encode($data));
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));
echo(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/subscribe/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)
{
$last_idx = 0;
$template_id = '';
$data = array();
$date = phpcommon\timestamp_to_datetime(time());
//通知签到
if (floor((time() - phpcommon\getdayseconds(time())) / 3600) == 8) {
while (true) {
$rows = $conn->execQuery('SELECT idx, accountid, openid, signtime ' .
' FROM subscribe WHERE signorder=1 AND idx > :last_idx LIMIT 0, 1000;',
array(
':last_idx' => $last_idx,
));
if (!$rows || count($rows) <= 0) {
break;
}
foreach ($rows as $row) {
if ($row['idx'] > $last_idx) {
$last_idx = $row['idx'];
}
if (floor((time() - phpcommon\getdayseconds($row['signtime'])) / 3600) != 32) {
continue;
}
$data = array(
'thing5' => array(
'value' => '连续签到,有机会获得永久时装'
),
'date4' => array(
'value' => $date
),
);
$template_id = 'lnZSKqeQPI6riyuH9FinutFBrbe6OE3W-7FjwVgoeo4';
$this->sendOrderMsg($row['accountid'],
array (
"touser" => $row['openid'],
"template_id" => $template_id,
"data" => $data
));
$ret = $conn->execScript('UPDATE subscribe SET ' .
' signorder=:signorder ' .
' WHERE accountid=:accountid; ',
array(
':accountid' => $row['accountid'],
':signorder' => 0
));
if (!$ret) {
die();
return;
}
}
}
//通知宝箱
} else if (floor((time() - phpcommon\getdayseconds(time())) / 3600) == 14) {
while (true) {
$rows = $conn->execQuery('SELECT idx, accountid, openid, boxtime ' .
' FROM subscribe WHERE boxorder=1 AND idx > :last_idx LIMIT 0, 1000;',
array(
':last_idx' => $last_idx,
));
if (!$rows || count($rows) <= 0) {
break;
}
foreach ($rows as $row) {
if ($row['idx'] > $last_idx) {
$last_idx = $row['idx'];
}
if (floor((time() - phpcommon\getdayseconds($row['boxtime'])) / 3600) != 38) {
continue;
}
$data = array(
'thing1' => array(
'value' => '免费宝箱'
),
'thing4' => array(
'value' => '有机会获得钻石和限时时装'
),
'date2' => array(
'value' => $date
),
);
$template_id = 'di_iqZLOeUzpwIblhvn_HDygoVH34Fs9MwD-asOX6J8';
$this->sendOrderMsg($row['accountid'],
array (
"touser" => $row['openid'],
"template_id" => $template_id,
"data" => $data
));
$ret = $conn->execScript('UPDATE subscribe SET ' .
' boxorder=:boxorder ' .
' WHERE accountid=:accountid; ',
array(
':accountid' => $row['accountid'],
':boxorder' => 0
));
if (!$ret) {
die();
return;
}
}
}
//通知钻石
} else if (floor((time() - phpcommon\getdayseconds(time())) / 3600) == 12
|| floor((time() - phpcommon\getdayseconds(time())) / 3600) == 9
|| floor((time() - phpcommon\getdayseconds(time())) / 3600) == 18) {
while (true) {
$rows = $conn->execQuery('SELECT idx, accountid, openid, diatime ' .
' FROM subscribe WHERE diaorder=1 AND idx > :last_idx LIMIT 0, 1000;',
array(
':last_idx' => $last_idx,
));
if (!$rows || count($rows) <= 0) {
break;
}
foreach ($rows as $row) {
if ($row['idx'] > $last_idx) {
$last_idx = $row['idx'];
}
if (floor((time() - phpcommon\getdayseconds($row['diatime'])) / 3600) != 33
&& floor((time() - phpcommon\getdayseconds($row['diatime'])) / 3600) != 12
&& floor((time() - phpcommon\getdayseconds($row['diatime'])) / 3600) != 18) {
continue;
}
$data = array(
'thing1' => array(
'value' => '幸运礼包'
),
'thing4' => array(
'value' => '领取物资,有几率开出锦鲤套装'
),
'date2' => array(
'value' => $date
),
);
$template_id = 'di_iqZLOeUzpwIblhvn_HMaFbcOcO_VvgPIFz-NhA9c';
$this->sendOrderMsg($row['accountid'],
array (
"touser" => $row['openid'],
"template_id" => $template_id,
"data" => $data
));
$ret = $conn->execScript('UPDATE subscribe SET ' .
' diaorder=:diaorder ' .
' WHERE accountid=:accountid; ',
array(
':accountid' => $row['accountid'],
':diaorder' => 0
));
if (!$ret) {
die();
return;
}
}
}
//通知赛季
} else if (floor((time() - phpcommon\getdayseconds(phpcommon\getThisMonthFirstDaySeconds(time()) + 5 * 3600 * 24)) / 3600) == 17) {
$start = phpcommon\timestamp_to_date(phpcommon\getThisMonthFirstDaySeconds(time()) + 6 * 3600 * 24);
$end = phpcommon\timestamp_to_date(phpcommon\getNextMonthFirstDaySeconds(time()) + 5 * 3600 * 24);
while (true) {
$rows = $conn->execQuery('SELECT idx, accountid, openid, seatime ' .
' FROM subscribe WHERE seaorder=1 AND idx > :last_idx LIMIT 0, 1000;',
array(
':last_idx' => $last_idx,
));
if (!$rows || count($rows) <= 0) {
break;
}
foreach ($rows as $row) {
if ($row['idx'] > $last_idx) {
$last_idx = $row['idx'];
}
$data = array(
'thing1' => array(
'value' => '新赛季即将开启'
),
'thing12' => array(
'value' => '新赛季新奖励, 更多惊喜等着您!'
),
'date6' => array(
'value' => $start
),
'date7' => array(
'value' => $end
),
);
$template_id = 'VEZDV0GJxAtouMq2imy3Ykqof3x1dd-hR59dO7osEUU';
$this->sendOrderMsg($row['accountid'],
array (
"touser" => $row['openid'],
"template_id" => $template_id,
"data" => $data
));
$ret = $conn->execScript('UPDATE subscribe SET ' .
' diaorder=:diaorder ' .
' WHERE accountid=:accountid; ',
array(
':accountid' => $row['accountid'],
':diaorder' => 0
));
if (!$ret) {
die();
return;
}
}
}
}
}
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);
}
echo json_encode(array(
'errcode' => 0,
'errmsg' => '',
));
}
public function sendOrder()
{
$account_id = $_REQUEST['account_id'];
$accept = $_REQUEST['accept'];
$type = $_REQUEST['type'];
$conn = $this->getMysql($account_id);
if (!$conn) {
phpcommon\sendError(ERR_USER_BASE + 1, '没有这个玩家');
return;
}
$row = $conn->execQueryOne('SELECT * ' .
' FROM subscribe WHERE accountid=:accountid;',
array(
':accountid' => $account_id,
));
if (!$row) {
phpcommon\sendError(ERR_USER_BASE + 1, '没有这个玩家');
return;
} else {
$signorder = $row['signorder'];
$boxorder = $row['boxorder'];
$diaorder = $row['diaorder'];
$seaorder = $row['seaorder'];
$signtime = $row['signtime'];
$boxtime = $row['boxtime'];
$diatime = $row['diatime'];
$seatime = $row['seatime'];
if ($type == 1) {
$signorder = $accept;
$signtime = time();
} else if ($type == 2){
$boxorder = $accept;
$boxtime = time();
} else if ($type == 3){
$diaorder = $accept;
$diatime = time();
} else if ($type == 4){
$seaorder = $accept;
$seatime = time();
}
$ret = $conn->execScript('UPDATE subscribe SET signtime=:signtime, boxtime=:boxtime, diatime=:diatime, seatime=:seatime, signorder=:signorder, boxorder=:boxorder, diaorder=:diaorder, seaorder=:seaorder ' .
' WHERE accountid=:accountid; ',
array(
':accountid' => $account_id,
':signtime' => $signtime,
':boxtime' => $boxtime,
':diatime' => $diatime,
':seatime' => $seatime,
':signorder' => $signorder,
':boxorder' => $boxorder,
':diaorder' => $diaorder,
':seaorder' => $seaorder,
));
if (!$ret) {
die();
return;
}
}
echo json_encode(array(
'errcode' => 0,
'errmsg' => '',
));
}
public function getOrderInfo()
{
$account_id = $_REQUEST['account_id'];
$conn = $this->getMysql($account_id);
if (!$conn) {
phpcommon\sendError(ERR_USER_BASE + 1, '没有这个玩家');
return;
}
$row = $conn->execQueryOne('SELECT * FROM subscribe WHERE accountid=:accountid;',
array(
':accountid' => $account_id,
));
if (!$row) {
$ret = $conn->execScript('INSERT INTO subscribe(accountid, channel, gameid, openid, signorder, boxorder, diaorder, seaorder, signtime, boxtime, diatime, seatime) ' .
' VALUES(:accountid, :channel, :gameid, :openid, 0, 0, 0, 0, 0, 0, 0, 0) ' .
' ON DUPLICATE KEY UPDATE accountid=:accountid, channel=:channel, gameid=:gameid, openid=:openid, signorder=0, boxorder=0, diaorder=0, seaorder=0, signtime=0, boxtime=0, diatime=0, seatime=0;',
array(
':accountid' => $account_id,
':channel' => phpcommon\extractChannel($account_id),
':gameid' => phpcommon\extractGameId($account_id),
':openid' => phpcommon\extractOpenId($account_id),
));
if (!$ret) {
die();
return;
}
echo json_encode(array(
'errcode' => 0,
'errmsg' => '',
'signorder' => 0,
'boxorder' => 0,
'diaorder' => 0,
'seaorder' => 0,
));
} else {
echo json_encode(array(
'errcode' => 0,
'errmsg' => '',
'signorder' => $row['signorder'],
'boxorder' => $row['boxorder'],
'diaorder' => $row['diaorder'],
'seaorder' => $row['seaorder'],
));
}
}
}