Templatemessage.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466
  1. <?php
  2. namespace app\admin\controller;
  3. use app\admin\service\ExclusiveService;
  4. use app\common\constants\BigData;
  5. use app\common\controller\Backend;
  6. use app\common\library\WeChatObject;
  7. use app\main\constants\TemplateMsgConstants;
  8. use app\main\service\TemplateService;
  9. use app\main\service\UrlService;
  10. use app\main\service\VisitLimitService;
  11. use EasyWeChat\Factory;
  12. use EasyWeChat\OfficialAccount\TemplateMessage\Client;
  13. use think\Config;
  14. use app\common\library\Redis;
  15. use Symfony\Component\Cache\Simple\RedisCache;
  16. use app\main\constants\AdminConstants;
  17. /**
  18. * 模板消息
  19. *
  20. * @icon fa fa-circle-o
  21. */
  22. class Templatemessage extends Backend
  23. {
  24. /**
  25. * Templatemessage模型对象
  26. */
  27. protected $model = null;
  28. public function _initialize()
  29. {
  30. parent::_initialize();
  31. $this->model = model('Templatemessage');
  32. $this->view->assign("statueList", $this->model->getStatueList());
  33. $this->assign('admin_id', $this->auth->id);
  34. $this->assignconfig('admin_id', $this->auth->id);
  35. }
  36. public function index()
  37. {
  38. //设置过滤方法
  39. $this->request->filter(['strip_tags']);
  40. $this->assignconfig('nowtime',time());
  41. if ($this->request->isAjax()) {
  42. list($where, $sort, $order, $offset, $limit) = $this->buildparams();
  43. $total = $this->model
  44. ->join('template_collect', 'templatemessage.id = template_collect.templetemessage_id', 'left')
  45. ->field('templatemessage.*, template_collect.pv, template_collect.uv, template_collect.recharge_orders, template_collect.recharge_money')
  46. ->where($where)
  47. ->where('admin_id','in',$this->auth->id)
  48. ->order('templatemessage.'.$sort, $order)
  49. ->count();
  50. $list = $this->model
  51. ->join('template_collect', 'templatemessage.id = template_collect.templetemessage_id', 'left')
  52. ->field('templatemessage.*, template_collect.pv, template_collect.uv, template_collect.recharge_orders, template_collect.recharge_money')
  53. ->where($where)
  54. ->where('admin_id','in',$this->auth->id)
  55. ->order('templatemessage.'.$sort, $order)
  56. ->limit($offset, $limit)
  57. ->select();
  58. if (VisitLimitService::instance()->checkMigrated()) {
  59. $ids = array_column($list, 'id');
  60. $collectList = TemplateService::instance()->getMigratedCollectAnalysis($ids)->data;
  61. foreach ($list as $index => $item) {
  62. if (array_key_exists($item['id'], $collectList)) {
  63. $list[$index]['uv'] = $collectList[$item['id']]['uv'];
  64. $list[$index]['recharge_money'] = $collectList[$item['id']]['recharge_money'];
  65. $list[$index]['day_uv'] = $collectList[$item['id']]['day_uv'];
  66. $list[$index]['day_money'] = $collectList[$item['id']]['day_recharge_money'];
  67. } else {
  68. $list[$index]['uv'] = 0;
  69. $list[$index]['recharge_money'] = 0;
  70. $list[$index]['day_uv'] = 0;
  71. $list[$index]['day_money'] = 0;
  72. }
  73. }
  74. } else {
  75. $redis = Redis::instance();
  76. foreach($list as $item){
  77. $item['day_uv'] = intval($redis->get(TemplateMsgConstants::getTemplateUvToDayKey($item['id'])));
  78. $item['day_money'] = floatval($redis->get(TemplateMsgConstants::getTemplateRechargeMoneyToDayKey($item['id'])));
  79. if(empty($item['recharge_money'])){
  80. $item['recharge_money'] = '0.00';
  81. }
  82. if(empty($item['day_money'])){
  83. $item['day_money'] = '0.00';
  84. }
  85. }
  86. }
  87. $result = array("total" => $total, "rows" => $list);
  88. return json($result);
  89. }
  90. return $this->view->fetch();
  91. }
  92. //测试发送模板消息
  93. public function sent()
  94. {
  95. // refresh_token adminConfig表获取
  96. $admin_id = $this->auth->id;
  97. $user_id = $_POST['user_id'];
  98. if (preg_match("/\d+/i", $user_id, $matches)) {
  99. if(!empty($matches)){
  100. if(empty($matches)){
  101. //没有匹配到数字。错误
  102. return json(['errcode' => 1, 'errmsg' => '无法匹配到此用户']);
  103. }else{
  104. $user_id = intval($matches[0]);
  105. }
  106. }
  107. } else {
  108. //没有匹配到数组,错误
  109. return json(['errcode' => 1, 'errmsg' => '无法匹配到此用户']);
  110. }
  111. $user = model('User')->setConnect($user_id)->where('id', $user_id)->find();
  112. if (!$user) {
  113. return json(['errcode' => 1, 'errmsg' => '无此用户']);
  114. }
  115. $openid = $user->openid;
  116. $Config = model('AdminConfig')->getAdminInfoAll($admin_id); //where('admin_id', '=', $admin_id)->find();
  117. $wechat = new WeChatObject($Config);
  118. $officialAccount = $wechat->getOfficialAccount();
  119. $user_nickname = $user->nickname;
  120. $user_id = $user->id;
  121. $user_vip_endtime = $user->vip_endtime;
  122. $df_config = $Config;
  123. $wx_nickname = $df_config['json']['authorizer_info']['nick_name'] ?: $df_config['json']['authorizer_info']['user_name'];
  124. $book_name = '';
  125. $redis = Redis::instance();
  126. $key = 'U-R:'.$user_id;
  127. if($redis->exists($key)){
  128. $readkey = $redis->zrevrange($key,0,1);
  129. $book_name = $redis->hget($readkey[0],'chapter_name');
  130. }
  131. $message = json_decode($_POST['message_html'],true);
  132. $message_json['touser'] = '{$openid}';
  133. $message_json['template_id'] = $_POST['template_id'];
  134. $message_json['url'] = trim($_POST['url']);
  135. $message_json['data'] = [];
  136. foreach ($message as $v){
  137. foreach ($v as $value){
  138. if((preg_match ("/^[a-z]/i", $value['key'])) && !empty($value['fieldname'])){
  139. $value['fieldname'] = stripslashes($value['fieldname']);
  140. $value['fieldname'] = preg_replace("/\">(.*?)<\/strong>/",'',$value['fieldname']);
  141. $value['fieldname'] = str_replace('</strong>','',$value['fieldname']);
  142. $value['fieldname'] = str_replace('">','',$value['fieldname']);
  143. $value['fieldname'] = str_replace('&nbsp;','',$value['fieldname']);
  144. $value['fieldname'] = str_replace('<strong contenteditable="false" data-key="','',$value['fieldname']);
  145. $value['fieldname'] = str_replace('$user_nickname',$user_nickname,$value['fieldname']);
  146. $value['fieldname'] = str_replace('$user_id',$user_id,$value['fieldname']);
  147. if(!empty($user_vip_endtime)){$value['fieldname'] = str_replace('$user_vip_endtime',$user_vip_endtime,$value['fieldname']);}else{
  148. $value['fieldname'] = str_replace('$user_vip_endtime','',$value['fieldname']);
  149. }
  150. $value['fieldname'] = str_replace('$wx_nickname',$wx_nickname,$value['fieldname']);
  151. $value['fieldname'] = str_replace('$book_name',$book_name,$value['fieldname']);
  152. $message_json['data'][$value['key']] = ['color'=>$value['color'],'value'=>$value['fieldname']];
  153. }
  154. }
  155. }
  156. $message_json['touser']= $openid;
  157. $send_res = $officialAccount->template_message->send($message_json);
  158. if($send_res['errcode'] == 40037){
  159. $send_res['errmsg'] = '模板ID无效,请到公众号后台检查该模板是否存在';
  160. }
  161. return json($send_res);
  162. }
  163. /*
  164. * 创建新模板
  165. */
  166. // public function WeChatTemplate()
  167. // {
  168. // $openPlatform = Factory::openPlatform(Config::get('wechat'));
  169. // $openPlatform['cache'] = new RedisCache(Redis::instanceCache());
  170. // $Config = model('AdminConfig')->where('admin_id', '=', $this->auth->id)->find();
  171. // $officialAccount = $openPlatform->officialAccount($Config->appid, $Config->refresh_token);
  172. // $getIndustry = $officialAccount->template_message->getIndustry();
  173. // $getIndustry = array_values($getIndustry);
  174. //
  175. // if (empty($getIndustry[0]['first_class']) && empty($getIndustry[1]['first_class'])) {
  176. // $officialAccount->template_message->setIndustry(37, 2);
  177. // $officialAccount->template_message->addTemplate('TM00009');
  178. // $officialAccount->template_message->addTemplate('TM405959619');
  179. // }
  180. //
  181. // $this->getTemplate();
  182. // }
  183. /*
  184. *获取远程模板
  185. */
  186. public function getTemplate()
  187. {
  188. $Config = model('AdminConfig')->getAdminInfoAll($this->auth->id);
  189. $wechat = new WeChatObject($Config);
  190. $officialAccount = $wechat->getOfficialAccount();
  191. $tmps = $officialAccount->template_message->getPrivateTemplates();
  192. model('templatelist')->where(array('admin_id' => $this->auth->id))->delete();
  193. if (!empty($tmps['template_list'])) {
  194. foreach ($tmps['template_list'] as &$value) {
  195. $value['admin_id'] = $this->auth->id;
  196. }
  197. if (model('templatelist')->saveall($tmps['template_list'])) {
  198. return $tmps['template_list'];
  199. }
  200. }
  201. }
  202. //
  203. public function add()
  204. {
  205. if ($this->request->isPost()) {
  206. $row = $this->request->post('row/a');
  207. if(isset($row['sub_from'])){
  208. unset($row['sub_from']);
  209. }
  210. if(isset($row['sub_to'])){
  211. unset($row['sub_to']);
  212. }
  213. if (strtotime($row['sendtime']) < time()) {
  214. $this->error('发送时间不能小于当前时间');
  215. }
  216. unset($row['type']);
  217. $url = UrlService::instance()->replaceReferralHost($this->getCurrentAccountChannelId(), $row['url'])->data;
  218. $row['url'] = trim($url);
  219. $tmp_row = $row;
  220. $row['message_json'] = UrlService::instance()->replaceReferralHost($this->getCurrentAccountChannelId(), $this->message_json($row))->data;
  221. // $this->error(json_encode($row,JSON_UNESCAPED_UNICODE));
  222. if ($row) {
  223. $templatemessage = new \app\admin\model\Templatemessage();
  224. $templatemessage->save($row);
  225. $id = $templatemessage->id;
  226. $tmp_row['url'] = $this->_appendUrlExt($url, BigData::BIG_DATA_TEMPLATE_MSG, strtotime($row['sendtime']), $id);
  227. $tmp_row['message_json'] = UrlService::instance()->replaceReferralHost($this->getCurrentAccountChannelId(), $this->message_json($tmp_row))->data;
  228. $this->model->update(
  229. [
  230. 'url' => $tmp_row['url'],
  231. 'message_json' => $tmp_row['message_json'],
  232. ],
  233. ['id' => $id]
  234. );
  235. $this->success();
  236. }
  237. $this->error();
  238. }
  239. return $this->view->fetch();
  240. }
  241. /**
  242. * 追加打点信息到URL
  243. * @param $url
  244. * @param $mark
  245. * @param $sendTime
  246. * @param $push_id
  247. * @return string
  248. */
  249. private function _appendUrlExt($url, $mark, $sendTime, $push_id)
  250. {
  251. $url = trim($url);
  252. $ext = [
  253. 'mark' => $mark,
  254. 'push_time' => $sendTime,
  255. 'push_id' => $push_id,
  256. ];
  257. $strExt = json_encode($ext);
  258. if (strpos($url, '?') === false) {
  259. $url .= '?ext=' . $strExt;
  260. } else {
  261. $url .= '&ext=' . $strExt;
  262. }
  263. return $url;
  264. }
  265. /*
  266. * 模板列表
  267. * @param w=1 远程获取模板
  268. */
  269. public function ajaxtmp()
  270. {
  271. $tmps = [];
  272. if(intval(input('w'))){
  273. $tmps = $this->getTemplate();
  274. }
  275. if(empty($tmps)){
  276. $tmps = model('templatelist')->field('id,template_id,title,content')->where(array('admin_id' => $this->auth->id))->select();
  277. }
  278. if (empty($tmps)) {
  279. return json(['error' => -1, 'msg' => '模板数据未创建,请点击刷新模板列表']);
  280. }
  281. foreach ($tmps as &$value) {
  282. $value['content'] = str_replace('{', '#', $value['content']);
  283. $value['content'] = str_replace('}', '#', $value['content']);
  284. $value['content'] = str_replace('.DATA', '', $value['content']);
  285. $value['content'] = str_replace(':', '#', $value['content']);
  286. $value['content'] = str_replace('##', '#', $value['content']);
  287. $contentArr = explode('<br />',nl2br($value['content']));
  288. $fieldListArr = [];
  289. foreach ($contentArr as $k =>$text) {
  290. $text = trim($text);
  291. if (strlen($text) > 0) {
  292. $keywordArr = explode('#',$text);
  293. foreach ($keywordArr as $key =>$keywordArrValue){
  294. $keywordArrValue = trim($keywordArrValue);
  295. $field = [];
  296. if (strlen(trim($keywordArrValue)) > 0) {
  297. if(preg_match ("/^[a-z]/i", $keywordArrValue)){
  298. $field['fieldname'] = '';
  299. $field['key'] = $keywordArrValue;
  300. $field['color'] = '#000000';
  301. }else{
  302. $field['fieldname'] = $keywordArrValue.':';
  303. $field['key'] = $keywordArrValue. ':';
  304. $field['color'] = '';
  305. }
  306. $keywordArr[$key]= $field;
  307. }else{
  308. unset($keywordArr[$key]);
  309. }
  310. }
  311. $fieldListArr[] = array_values($keywordArr);
  312. }
  313. }
  314. $value['content'] = array_values($fieldListArr);
  315. }
  316. $return['error'] = 0;
  317. $return['msg'] = '请求成功.';
  318. $return['data'] = $tmps;
  319. return json_encode($return, JSON_UNESCAPED_UNICODE);
  320. }
  321. public function edit($ids=null){
  322. $canEdit = 0;
  323. $row = $this->model->get($ids);
  324. if (!$row)
  325. $this->error(__('No Results were found'));
  326. if($row['sendtime'] <= time()){
  327. $canEdit = 1;
  328. }
  329. if($row['sendtime'] > time() && $row['sendtime']-time() <= 600){
  330. $canEdit = 1;
  331. }
  332. //解析占位符
  333. $row['message_json'] = UrlService::instance()->replaceReferralHost($this->getCurrentAccountChannelId(), $row['message_json'], false)->data;
  334. $row['url'] = UrlService::instance()->replaceReferralHost($this->getCurrentAccountChannelId(), $row['url'], false)->data;
  335. if ($this->request->isAjax())
  336. {
  337. $params = $this->request->post("row/a");
  338. if ($params)
  339. {
  340. unset($row['type']);
  341. if(isset($params['sub_from'])){
  342. unset($params['sub_from']);
  343. }
  344. if(isset($params['sub_to'])){
  345. unset($params['sub_to']);
  346. }
  347. $params['url'] = UrlService::instance()->replaceReferralHost($this->getCurrentAccountChannelId(), $params['url'])->data;
  348. $params['url'] = trim($this->_appendUrlExt($params['url'], BigData::BIG_DATA_TEMPLATE_MSG, $row['sendtime'], $ids));
  349. $params['message_json'] = UrlService::instance()->replaceReferralHost($this->getCurrentAccountChannelId(), $this->message_json($params))->data;
  350. try
  351. {
  352. //是否采用模型验证
  353. if ($this->modelValidate)
  354. {
  355. $name = basename(str_replace('\\', '/', get_class($this->model)));
  356. $validate = is_bool($this->modelValidate) ? ($this->modelSceneValidate ? $name . '.edit' : true) : $this->modelValidate;
  357. $row->validate($validate);
  358. }
  359. $result = $row->allowField(true)->save($params);
  360. if ($result !== false)
  361. {
  362. $this->success();
  363. }
  364. else
  365. {
  366. $this->error($row->getError());
  367. }
  368. }
  369. catch (\think\exception\PDOException $e)
  370. {
  371. $this->error($e->getMessage());
  372. }
  373. }
  374. $this->error(__('Parameter %s can not be empty', ''));
  375. }
  376. $row['sendtime'] = date('Y-m-d H:i:s',$row['sendtime']);
  377. //获取独家书籍id
  378. $bnotin= [];
  379. ExclusiveService::instance()->getExclusiveNotidsWithoutWhere($this->group, $this->auth->id,$bnotin);
  380. $this->assignconfig('bnotin', $bnotin);
  381. $this->assign("canedit",$canEdit);
  382. $json = json_decode($row['user_json'], true);
  383. $from = $to = '';
  384. if ($json['all'] == 0 && !$json['subscribe_time'] && $json['subscribe_range']) {
  385. list($from, $to) = explode('-', $json['subscribe_range']);
  386. if($from == 'NaN'){
  387. $from = '';
  388. }
  389. if($to == 'NaN'){
  390. $to = '';
  391. }
  392. if($from){
  393. $from = date('Y-m-d H:i:s', $from);
  394. }
  395. if($to){
  396. $to = date('Y-m-d H:i:s', $to);
  397. }
  398. }
  399. $this->view->assign('from', $from);
  400. $this->view->assign('to', $to);
  401. $this->view->assign("row", $row);
  402. return $this->view->fetch();
  403. }
  404. /*
  405. * 处理message_json返回的数据
  406. */
  407. public function message_json($row){
  408. $message = json_decode($row['message_html'],true);
  409. $message_json['touser'] = '{$openid}';
  410. $message_json['template_id'] = $row['template_id'];
  411. $message_json['url'] = trim($row['url']);
  412. $message_json['data'] = [];
  413. foreach ($message as $v){
  414. foreach ($v as $value){
  415. if((preg_match ("/^[a-z]/i", $value['key'])) && !empty($value['fieldname'])){
  416. $value['fieldname'] = stripslashes($value['fieldname']);
  417. $value['fieldname'] = preg_replace("/\">(.*?)<\/strong>/",'',$value['fieldname']);
  418. $value['fieldname'] = str_replace('</strong>','',$value['fieldname']);
  419. $value['fieldname'] = str_replace('">','',$value['fieldname']);
  420. $value['fieldname'] = str_replace('&nbsp;','',$value['fieldname']);
  421. $value['fieldname'] = str_replace('<strong contenteditable="false" data-key="','',$value['fieldname']);
  422. $message_json['data'][$value['key']] = ['color'=>$value['color'],'value'=>$value['fieldname']];
  423. }
  424. }
  425. }
  426. return json_encode($message_json);
  427. }
  428. }