CustomService.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: Bear
  5. * Date: 2018/11/29
  6. * Time: 下午5:49
  7. */
  8. namespace app\main\service;
  9. use app\admin\model\Custom;
  10. use app\admin\model\CustomUrl;
  11. use app\common\constants\BigData;
  12. use app\common\constants\Message;
  13. use app\common\constants\ShortUrl;
  14. use app\common\library\Redis;
  15. use app\common\model\CustomQrcode;
  16. use app\main\constants\ApiConstants;
  17. use app\main\constants\CustomConstants;
  18. use app\main\constants\ErrorCodeConstants;
  19. use app\main\helper\ArrayHelper;
  20. use function GuzzleHttp\Psr7\parse_query;
  21. use think\Config;
  22. class CustomService extends BaseService
  23. {
  24. /**
  25. * @var CustomService
  26. */
  27. protected static $self = NULL;
  28. /**
  29. * @return CustomService
  30. */
  31. public static function instance()
  32. {
  33. if (self::$self == NULL) {
  34. self::$self = new self();
  35. }
  36. return self::$self;
  37. }
  38. /**
  39. * @return \think\Model
  40. */
  41. public function getCustomQrcodeModel()
  42. {
  43. return new CustomQrcode();
  44. }
  45. /**
  46. * @return \think\Model
  47. */
  48. public function getCustomModel()
  49. {
  50. return new Custom;
  51. }
  52. /**
  53. * @return \think\Model
  54. */
  55. public function getCustomUrlModel()
  56. {
  57. return new CustomUrl;
  58. }
  59. /**
  60. * @return \think\Model
  61. */
  62. public function getShortUrlModel() {
  63. return model("ShortUrl");
  64. }
  65. /**
  66. * 检查ext参数是客服消息
  67. * @param $ext
  68. * @return \app\main\model\object\ReturnObject
  69. */
  70. public function checkExtIsCustom($ext = '')
  71. {
  72. if (!$ext) {
  73. $ext = UserService::instance()->getUserInfo()->ext;
  74. }
  75. if ($ext) {
  76. $ext_json = json_decode($ext, true);
  77. if ($ext_json &&
  78. array_key_exists('mark', $ext_json) &&
  79. in_array($ext_json['mark'], [BigData::BIG_DATA_MARK_IMAGE_TEXT, BigData::BIG_DATA_MARK_LINK])
  80. ) {
  81. return $this->setData(true)->getReturn();
  82. }
  83. }
  84. return $this->setData(false)->getReturn();
  85. }
  86. /**
  87. * 返回最后一条发送成功的客服消息的资源
  88. * @param $adminId
  89. * @param $appid
  90. * @return array
  91. */
  92. public function getLastSendSuccessCustom($adminId, $appid)
  93. {
  94. $result = [];
  95. $redisKey = 'CTC:'.$adminId;
  96. if (Redis::instance()->exists($redisKey)) {
  97. $result = json_decode(Redis::instance()->get($redisKey), true);
  98. } else {
  99. //48小时
  100. $model = $this->getCustomModel()
  101. ->where('admin_id', $adminId)
  102. ->where('sendtime', '>=', time()-3600*24*2)
  103. ->where('statue', 'eq', 'hidden')
  104. ->order("sendtime desc")
  105. ->find();
  106. $replace = [];
  107. if (!empty($model)) {
  108. $content = '';
  109. if ($model['message_type'] == Message::MESSAGE_TYPE_IMAGE_TEXT) {
  110. //图文
  111. $content = $model['message_json'];
  112. } elseif ($model['message_type'] == Message::MESSAGE_TYPE_LINK) {
  113. //文字
  114. $content = $model['message_text'];
  115. }
  116. if (empty($content) || is_array($content)) {
  117. Redis::instance()->set($redisKey, json_encode([]), 600);
  118. return [];
  119. }
  120. $shortIds = [];
  121. if (preg_match_all("|j\\\/(\d+)|", $content, $m)) {
  122. $shortIds = $m[1];
  123. } else if (preg_match_all("|/j/(\d+)|", $content, $m)) {
  124. $shortIds = $m[1];
  125. } else {
  126. Redis::instance()->set($redisKey, json_encode([]), 600);
  127. return [];
  128. }
  129. $shortUrlHost = Config::get("site.short_url_host");
  130. if (empty($shortUrlHost)) {
  131. //取渠道业务域名
  132. $shortUrlHost = trim(getCurrentDomain($adminId, null, [], true),'/');
  133. }
  134. $maps['id'] = ['in', $shortIds];
  135. $rows = $this->getShortUrlModel()->where($maps)->select();
  136. foreach ($rows as $index => $row) {
  137. $goUrl = sprintf('%s/%s/%s', $shortUrlHost, ShortUrl::SHORT_URL_PATH, $row['id']);
  138. $url = $row['url'];
  139. $parse = parse_url($url);
  140. $host = $parse['host'] ?? '';
  141. $path = $parse['path'] ?? '';
  142. if (preg_match('/^' . $appid . '/', $host)) {
  143. if (array_key_exists('query', $parse)) {
  144. $query = parse_query($parse['query']);
  145. if (!empty($query)) {
  146. if (array_key_exists('book_id', $query)) {
  147. $replace = [
  148. 'book_id' => $query['book_id'],
  149. 'url' => $goUrl,
  150. ];
  151. break;
  152. } elseif (array_key_exists('t', $query)) {
  153. $replace = [
  154. 'book_id' => '',
  155. 'url' => $goUrl,
  156. 'referral_id' => $query['t'],
  157. ];
  158. break;
  159. }
  160. }
  161. }
  162. if (!empty($path)) {
  163. $path = explode('/', $parse['path']);
  164. if ($keyIndex = array_search('t', $path)) {
  165. $push_id = $path[$keyIndex+1];
  166. $replace = [
  167. 'book_id' => '',
  168. 'url' => $goUrl,
  169. 'referral_id' => $push_id,
  170. ];
  171. break;
  172. }
  173. }
  174. }
  175. }
  176. if (!empty($replace)) {
  177. $replace['custom_id'] = $model['id'];
  178. //查询小说标题
  179. if (isset($replace['referral_id']) && $replace['referral_id']) {
  180. $referralinfo = model('referral')->getone($replace['referral_id'], false);
  181. if (empty($referralinfo) || !$referralinfo['book_id']) {
  182. Redis::instance()->set($redisKey, json_encode([]), 600);
  183. return [];
  184. }
  185. $replace['book_id'] = $referralinfo['book_id'];
  186. }
  187. $bookinfo = BookService::instance()->getBookModel()->BookInfo($replace['book_id']);
  188. if ($bookinfo['state'] == '0') {
  189. //下架
  190. Redis::instance()->set($redisKey, json_encode([]), 600);
  191. return [];
  192. } else if ($bookinfo['state'] == '-1') {
  193. //入库
  194. if ($bookinfo['cansee'] == '0') {
  195. //不可见
  196. Redis::instance()->set($redisKey, json_encode([]), 600);
  197. return [];
  198. }
  199. }
  200. $replace['book_name'] = $bookinfo['name'];
  201. $replace['image'] = $bookinfo['image'];
  202. $replace['description'] = $bookinfo['description'];
  203. //占位符替换
  204. if (strpos($url, '{$ophost}')) {
  205. //占位符转换
  206. $replace['url'] = UrlService::instance()->replaceReferralHost($adminId, $replace['url'], false)->data;
  207. }
  208. }
  209. }
  210. Redis::instance()->set($redisKey, json_encode($replace), 600);
  211. $result = $replace;
  212. }
  213. return $result;
  214. }
  215. public function getCustomUserJson($params)
  216. {
  217. $user_json = [];
  218. if (isset($params['sub_from']) && isset($params['sub_to'])) {
  219. $params['sub_from'] = strtotime($params['sub_from']);
  220. $params['sub_to'] = strtotime($params['sub_to']);
  221. if ($params['sub_from'] >= $params['sub_to']) {
  222. return $this->setCode(ErrorCodeConstants::PARAMS_ERROR_INVALID)->setMsg('结束时间不得小于开始时间');
  223. }
  224. if(isset($params['user_json'])){
  225. $user_json = json_decode($params['user_json'], true);
  226. }
  227. $user_json['subscirbe_range'] = $params['sub_from'] . '-' . $params['sub_to'];
  228. }
  229. $user_json = json_encode($user_json, JSON_UNESCAPED_UNICODE);
  230. return $this->setData($user_json)->getReturn();
  231. }
  232. /**
  233. * 获取满足条件的客服消息id列表
  234. * @param $where
  235. * @param $map
  236. * @param int $offset
  237. * @param int $limit
  238. * @return \app\main\model\object\ReturnObject
  239. */
  240. public function getCustomIds($where, $map, $offset = 0, $limit = 20)
  241. {
  242. $result = [];
  243. $result['total'] = model('custom')
  244. ->join('custom_url', 'custom_url.custom_id=custom.id')
  245. ->join('admin', 'custom_url.official_account_id=admin.id')
  246. ->where($where)
  247. ->where($map)
  248. ->group('custom.id')
  249. ->count();
  250. $result['ids'] = model('custom')
  251. ->join('custom_url', 'custom_url.custom_id=custom.id')
  252. ->join('admin', 'custom_url.official_account_id=admin.id')
  253. ->where($where)
  254. ->where($map)
  255. ->limit($offset, $limit)
  256. ->group('custom.id')
  257. ->order('custom.id', 'desc')
  258. ->column('custom.id');
  259. return $this->setData($result)->getReturn();
  260. }
  261. /**
  262. * 获取客服消息统计信息
  263. * @param $customIds
  264. * @return \app\main\model\object\ReturnObject
  265. */
  266. public function getCustomCollectData($customIds)
  267. {
  268. $customList = model('custom')
  269. ->alias('c')
  270. ->whereIn('c.id', $customIds)
  271. ->join('admin a', 'c.admin_id=a.id')
  272. ->order('custom.id', 'desc')
  273. ->column('c.id,c.title,a.nickname,a.username,c.sendtime,c.send_num');
  274. $customCollect = model('custom_url')
  275. ->alias('cu')
  276. ->join('custom_url_collect cuc', 'cu.custom_id=cuc.custom_id AND cu.idx=cuc.idx', 'LEFT')
  277. ->whereIn('cu.custom_id', $customIds)
  278. ->order('idx', 'asc')
  279. ->column('cu.id,cu.title,cu.custom_id,cu.idx,cu.type,cu.book_id,cu.book_name,cuc.uv,cuc.recharge_money,cu.official_account_name');
  280. foreach ($customList as $index => $item) {
  281. $customList[$index]['collect'] = [];
  282. }
  283. if (VisitLimitService::instance()->checkMigrated()) {
  284. $result = ApiService::instance()->getCollectFromApi(ApiConstants::API_CUSTOM, ['ids' => array_keys($customList)])->data;
  285. $collectList = [];
  286. if ($result) {
  287. foreach ($result as $index=>$item) {
  288. $collectList[$item['cuId']][$item['idx']] = [
  289. 'uv' => $item['uv'],
  290. 'day_uv' => $item['uvDay'],
  291. 'recharge_money' => $item['money'],
  292. 'day_recharge_money' => $item['moneyDay'],
  293. ];
  294. }
  295. }
  296. $default = [
  297. 'uv' => 0,
  298. 'day_uv' => 0,
  299. 'recharge_money' => 0,
  300. 'day_recharge_money' => 0,
  301. ];
  302. foreach ($customCollect as $id=>$item) {
  303. if ($find = ArrayHelper::array_find($collectList, $item['custom_id'] . '.' . $item['idx'])) {
  304. $item = array_merge($item, $find);
  305. } else {
  306. $item = array_merge($item, $default);
  307. }
  308. $customList[$item['custom_id']]['collect'][] = $item;
  309. }
  310. } else {
  311. foreach ($customCollect as $item) {
  312. $item['day_uv'] = intval(Redis::instance()->get(CustomConstants::getCustomUvToDayKey($item['custom_id'], $item['idx'])));
  313. $item['day_recharge_money'] = floatval(Redis::instance()->get(CustomConstants::getCustomRechargeMoneyToDayKey($item['custom_id'], $item['idx'])));
  314. $item['uv'] = (float)$item['uv'];
  315. $item['recharge_money'] = (float)$item['recharge_money'];
  316. $customList[$item['custom_id']]['collect'][] = $item;
  317. }
  318. }
  319. $customList = array_values($customList);
  320. return $this->setData($customList)->getReturn();
  321. }
  322. }