push.php 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125
  1. <?php
  2. defined('IN_WEB') or die('Include Error!');
  3. /**
  4. * 信鸽推送相关
  5. */
  6. class ModelPush{
  7. //定义安卓和苹果的sid列表
  8. private $_andriod_sid_list = [1,3,5,7,9,11,13];
  9. private $_ios_sid_list = [2]; //[2,4,6,8,10,12,14]
  10. private $_secretInfo = array(//1 安卓, 2 IOS, 3 繁体安卓, 4繁体苹果, 5英语安卓, 6英语苹果, 7 奥马哈安卓 , 8 奥马哈苹果, 9 安卓主包, 10 IOS主包
  11. 1 => array(
  12. 'accessId' => 2100261272,
  13. 'accessKey' => 'AM2X5RW58G1Y',
  14. 'secretKey' => '8c398daf1d21bd82b5dce7c5b3fc827c',
  15. ),
  16. 2 => array(
  17. 'accessId' => 2200261278,
  18. 'accessKey' => 'I7M9P63E6HFG',
  19. 'secretKey' => 'cadb5e71d82d36f1724b72e2e640ae9f',
  20. ),
  21. 3 => array(
  22. 'accessId' => 2100275920,
  23. 'accessKey' => 'AW45I8V5IH6P',
  24. 'secretKey' => 'e42a5548ceee8cd4f7e25ba529b3c5d0',
  25. ),
  26. 4 => array(
  27. 'accessId' => 2200275921,
  28. 'accessKey' => 'IY1EW9C842KB',
  29. 'secretKey' => '8b223ff44fc9f81e76347dcd3271a383',
  30. ),
  31. 5 => array(
  32. 'accessId' => 2100275923,
  33. 'accessKey' => 'A72Y37VAYL1E',
  34. 'secretKey' => 'c2f28a374a74ad09a7be9e659f9ce2aa',
  35. ),
  36. 6 => array(
  37. 'accessId' => 2200275924,
  38. 'accessKey' => 'IW4H68U9FM2G',
  39. 'secretKey' => '773b4e0198bc71d0f8af0269d0391a9b',
  40. ),
  41. 7 => array(
  42. 'accessId' => 2100278390,
  43. 'accessKey' => 'A1B8GI9Y5P7C',
  44. 'secretKey' => '884cdfd614afe4900d72b531b043da4d',
  45. ),
  46. 8 => array(
  47. 'accessId' => 2200278391,
  48. 'accessKey' => 'I85FG1TH36MB',
  49. 'secretKey' => 'f8830313cf646c77c652ec737c575f27',
  50. ),
  51. 9 => array(
  52. 'accessId' => 2100278549,
  53. 'accessKey' => 'A718VKKJ7N9F',
  54. 'secretKey' => '31955700823e92dda1b5e375de71c45d',
  55. ),
  56. 10 => array(
  57. 'accessId' => 2200278550,
  58. 'accessKey' => 'IMZ7X9K627MB',
  59. 'secretKey' => '6dee06eb4bbd4dfcdef30ca199988d14',
  60. ),
  61. 11 => array(
  62. 'accessId' => 2100278561,
  63. 'accessKey' => 'AND65V648VQM',
  64. 'secretKey' => 'e7d90b7c6a5dc1cd97e21e29c8df0a51',
  65. ),
  66. 12 => array(
  67. 'accessId' => 2200278562,
  68. 'accessKey' => 'I335MWG3E7KR',
  69. 'secretKey' => '10e6f492889b0fb3439d21950538bd27',
  70. ),
  71. 13 => array(
  72. 'accessId' => 2100279187,
  73. 'accessKey' => 'ANK2XX6M869P',
  74. 'secretKey' => 'd3e3cb309c205d8990bab60a641a1995',
  75. ),
  76. 14 => array(
  77. 'accessId' => 2200279190,
  78. 'accessKey' => 'IS32S15YG8SD',
  79. 'secretKey' => '8e5a3457eb2642b5252c25fb1b667331',
  80. ),
  81. 17 => array(
  82. 'accessId' => 2100295942,
  83. 'accessKey' => 'AV57B1J73YKH',
  84. 'secretKey' => '48d6a245fbfac2955fa6f61b09bdebc0',
  85. ),
  86. 19 => array(
  87. 'accessId' => 2100301866,
  88. 'accessKey' => 'ATQ53K9RL42Q',
  89. 'secretKey' => '2bf618f4fbb186b840eb1e7f23780b9b',
  90. ),
  91. 20 => array(
  92. 'accessId' => 2200298948,
  93. 'accessKey' => 'I4EF2537CLHK',
  94. 'secretKey' => '1f89fae1ea69ee62f3ee77c8a3d1ec49',
  95. )
  96. );
  97. private $_accessId = 0;
  98. private $_secretKey = 0;
  99. static $xingeApp = '';
  100. public function __construct()
  101. {
  102. $info = $this->_secretInfo[1] ?? $this->_secretInfo[9];
  103. $this->_accessId = $info['accessId'];
  104. $this->_secretKey = $info['secretKey'];
  105. }
  106. /**
  107. * 初始化
  108. */
  109. protected function initFile($device){
  110. include_once(PATH_LIB.'xg/XingeApp.php');
  111. $info = $this->_secretInfo[$device] ?? $this->_secretInfo[9];
  112. $this->_accessId = $info['accessId'];
  113. $this->_secretKey = $info['secretKey'];
  114. }
  115. /**
  116. * Notes:获取推送配置
  117. * User: wsc
  118. * Time: 2020/11/11 9:40
  119. * @param bool $db
  120. * @return array
  121. */
  122. public function getPushConf($db=false){
  123. $key = okeys::fasebasePushConf();
  124. $cache =oo::commonOprRedis('config')->hGetAll($key);
  125. if(empty($cache)||$db){
  126. $tb = otable::fasebasePushConf();
  127. $sql = "SELECT * FROM {$tb}";
  128. $arr = oo::commonOprDb('config')->getAll($sql,1);
  129. if(!empty($arr)){
  130. foreach ($arr as $v){
  131. $v['conf'] = json_decode($v['conf'],true);
  132. $cache[$v['id']] = json_encode($v,256);
  133. }
  134. oo::commonOprRedis('config')->hMset($key,$cache);
  135. }
  136. }
  137. $cache = $cache?funs::getArrFromJsonArr($cache):[];
  138. return $cache;
  139. }
  140. /**
  141. * 不入队立即给单个玩家推送消息
  142. * 国内只有在玩家登录游戏切换到后台时候才能收到推送
  143. * @param $uid
  144. * @param $title
  145. * @param $content
  146. * @param array $argument
  147. * @param string $type
  148. * @return array|int
  149. * Created by: Owen
  150. * Created on: 2020/7/4 16:58
  151. */
  152. public function pushNewsToOne($uid, $title, $content, $argument = array(),$type = ''){
  153. $pushLock = oo::commonOprModel('member')->getUserSettingLock($uid);
  154. if(!empty($pushLock)){
  155. if(in_array('ALL',$pushLock)){
  156. return -100;
  157. }
  158. if(($type == "steal" || $type == "attack") && in_array('stealAndAttack',$pushLock)){
  159. return -100;
  160. }
  161. }
  162. $ret = $this->getPushTokenByUid($uid);
  163. if( $ret <= -1 ){
  164. return -100;
  165. }
  166. $token = $ret['token'];
  167. $sid = $ret['sid'];
  168. $ret = $this->pushNewsSingle($title, $content, $token, $sid, $argument);
  169. return $ret;
  170. }
  171. /**
  172. * 入队给单个玩家推送消息
  173. * 国内只有在玩家登录游戏切换到后台时候才能收到推送
  174. * @param $uid
  175. * @param $titleKey
  176. * @param $contentKey
  177. * @param array $langArg
  178. * @param string $type
  179. * @param array $pushArg
  180. * @return array|int
  181. * Created by: Owen
  182. * Created on: 2020/7/4 17:06
  183. */
  184. public function pushNews($uid,$titleKey,$contentKey,$langArg = [],$type = '',$pushArg = []){
  185. $pushLock = oo::commonOprModel('member')->getUserSettingLock($uid);
  186. if(!empty($pushLock)){
  187. if(in_array('ALL',$pushLock)){
  188. return -100;
  189. }
  190. if(($type == "steal" || $type == "attack") && in_array('stealAndAttack',$pushLock)){
  191. return -100;
  192. }
  193. }
  194. $ret = $this->getPushTokenByUid($uid);
  195. if( $ret <= -1 ||$ret['token']=='BLACKLISTED'){
  196. return -100;
  197. }
  198. $token = $ret['token'];
  199. $lang = $ret['lang']?strtolower($ret['lang']):'en';
  200. $sid = $ret['sid']??1;
  201. $title = oo::commonOprModel('lang')->getLang($lang,$titleKey);
  202. $content = oo::commonOprModel('lang')->getLang($lang,$contentKey,$langArg);
  203. $label = explode('.',$titleKey);
  204. $label = end($label);
  205. $img = "";
  206. $pushCfg = $this->getPushConf();
  207. $id = 0;
  208. foreach ($pushCfg as $row){
  209. if($row['class'] == "other" && $row['type'] == $label){
  210. if(!empty($row['conf'][$lang]["title"])){
  211. $title = $row['conf'][$lang]["title"];
  212. $content = $row['conf'][$lang]["content"];
  213. $id = $row['id'];
  214. if(!empty($langArg) && is_array($langArg)){
  215. foreach ($langArg as $key=>$row){
  216. $content = str_replace("{{$key}}",$row,$content);
  217. }
  218. }
  219. break;
  220. }
  221. }
  222. }
  223. if(in_array($id,[16])){
  224. $img = "https://spin.gworldtek.com/public/game/image/firebase/{$id}.jpg";
  225. }
  226. $ret = self::push($token,$title,$content,$pushArg,$sid,$label,$img);
  227. return $ret;
  228. }
  229. /**
  230. * Notes:根据消息id推送消息
  231. * User: wsc
  232. * Time: 2020/11/9 12:01
  233. * @param $nid int 需要推送的消息id
  234. * @param array $uidList 需要推送的玩家列表
  235. * @param array $pushArg 额外参数
  236. * @return array|int
  237. */
  238. public function pushNewsByNid($nid,$uidList=[],$pushArg = []){
  239. $ret = [];
  240. if(empty($uidList)){
  241. return -100;
  242. }
  243. $pushCfg = $this->getPushConf();
  244. $uInfos = $this->getPushTokenByUid($uidList);
  245. if(empty($uInfos)||!is_array($uInfos)){
  246. return -99;
  247. }
  248. $uInfos = array_column($uInfos,null,'uid');
  249. if(!empty($uInfos)&&!empty($pushCfg[$nid])){
  250. foreach ($uidList as $uid){
  251. if(!isset($uInfos[$uid]['token'])){
  252. continue;
  253. }
  254. $lang = $uInfos[$uid]['lang']??'en';
  255. $token = $uInfos[$uid]['token'];
  256. $title = $pushCfg[$nid]['conf'][$lang]['title'];
  257. $content = $pushCfg[$nid]['conf'][$lang]['content'];
  258. $sid = $ret['sid']??1;
  259. $ret[$uid] = self::push($token,$title,$content,$pushArg,$sid,"activity");
  260. }
  261. }
  262. return $ret;
  263. }
  264. public function pushNewsToMultUserLang($uidList = array(), $title, $content){
  265. $count = count($uidList);
  266. $p = 100;
  267. $pages = ceil($count/$p);
  268. for ($i = 1; $i <= $pages; $i++) {
  269. $s = ($i-1)*$p;
  270. $tempArr = array_slice($uidList, $s , $p);
  271. $tokenList = self::getPushMultByUids($tempArr);
  272. if (!$tokenList) {
  273. continue;
  274. }
  275. foreach ($tokenList as $tokenArr) {
  276. if(isset($title[$tokenArr['lang']])){
  277. $titleTemp = $title[$tokenArr['lang']];
  278. }else{
  279. $titleTemp = $title['en'];
  280. }
  281. if(isset($content[$tokenArr['lang']])){
  282. $contentTemp = $content[$tokenArr['lang']];
  283. }else{
  284. $contentTemp = $content['en'];
  285. }
  286. oo::commonOprModel('firebase')->sendToDevice($tokenArr['token'], $titleTemp, $contentTemp);
  287. }
  288. }
  289. return 1;
  290. }
  291. /**
  292. * 给单个玩家推送消息
  293. * 只有在玩家登录游戏时候才能收到推送
  294. */
  295. public function pushNewsSingle($title, $content, $token, $sid, $argument = array())
  296. {
  297. $ret = oo::commonOprModel('firebase')->sendToDevice($token, $title, $content, $argument);
  298. return $ret;
  299. }
  300. /**
  301. * 给多个玩家推送
  302. */
  303. public function pushNewsToMultUser($uidList = array(), $title, $content)
  304. {
  305. if (!is_array($uidList)) {
  306. return -1;
  307. }
  308. include_once(PATH_LIB.'xg/XingeApp.php');
  309. $count = count($uidList);
  310. $p = 20;
  311. $pages = ceil($count/$p);
  312. for ($i = 1; $i <= $pages; $i++) {
  313. $s = ($i-1)*$p;
  314. $tempArr = array_slice($uidList, $s , $p);
  315. $tokenList = $this->getPushMultTokenByUids($tempArr);
  316. if (empty($tokenList) || $tokenList < 0) {
  317. continue;
  318. }
  319. foreach ($tokenList as $sid => $tokenArr) {
  320. foreach ($tokenArr as $t) {
  321. oo::commonOprModel('firebase')->sendToDevice($t, $title, $content);
  322. }
  323. }
  324. }
  325. return 1;
  326. }
  327. /**
  328. * 根据账号类型和设备发送推送
  329. * $deviceType 1 安卓 2 苹果
  330. * $accountType 1 游客 0 FB
  331. */
  332. public function pushNewsToMultUserByAccount($deviceType = 1, $accountType = 1, $title, $content)
  333. {
  334. $this->initFile($deviceType);
  335. $table = otable::xg_push();
  336. $sql = " SELECT COUNT(uid) AS c FROM {$table} WHERE sid = {$deviceType} AND token != '0' ";
  337. $ret = oo::commonOprDb('common')->getOne($sql, 1);
  338. $count = intval($ret['c']);
  339. if( $count <= 0 ){
  340. return;
  341. }
  342. $limit = 30;
  343. $pages = ceil($count / $limit);
  344. for ($i = 1; $i <= $pages; $i++) {
  345. $page = ($i -1) * $limit;
  346. $sqlList = " SELECT uid, token FROM {$table} WHERE sid = {$deviceType} AND token != '0' LIMIT {$page}, {$limit} ";
  347. $list = oo::commonOprDb('common')->getAll($sqlList, 1);
  348. if (empty($list)) {
  349. continue;
  350. }
  351. //循环处理
  352. foreach ($list as $info) {
  353. $uid = $info['uid'];
  354. $token = $info['token'];
  355. $isVisitor = oo::commonOprModel('member')->isVistor($uid);
  356. if ($isVisitor != $accountType && $accountType != 2) {//账号类型不匹配
  357. continue;
  358. }
  359. oo::commonOprModel('firebase')->sendToDevice($token, $title, $content);
  360. }
  361. }
  362. }
  363. /**
  364. * 根据语言推送
  365. * @param int $deviceType
  366. * @param int $accountType
  367. * @param $title
  368. * @param $content
  369. * Created by: Owen
  370. * Created on: 2019/12/19 16:03
  371. */
  372. public function pushNewsToMultUserByAccountLang($deviceType = 1, $accountType = 1, $title, $content){
  373. $this->initFile($deviceType);
  374. $table = otable::xg_push();
  375. $sql = " SELECT COUNT(uid) AS c FROM {$table} WHERE sid = {$deviceType} AND token != '0' ";
  376. $ret = oo::commonOprDb('common')->getOne($sql, 1);
  377. $count = intval($ret['c']);
  378. if( $count <= 0 ){
  379. return;
  380. }
  381. $limit = 30;
  382. $pages = ceil($count / $limit);
  383. for ($i = 1; $i <= $pages; $i++) {
  384. $page = ($i -1) * $limit;
  385. $sqlList = " SELECT * FROM {$table} WHERE sid = {$deviceType} AND token != '0' LIMIT {$page}, {$limit} ";
  386. $list = oo::commonOprDb('common')->getAll($sqlList, 1);
  387. if (empty($list)) {
  388. continue;
  389. }
  390. //循环处理
  391. foreach ($list as $info) {
  392. $uid = $info['uid'];
  393. $token = $info['token'];
  394. $lang = $info['lang'];
  395. $isVisitor = oo::commonOprModel('member')->isVistor($uid);
  396. if ($isVisitor != $accountType && $accountType != 2) {//账号类型不匹配
  397. continue;
  398. }
  399. if(isset($title[$lang])){
  400. $title = $title[$lang];
  401. }else{
  402. $title = $title['en'];
  403. }
  404. if(isset($content[$lang])){
  405. $content = $content[$lang];
  406. }else{
  407. $content = $content['en'];
  408. }
  409. oo::commonOprModel('firebase')->sendToDevice($token, $title, $content);
  410. }
  411. }
  412. }
  413. /**
  414. * 之前全部推送泰语的
  415. * 每日自动推送兑换码
  416. * 每日9:30 和 12:30
  417. */
  418. public function autoPushExchangeOld()
  419. {
  420. $money = 15000;
  421. $limit = 1000;
  422. $day = 1;
  423. $ret = oo::commonOprModel('exchangecode')->createCode($money, $limit, $day, 1, 1);
  424. $arr = json_decode($ret, 1);
  425. if( $arr['code'] != 1 ){
  426. oo::logs()->todebug(array('ret' => $ret), 'autoPushExchangeErr.log');
  427. }
  428. $code = $arr['num'];//兑换码
  429. $titleArr = oo::getLang('exchange_pushTitle');//标题
  430. $contentArr = oo::getLang('exchange_pushContent');//内容数组
  431. $randNum = array_rand($contentArr);
  432. $title = $titleArr[$randNum];
  433. $content = $contentArr[$randNum];
  434. $content = str_replace('@', $code, $content);
  435. //推送
  436. include_once(PATH_LIB.'xg/XingeApp.php');
  437. $android_accessId = $this->_secretInfo[9]['accessId'];
  438. $android_secretKey = $this->_secretInfo[9]['secretKey'];
  439. $ios_accessId = $this->_secretInfo[2]['accessId'];
  440. $ios_secretKey = $this->_secretInfo[2]['secretKey'];
  441. $androidold_accessId = $this->_secretInfo[1]['accessId'];
  442. $androidold_secretKey = $this->_secretInfo[1]['secretKey'];
  443. XingeApp::PushAllAndroid($android_accessId, $android_secretKey, $title, $content, array('type' => 3, 'code' => $code));
  444. XingeApp::PushAllAndroid($androidold_accessId, $androidold_secretKey, $title, $content, array('type' => 3, 'code' => $code));
  445. XingeApp::PushAllIos($ios_accessId, $ios_secretKey, $content, XingeApp::IOSENV_PROD, array('type' => 3, 'code' => $code));
  446. oo::logs()->todebug(array('code' => $code), 'autoPushExchangeSuc.log');
  447. }
  448. /**
  449. * 后台自动推送
  450. */
  451. public function autpPushNewsToAll()
  452. {
  453. $key = 'AUTOPUSHNEWSTOALL';
  454. $ret = oo::commonOprRedis('common')->lPop($key);
  455. if (empty($ret)) {
  456. return;
  457. }
  458. $info = json_decode($ret, 1);
  459. //list($devicetype, $accounttype, $title, $content) = $info;
  460. $devicetype = $info['devicetype'];
  461. $accounttype = $info['accounttype'];
  462. $title = $info['title'];
  463. $content = $info['content'];
  464. oo::logs()->debug3(array('devicetype' => $devicetype, 'accounttype' => $accounttype,'title' => $title, 'content' => $content), 'pushNewsToMultUserByAccount.log');
  465. $this->pushNewsToMultUserByAccount($devicetype, $accounttype, $title, $content);
  466. }
  467. /**
  468. * 通过UID获取推送的token
  469. */
  470. public function getPushTokenByUid($uids = 0){
  471. $table = otable::xg_push();
  472. $ret =[];
  473. if(is_array($uids)){
  474. $uidsStr =implode(',',$uids);
  475. $sql = "SELECT * FROM {$table} WHERE uid in({$uidsStr})";
  476. $ret = oo::commonOprDb('common')->getAll($sql, 1);
  477. }else if($uids>0){
  478. $sql = "SELECT * FROM {$table} WHERE uid={$uids} LIMIT 1";
  479. $ret = oo::commonOprDb('common')->getOne($sql, 1);
  480. }
  481. if( empty($ret) ){
  482. return -1;
  483. }
  484. return $ret;
  485. }
  486. /**
  487. * 获取多个token
  488. */
  489. public function getPushMultTokenByUids($uidList = array(), $flag = 1)
  490. {
  491. if(empty($uidList) || !is_array($uidList)){
  492. return false;
  493. }
  494. $uidStr = implode(',', $uidList);
  495. $table = otable::xg_push();
  496. $sql = " SELECT token, sid FROM {$table} WHERE uid IN ({$uidStr}) ";
  497. $ret = oo::commonOprDb('common')->getAll($sql, 1);
  498. if( empty($ret) ){
  499. return -1;
  500. }
  501. $list = array();
  502. foreach ($ret as $value) {
  503. if(empty($value['token'])){
  504. continue;
  505. }
  506. $sid = $value['sid'];
  507. if($flag == 2){
  508. $list[] = $value['token'];
  509. }else{
  510. $list[$sid][] = $value['token'];
  511. }
  512. }
  513. return $list;
  514. }
  515. /**
  516. * 获取多个用户信息
  517. * @param array $uidList
  518. * @return array|bool
  519. * Created by: Owen
  520. * Created on: 2019/12/19 15:53
  521. */
  522. public function getPushMultByUids($uidList = array())
  523. {
  524. if(empty($uidList) || !is_array($uidList)){
  525. return false;
  526. }
  527. $uidStr = implode(',', $uidList);
  528. $table = otable::xg_push();
  529. $sql = " SELECT * FROM {$table} WHERE uid IN ({$uidStr}) ";
  530. $ret = oo::commonOprDb('common')->getAll($sql, MYSQLI_ASSOC);
  531. if(empty($ret) ){
  532. return false;
  533. }
  534. $list = array();
  535. foreach ($ret as $value) {
  536. $list[] = [
  537. 'uid' => $value['uid'],
  538. 'token'=> $value['token'],
  539. 'lang' => $value['lang'],
  540. 'topic'=> $value['topic'],
  541. 'accountType'=> $value['accountType'],
  542. ];
  543. }
  544. return $list;
  545. }
  546. /**
  547. * 给所有IOS设备发送推送
  548. */
  549. public function pushAllIosDevice($content)
  550. {
  551. //推送
  552. include_once(PATH_LIB.'xg/XingeApp.php');
  553. $ios_accessId = $this->_secretInfo[2]['accessId'];
  554. $ios_secretKey = $this->_secretInfo[2]['secretKey'];
  555. $ret = XingeApp::PushAllIos($ios_accessId, $ios_secretKey, $content, XingeApp::IOSENV_PROD);
  556. return $ret;
  557. }
  558. /**
  559. * 给android设备推送信息
  560. */
  561. public function pushAllAndroidDevice($title, $content)
  562. {
  563. //推送
  564. include_once(PATH_LIB.'xg/XingeApp.php');
  565. $android_accessId = $this->_secretInfo[1]['accessId'];
  566. $android_secretKey = $this->_secretInfo[1]['secretKey'];
  567. $ret = XingeApp::PushAllAndroid($android_accessId, $android_secretKey, $title, $content);
  568. return $ret;
  569. }
  570. /**
  571. * 老用户召回
  572. */
  573. public function recallbackuser()
  574. {
  575. $key = 'XGRECALLBACK';
  576. $info = oo::commonOprRedis('recall')->lPop($key);
  577. //$info = oo::commonOprRedis('recall')->lGetRange($key, 0, -1);
  578. if (empty($info)) {
  579. return false;
  580. }
  581. $arr = json_decode($info, 1);
  582. if (!is_array($arr)) {
  583. return false;
  584. }
  585. $id = $arr['id'];//表id
  586. $day = $arr['day'];//流失天数
  587. $title = $arr['title'];//推送标题
  588. $conent = $arr['conent'];//推送内容
  589. $devices = $arr['devices'];//推送设备
  590. $losetime = strtotime('-'.$day.' days');//流失时间
  591. //计算推送人数
  592. $table = otable::xg_push();
  593. $sqlSum = " SELECT COUNT(uid) AS s FROM {$table} ";
  594. $sumRs = oo::commonOprDb('common')->getOne($sqlSum, 1);
  595. $sum = intval($sumRs['s']);
  596. if ($sum <= 0) {
  597. return false;
  598. }
  599. //修改召回状态
  600. $pushTable = otable::recallback_push();//召回表
  601. $updatstatussql = " UPDATE {$pushTable} SET status = 2 WHERE id = {$id} LIMIT 1";
  602. oo::commonOprDb('common')->query($updatstatussql);
  603. $where = " WHERE sid IN ($devices) ";
  604. $page = 20;
  605. $pages = ceil($sum/$page);
  606. //统计发送玩家总数
  607. $pushNum = 0;
  608. for ($i=1; $i <= $pages; $i++) {
  609. $start = ($i - 1)*$page;
  610. $sql = "SELECT uid, token FROM {$table} {$where} LIMIT $start, $page";
  611. $list = oo::commonOprDb('common')->getAll($sql, 1);
  612. $uidList = array();
  613. foreach ($list as $tempVal) {
  614. array_push($uidList, $tempVal['uid']);
  615. }
  616. $userinfo = array();
  617. $userInfoRs = oo::commonOprModel('member')->getUserInfoMulti(array('keylist' => $uidList), $userinfo);
  618. //查询流失玩家
  619. if ($userInfoRs != 1) {
  620. continue;
  621. }
  622. //处理流失玩家
  623. $recallbackUidList = array();
  624. foreach ($userinfo as $tempInfo) {
  625. $lasttime = $tempInfo['lasttime'];
  626. $tempUid = $tempInfo['uid'];
  627. if ($lasttime >= $losetime) {
  628. continue;
  629. }
  630. array_push($recallbackUidList, $tempUid);
  631. }
  632. if (empty($recallbackUidList)) {
  633. continue;
  634. }
  635. $pushNum += count($recallbackUidList);
  636. $this->pushNewsToMultUser($recallbackUidList, $title, $conent);//发送推送
  637. usleep(1000);
  638. }
  639. //更新召回数据库
  640. $endtime = time();
  641. $updateSql = "UPDATE {$pushTable} SET nums = {$pushNum}, status = 1, endtime = {$endtime} WHERE id = {$id} LIMIT 1";
  642. oo::commonOprDb('common')->query($updateSql);
  643. //记录数据库
  644. oo::logs()->debug3(array('id' => $id, 'pushNum' => $pushNum, 'endtime' => $endtime), 'pushRecallback.log');
  645. }
  646. /**
  647. * 更新用户的标签
  648. * @param $uid
  649. * @return array|bool
  650. */
  651. public function refreshTag($uid, $lang)
  652. {
  653. if(empty($uid)) {
  654. return false;
  655. }
  656. $ret = $this->getPushTokenByUid($uid);
  657. if($ret <= -1) {
  658. return false;
  659. }
  660. $sid = $ret['sid'];
  661. $tag = $sid.'-'.$lang;
  662. $token = $ret['token'];
  663. $res = $this->refreshTagByToken($tag, $token, $sid);
  664. return $res;
  665. }
  666. /**
  667. * 查询该token是否有标签
  668. * 1.如果有,判断是否和该传入标签一样。一样则不处理,否则删除存在的不一样的,写入当前传入标签
  669. * 2.没有,直接写入
  670. * @param $tag
  671. * @param $token
  672. * @return array
  673. */
  674. public function refreshTagByToken($tag, $token, $sid = 0)
  675. {
  676. if($sid) {
  677. $this->initFile($sid);
  678. }
  679. include_once(PATH_LIB.'xg/XingeApp.php');
  680. $push = new XingeApp($this->_accessId, $this->_secretKey);
  681. //查询当前token下的标签
  682. $ret = $push->QueryTokenTags($token);
  683. $existTag = false;
  684. if($ret['ret_code'] == 0 && !empty($ret['result'])) {
  685. $tokenPairList = [];
  686. foreach ($ret['result']['tags'] as $tv) {
  687. if($tv != $tag){
  688. $tokenPairsDel = new TagTokenPair($tv, $token);
  689. array_push($tokenPairList, $tokenPairsDel);
  690. }else {
  691. $existTag = true;
  692. }
  693. }
  694. if(!empty($tokenPairList)) {
  695. //批量删除其他标签
  696. $ret = $push->BatchDelTag($tokenPairList);//删除该token下的标签
  697. oo::logs()->nodatedebug($tv.'resdel:'.json_encode($ret));
  698. }
  699. }
  700. if(!$existTag) {
  701. $tokenPairsSet = new TagTokenPair($tag, $token);
  702. $setTag = $push->BatchSetTag([$tokenPairsSet]);
  703. if($setTag['ret_code'] == 0) {
  704. return oo::res(1);
  705. }
  706. return oo::res(-1);
  707. }else {
  708. return oo::res(1);
  709. }
  710. }
  711. /**
  712. * 查询token下的标签
  713. * @param $token
  714. * @return array|mixed
  715. */
  716. public function QueryTokenTags($token, $sid=0)
  717. {
  718. if($sid) {
  719. $this->initFile($sid);
  720. }
  721. //推送
  722. include_once(PATH_LIB.'xg/XingeApp.php');
  723. $push = new XingeApp($this->_accessId, $this->_secretKey);
  724. $ret = $push->QueryTokenTags($token);
  725. return $ret;
  726. }
  727. /**
  728. * 推送所有安卓该语言的玩家
  729. * @param $lang
  730. * @param $message
  731. * @return bool
  732. */
  733. public function pushAllAndroidByLang($lang, $title, $content, $argument=array())
  734. {
  735. include_once(PATH_LIB.'xg/XingeApp.php');
  736. $sidList = $this->_andriod_sid_list;
  737. foreach ($sidList as $sid){
  738. $this->initFile($sid);
  739. $tag = $sid.'-'.$lang;
  740. //推送
  741. $ret = XingeApp::PushTagAndroid($this->_accessId, $this->_secretKey, $title, $content, $tag, $argument );
  742. if($ret['ret_code'] != 0) {
  743. oo::logs()->debug3('pushByTags: tag:'.$tag.' sid:'.$sid.' ret:'.json_encode($ret), 'pushtag_error.php');
  744. }
  745. }
  746. //firebase推送
  747. $topic = 'lang_'.$lang;
  748. $res = oo::commonOprModel('firebase')-> sendToTopic($topic, $title, $content, $argument);
  749. return true;
  750. }
  751. /**
  752. * 推送所有苹果该语言的玩家
  753. * @param $lang
  754. * @param $message
  755. * @return bool
  756. */
  757. public function pushAllIosByLang($lang, $title, $content, $argument=array())
  758. {
  759. $sidList = $this->_ios_sid_list;
  760. foreach ($sidList as $sid){
  761. $this->initFile($sid);
  762. $tag = $sid.'-'.$lang;
  763. //推送
  764. $ret = XingeApp::PushTagIos($this->_accessId, $this->_secretKey, $content, $tag, 1, $argument);
  765. if($ret['ret_code'] != 0) {
  766. oo::logs()->debug3('pushByTags: tag:'.$tag.' sid:'.$sid.' ret:'.json_encode($ret), 'pushtag_error.php');
  767. }
  768. }
  769. return true;
  770. }
  771. /**
  772. * 安卓按标签推送
  773. * @param $sid
  774. * @param $lang
  775. * @param $title
  776. * @param $content
  777. * @param array $argument
  778. */
  779. public function pushAndroidByTag($sid, $lang, $title, $content, $argument=array())
  780. {
  781. $this->initFile($sid);
  782. $tag = $sid.'-'.$lang;
  783. //推送
  784. $ret = XingeApp::PushTagAndroid($this->_accessId, $this->_secretKey, $title, $content, $tag, $argument );
  785. if($ret['ret_code'] != 0) {
  786. oo::logs()->debug3('pushByTags: tag:'.$tag.' sid:'.$sid.' ret:'.json_encode($ret), 'pushtag_error.php');
  787. }
  788. }
  789. /**
  790. * 苹果按标签推送
  791. * @param $sid
  792. * @param $lang
  793. * @param $content
  794. * @param array $argument
  795. */
  796. public function pushIosByTag($sid, $lang, $content, $argument=array())
  797. {
  798. $this->initFile($sid);
  799. $tag = $sid.'-'.$lang;
  800. //推送
  801. $ret = XingeApp::PushTagIos($this->_accessId, $this->_secretKey, $content, $tag, 1, $argument);
  802. if($ret['ret_code'] != 0) {
  803. oo::logs()->debug3('pushByTags: tag:'.$tag.' sid:'.$sid.' ret:'.json_encode($ret), 'pushtag_error.php');
  804. }
  805. }
  806. /**
  807. * 根据语言推送
  808. * @param $titleKey
  809. * @param $contentKey
  810. * @param array $extraData
  811. * Created by: Owen
  812. * Created on: 2020/7/6 11:07
  813. */
  814. public function pushByLang($titleKey, $contentKey,$extraData = []){
  815. $titleConfig = oo::commonOprModel('lang')->getAllLang($titleKey);
  816. $contentConfig = oo::commonOprModel('lang')->getAllLang($contentKey);
  817. foreach ($titleConfig as $lang=>$value){
  818. oo::commonOprModel('firebase')->sendToTopic(okeys::FireBaseTopic($lang), $value, $contentConfig[$lang],$extraData);
  819. }
  820. }
  821. /**
  822. * 根据订阅主题推送
  823. * @param int $deviceType
  824. * @param int $accountType
  825. * @param $title
  826. * @param $content
  827. * Created by: Owen
  828. * Created on: 2020/3/23 15:13
  829. */
  830. public function pushByTopicClassLang($deviceType = 1, $accountType = 1, $title, $content){
  831. $table = otable::xg_push();
  832. $firebaseTopic = okeys::FireBaseTopic();
  833. $sql = "SELECT COUNT(uid) AS c FROM {$table} WHERE topic LIKE '%{$firebaseTopic}%' AND token != '0' AND sid={$deviceType}";
  834. if($accountType != 2){
  835. $sql .= " AND accountType={$accountType}";
  836. }
  837. $ret = oo::commonOprDb('common')->getOne($sql, 1);
  838. $count = intval($ret['c']);
  839. if( $count <= 0 ){
  840. return;
  841. }
  842. if($count != 1){
  843. return;
  844. }
  845. $limit = 100;
  846. $pages = ceil($count / $limit);
  847. for ($i = 1; $i <= $pages; $i++) {
  848. $page = ($i -1) * $limit;
  849. $sqlList = "SELECT * FROM {$table} WHERE topic LIKE '%{$firebaseTopic}%' AND sid = {$deviceType} AND token != '0'";
  850. if($accountType != 2){
  851. $sqlList .= " AND accountType={$accountType}";
  852. }
  853. $sqlList .=" LIMIT {$page}, {$limit} ";
  854. $list = oo::commonOprDb('common')->getAll($sqlList, 1);
  855. if (empty($list)) {
  856. continue;
  857. }
  858. $push = [];
  859. foreach ($list as $info) {
  860. $push[$info['lang']][] = $info['token'];
  861. }
  862. foreach ($push as $key=>$row){
  863. if(isset($title[$key])){
  864. $title = $title[$key];
  865. }else{
  866. $title = $title['en'];
  867. }
  868. if(isset($content[$key])){
  869. $content = $content[$key];
  870. }else{
  871. $content = $content['en'];
  872. }
  873. foreach ($row as $token){
  874. oo::commonOprModel('firebase')->sendToDevice($token, $title, $content);
  875. }
  876. }
  877. }
  878. }
  879. /**
  880. * 推送入队
  881. * @param $token
  882. * @param $title
  883. * @param $content
  884. * @param $data
  885. * @param $sid
  886. * @return bool
  887. * Created by: Owen
  888. * Created on: 2020/3/23 16:18
  889. */
  890. public function push($token,$title,$content,$data = [],$sid = 1,$label = "",$img = ""){
  891. if(strlen($token) < 100){
  892. return false;
  893. }
  894. return oo::commonOprRedis('common')->rpush(okeys::FireBaseList(),json_encode([
  895. 'token' => $token,
  896. 'title' => $title,
  897. 'content' => $content,
  898. 'data' => $data,
  899. 'sid' => $sid,
  900. 'label' => $label,
  901. 'img' => $img,
  902. ]));
  903. }
  904. /**
  905. * 推送出队
  906. * @param int $length
  907. * @return array
  908. * Created by: Owen
  909. * Created on: 2020/3/23 14:55
  910. */
  911. public function pop($length = 500){
  912. $key = okeys::FireBaseList();
  913. $ret = oo::commonOprRedis('common')->lGetRange($key,0,$length);
  914. $return = [];
  915. foreach ($ret as $row){
  916. $return[] = json_decode($row,true);
  917. }
  918. oo::commonOprRedis('common')->lTrim($key,$length,-1);
  919. return $return;
  920. }
  921. /**
  922. * 定时推送
  923. * Created by: Owen
  924. * Created on: 2020/3/23 16:17
  925. */
  926. public function fireBasePushByRedisList(){
  927. $ret = self::pop();
  928. $path = "FireBasePush/".date('Ymd').'/';
  929. foreach ($ret as $row){
  930. try{
  931. oo::commonOprModel('firebase')->sendToDevice($row['token'], $row['title'], $row['content'], $row['data']??[],$row['sid']??1);
  932. }catch (Exception $exception){
  933. oo::logs()->debug5(['message'=>$exception->getMessage(),"time"=>time()],'FireBasePush.log',$path);
  934. continue;
  935. }
  936. }
  937. }
  938. /**
  939. * 排行榜活动Firebase推送
  940. * @return bool
  941. * Created by: Owen
  942. * Created on: 2020/7/4 18:57
  943. */
  944. public function rankFirebasePush(){
  945. if(oo::commonOprRedis('Activity')->get(okeys::ActivityRankPushLock("PUSH")) && !oo::commonOprRedis('Activity')->get(okeys::ActivityRankPushLock("PUSHED"))){
  946. $activity = oo::commonOprRedis('common')->hGetAll(okeys::Activity());
  947. if(empty($activity)){
  948. return false;
  949. }
  950. $isOnLine = false;
  951. $activityName = "";
  952. foreach ($activity as $key=>$row) {
  953. $temp = explode('#', $key);
  954. if ($temp[0] == 13) {
  955. $temp = json_decode($row,true);
  956. if(time() < $temp['reward_time']){
  957. return false;
  958. }
  959. $isOnLine = true;
  960. $activityName = $temp['activityName'];
  961. break;
  962. }
  963. }
  964. if(!$isOnLine){
  965. return false;
  966. }
  967. $maxRoomId = oo::commonOprModel('activity')->getRankCurMaxRoomId();
  968. //消息队列推送到不同服务器节点
  969. oo::commonOprModel('workerman')->pushFun('push', 'rankFirebaseCirclePush', [$activityName, $maxRoomId]);
  970. }
  971. }
  972. /**
  973. * 通知当前节点排行榜活动Firebase推送
  974. */
  975. public function rankFirebaseCirclePush($activityName, $maxRoomId){
  976. $online = oo::commonOprModel('workerman')->getAllUidList();
  977. for ($i=1;$i<=$maxRoomId;$i++){
  978. $users = oo::commonOprModel('activity')->getRankRoomUsers($i);
  979. $pushUser = array_diff($users,$online);
  980. foreach ($pushUser as $uid){
  981. if(!oo::commonOprRedis('Activity')->hGet(okeys::RewardedAcRank(),$uid)){
  982. $randId = oo::commonOprModel('activity')->getCurUserRank($uid);
  983. if($randId !== false){
  984. oo::commonOprRedis('Activity')->hSetNx(okeys::ActivityRankPushData(),$uid, $randId + 1)
  985. && !IS_DEBUF && oo::commonOprModel('push')->pushNews($uid, 'push.title.activityRank','push.title.activityRank',[],'',['id'=>3,'content'=>0]);
  986. }
  987. }
  988. }
  989. }
  990. oo::commonOprRedis('Activity')->expire(okeys::ActivityRankPushData(),oo::redisRandomExpire(3*24*60*60));
  991. oo::commonOprRedis('Activity')->setex(okeys::ActivityRankPushLock('activityName'),$activityName,oo::redisRandomExpire(3*24*60*60));
  992. oo::commonOprRedis('Activity')->setex(okeys::ActivityRankPushLock("PUSHED"),1,oo::redisRandomExpire(3*24*60*60));
  993. }
  994. /**
  995. * 新增等级推送
  996. * Created by: Owen
  997. * Created on: 2020/7/29 18:31
  998. */
  999. public function updateCurMaxLevel(){
  1000. if(!IS_DEBUF && oo::commonOprRedis('common')->delete(okeys::UpdateCurMaxLevelPush())){
  1001. $curMaxLevel = oo::commonOprModel('config')->getCurMaxLevel();
  1002. $downLevel = oo::commonOprModel('readconfig')->getSysCon('UpdateMaxLevel','downLevel') ?? 10;
  1003. $actionLevel = max($curMaxLevel - $downLevel,90);
  1004. $tb = otable::gh_gameserver();
  1005. $sql = "SELECT mid FROM {$tb} WHERE levelId > {$actionLevel}";
  1006. $ret = oo::commonOprDb('common')->getAll($sql,MYSQLI_ASSOC);
  1007. if(!empty($ret)){
  1008. $uidArr = implode(',',array_column($ret,'mid'));
  1009. $tb = otable::xg_push();
  1010. $sql = "SELECT * FROM {$tb} WHERE uid IN ({$uidArr})";
  1011. $ret = oo::commonOprDb('common')->getAll($sql,MYSQLI_ASSOC);
  1012. if(!empty($ret)){
  1013. $langContent = oo::commonOprModel('readconfig')->getSysCon('UpdateMaxLevel','push');
  1014. $langContent = json_decode($langContent,true);
  1015. foreach ($ret as $row){
  1016. self::push($row['token'],$langContent[$row['lang']]['title'],$langContent[$row['lang']]['content'],[],$row['sid'],"maxLevel");
  1017. }
  1018. }
  1019. }
  1020. }
  1021. }
  1022. /**
  1023. * 奖励定时推送
  1024. * Created by: Owen
  1025. * Created on: 2021/3/16 15:20
  1026. */
  1027. public function CrontabPush(){
  1028. $pushList = [
  1029. "FreeBar" =>"freeBar",
  1030. "TurnTable"=>"turnTable",
  1031. ];
  1032. foreach ($pushList as $type=>$langKey){
  1033. $ret = oo::commonOprRedis('Usercache')->zRangeByScore(okeys::PushCrontab($type),0,time(),['withscores'=>true]);
  1034. foreach ($ret as $uid=>$time){
  1035. $this->pushNews($uid,"push.title.".$langKey,"push.content.".$langKey,[],$langKey);
  1036. oo::commonOprRedis('Usercache')->zDelete(okeys::PushCrontab($type),$uid);
  1037. }
  1038. }
  1039. }
  1040. public function vipPush(){
  1041. $tb = otable::userinfo();
  1042. $curTime = time();
  1043. $ret = oo::commonOprDb('common')->getAll("SELECT uid FROM {$tb} WHERE vip=1 AND vip_expire>{$curTime}",MYSQLI_ASSOC);
  1044. $uidArr = array_column($ret,"uid");
  1045. foreach ($uidArr as $uid){
  1046. $this->pushNews($uid,"push.title.vip","push.content.vip",[],"vip");
  1047. }
  1048. }
  1049. }
  1050. ?>