HigeMessageService.php 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665
  1. <?php
  2. /**
  3. * 高级群发服务接口
  4. * Created by: PhpStorm
  5. * User: lytian
  6. * Date: 2020/2/21
  7. * Time: 10:55
  8. */
  9. namespace app\main\service;
  10. use app\admin\service\LogService;
  11. use app\admin\service\ShortUrlService;
  12. use app\common\constants\BigData;
  13. use app\common\constants\Common;
  14. use app\common\constants\ErrorCode;
  15. use app\common\constants\Message;
  16. use app\common\library\WeChatObject;
  17. use app\common\model\Activity;
  18. use app\main\constants\ActivityConstants;
  19. use app\main\service\MiniProgramService;
  20. use EasyWeChat\Kernel\Exceptions\InvalidArgumentException;
  21. use EasyWeChat\Kernel\Messages\Article;
  22. use think\Config;
  23. use think\Exception;
  24. use think\Log;
  25. class HigeMessageService extends BaseService
  26. {
  27. protected static $self = null;
  28. private static $adminConfig = [];
  29. private static $wechatObj = [];
  30. private static $imgArr = [];
  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 getUserModel()
  42. {
  43. return model("User");
  44. }
  45. /**
  46. * @return \think\Model
  47. */
  48. public function getAdminConfigModel()
  49. {
  50. return model("AdminConfig");
  51. }
  52. /**
  53. * @return \think\Model
  54. */
  55. public function getSendMessMediaModel()
  56. {
  57. return model("SendMessMedia");
  58. }
  59. /**
  60. * @return \think\Model
  61. */
  62. public function getSendMessageModel()
  63. {
  64. return model("SendMessage");
  65. }
  66. /**
  67. * 图片转换为永久素材
  68. * @param $channelId
  69. * @param $image
  70. * @param bool $isThumb
  71. * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
  72. */
  73. public function image2media($channelId, $image, $isThumb = false)
  74. {
  75. try {
  76. //判断下图片
  77. if (strrpos($image, 'http') !== false) {
  78. //转换成路径
  79. $info = parse_url($image);
  80. $imgPath = trim($info['path'], '/');
  81. } else {
  82. $imgPath = trim($image, '/');
  83. }
  84. $imgPath = ROOT_PATH . 'public/' .$imgPath;
  85. if (!file_exists($imgPath)) {
  86. throw new Exception("图片文件不存在", 201);
  87. }
  88. $officeAccount = $this->getWechatObj($channelId)->getOfficialAccount();
  89. if ($isThumb) {
  90. $res = $officeAccount->material->uploadThumb($imgPath);
  91. } else {
  92. $res = $officeAccount->material->uploadImage($imgPath);
  93. }
  94. if (isset($res['errcode'])) {
  95. Log::error("图文上传失败:res:". json_encode($res, JSON_UNESCAPED_UNICODE) . "channel_id: {$channelId} image: {$image}");
  96. }
  97. return $res;
  98. } catch (Exception | InvalidArgumentException $e) {
  99. Log::error("图片素材处理失败:errormsg: {$e->getMessage()} channel_id: {$channelId} image: {$imgPath}");
  100. return ['errcode' => 201, 'errormsg' => $e->getMessage()];
  101. }
  102. }
  103. /**
  104. * 删除微信历史消息
  105. * @param $channelId
  106. * @param $msgId
  107. * @return array
  108. */
  109. public function delWechatHistoryMessage($channelId,$msgId)
  110. {
  111. try {
  112. $officeAccount = $this->getWechatObj($channelId)->getOfficialAccount();
  113. $res = $officeAccount->broadcasting->delete($msgId);
  114. Log::info('删除微信历史消息'.json_encode($res, JSON_UNESCAPED_UNICODE) . "wx_msg_id: ".$msgId);
  115. if ($res['errmsg'] != 'ok') {
  116. Log::error("删除微信历史消息失败:res:". json_encode($res, JSON_UNESCAPED_UNICODE) . "msgId: {$msgId}");
  117. }
  118. return $res;
  119. }catch (Exception | InvalidArgumentException $e){
  120. Log::error("删除微信历史消息失败:errormsg: {$e->getMessage()} msgId: {$msgId}");
  121. return ['errcode' => 201, 'errormsg' => $e->getMessage()];
  122. }
  123. }
  124. /**
  125. * 创建图文消息
  126. * @param $adminInfo
  127. * @param $data
  128. * @return array|\EasyWeChat\Kernel\Support\Collection|object|\Psr\Http\Message\ResponseInterface|string
  129. * @throws Exception
  130. * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
  131. */
  132. public function uploadNews($channelId, $data)
  133. {
  134. $officeAccount = $this->getWechatObj($channelId)->getOfficialAccount();
  135. $res = $officeAccount->material->uploadArticle($data);
  136. if (isset($res['errcode'])) {
  137. Log::error("图文上传失败:res:". json_encode($res, JSON_UNESCAPED_UNICODE) . "channel_id: {$channelId} data:". json_encode($data, JSON_UNESCAPED_UNICODE));
  138. return $res;
  139. } else {
  140. return $res;
  141. }
  142. }
  143. /**
  144. * 创建媒体库
  145. * @param $adminId
  146. * @param $msgType
  147. * @param $msgContent
  148. * @return int|string
  149. * @throws \Exception
  150. */
  151. public function createMedia($adminId, $msgType, $msgContent)
  152. {
  153. $media = [
  154. 'admin_id' => $adminId,
  155. 'type' => $msgType,
  156. 'createtime' => time(),
  157. 'updatetime' => time(),
  158. ];
  159. if (!Common::isJson($msgContent)) {
  160. throw new \Exception('图文参数不是json格式');
  161. }
  162. //检测是否有null项 有的话清理掉
  163. if (strrpos($msgContent, 'null') !== false) {
  164. $data = json_decode($msgContent, true);
  165. $data = array_filter($data);
  166. $msgContent = json_encode($data);
  167. }
  168. if ($msgType == 1) {
  169. //文本
  170. $media['message_text'] = $msgContent;
  171. } elseif ($msgType == 2) {
  172. //图文
  173. $media['message_json'] = $msgContent;
  174. } elseif ($msgType == 3) {
  175. //图片
  176. $media['message_img'] = $msgContent;
  177. }
  178. $id = $this->getSendMessMediaModel()->allowField(true)->insertGetId($media);
  179. return $id;
  180. }
  181. /**
  182. * 消息预览接口
  183. * @param array $channelIds 测试发送的渠道
  184. * @param int $userId 接收用户id
  185. * @param int $msgType 1 文字 2 图文 3 图片
  186. * @param array $message 消息结构
  187. * @param array $others 其他参数
  188. * @return array
  189. * @throws InvalidArgumentException
  190. * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
  191. * @throws \EasyWeChat\Kernel\Exceptions\RuntimeException
  192. */
  193. public function sent(array $channelIds, int $userId, int $msgType, array $message, array $others = [])
  194. {
  195. if (!$channelIds || !is_array($channelIds)) {
  196. return LogService::toError(ErrorCode::PARAMS_ERROR_INVALID, 'channel_id参数错误');
  197. }
  198. if (!$userId) {
  199. return LogService::toError(ErrorCode::PARAMS_ERROR_INVALID, 'user_id参数错误');
  200. }
  201. if (!$message) {
  202. return LogService::toError(ErrorCode::PARAMS_ERROR_INVALID, '消息内容无效');
  203. }
  204. $success = 0;
  205. try {
  206. $user = $this->getUserModel()->setConnect($userId)->where('id', $userId)->find();
  207. if (!$user) {
  208. return LogService::toError(ErrorCode::DB_ERROR_SELECT, '无效的用户信息');
  209. }
  210. foreach ($channelIds as $channelId) {
  211. //匹配出用户ID
  212. if (preg_match("/\d+/i", $userId, $matches)) {
  213. if (!empty($matches)) {
  214. if (empty($matches)) {
  215. //没有匹配到数字。错误
  216. return LogService::toError(ErrorCode::PARAMS_ERROR_INVALID, '无法匹配到此用户');
  217. } else {
  218. $userId = intval($matches[0]);
  219. }
  220. }
  221. } else {
  222. //没有匹配到数组,错误
  223. return LogService::toError(ErrorCode::PARAMS_ERROR_INVALID, '无法匹配到此用户');
  224. }
  225. if ($user->channel_id != $channelId) {
  226. return LogService::toError(ErrorCode::DB_ERROR_SELECT, '该渠道无法匹配到此用户');
  227. }
  228. $officialAccount = $this->getWechatObj($channelId)->getOfficialAccount();
  229. if (!$officialAccount) {
  230. return LogService::toError(ErrorCode::DB_ERROR_SELECT, '无效的服务号信息');
  231. }
  232. if ($msgType == 1) {
  233. //文字消息
  234. $content = '';
  235. $str_list = [];
  236. foreach ($message as $item) {
  237. if (isset($item['url'])) {
  238. $str = '';
  239. $str .= "<a href=\"" . $item['url'] . "\">";
  240. $str .= $item['content'];
  241. $str .= "</a>";
  242. $str_list[] = $str;
  243. } else {
  244. if (isset($item['page'])){
  245. $item['content'] = MiniProgramService::instance()->getMiniText($item['page'],$item['content'],$channelId);
  246. }
  247. $str_list[] = $item['content'];
  248. }
  249. }
  250. $content = implode("\n", $str_list);
  251. Log::info('高级群发消息content:'.$content);
  252. $res = $officialAccount->broadcasting->previewText($content, $user['openid']);
  253. if (isset($res['errcode']) && $res['errcode'] != 0) {
  254. throw new Exception("高级群发测试发送失败:" . $res['errmsg'], 201);
  255. }
  256. $success++;
  257. } elseif ($msgType == 2) {
  258. //图文消息
  259. $newsCommentData = $newsData = $originData = [];
  260. $messageCount = count($message);
  261. foreach ($message as $k => $item) {
  262. $this->__setMiniBatch($item,$channelId);
  263. $article = [
  264. 'title' => $item['title'],
  265. 'thumb_media_id' => '',
  266. 'digest' => '',
  267. 'auth' => '',
  268. 'show_cover' => 0,
  269. 'content' => $this->parseContentImage($channelId, $item['content']),
  270. 'source_url' => '',
  271. ];
  272. if ($item['cover']) {
  273. $coverResult = $this->image2media($channelId, $item['cover'], 1);
  274. $article['thumb_media_id'] = $coverResult['media_id'];
  275. } else {
  276. throw new Exception("缺少封面图", 201);
  277. }
  278. //if ($messageCount > 1) {
  279. $article['digest'] = (isset($item['digest']) && !empty($item['digest'])) ? $item['digest'] : mb_substr(strip_tags($item['content']),
  280. 0, 64);
  281. //}
  282. $url = '';
  283. if (isset($item['type'])) {
  284. $url = $this->buildUrl($channelId, $item);
  285. if (in_array($item['type'], [1, 3]) && empty($url)) {
  286. return LogService::toError(ErrorCode::DB_ERROR_SELECT, '活动状态失效,请重新配置');
  287. }
  288. }
  289. $article['source_url'] = $url;
  290. $originData[] = $article;
  291. $articleObj = new Article($article);
  292. if ($item['need_open_comment'] == 1) {
  293. $articleObj->need_open_comment = 1;
  294. $articleObj->only_fans_can_comment = $article['only_fans_can_comment'] ?? 0;
  295. }
  296. $newsCommentData[] = $articleObj;
  297. }
  298. $mediaResult = $officialAccount->material->uploadArticle($newsCommentData);
  299. if (!empty($mediaResult['errcode']) && $mediaResult['errcode'] == 88000) {
  300. foreach ($originData as $article) {
  301. $newsData[] = new Article($article);
  302. }
  303. $mediaResult = $officialAccount->material->uploadArticle($newsData);
  304. }
  305. if (isset($mediaResult['media_id'])) {
  306. $mediaId = $mediaResult['media_id'];
  307. $res = $officialAccount->broadcasting->previewNews($mediaId, $user['openid']);
  308. if (isset($res['errcode']) && $res['errcode'] != 0) {
  309. throw new Exception("高级群发测试发送失败:" . $res['errmsg'], 201);
  310. }
  311. } else {
  312. throw new Exception("高级群发测试发送失败:" . $mediaResult['errmsg'], 201);
  313. }
  314. $success++;
  315. } elseif ($msgType == 3) {
  316. //图片消息
  317. $imgPath = current($message);
  318. $mediaResult = $this->image2media($channelId, $imgPath['img_path']);
  319. if (isset($mediaResult['media_id'])) {
  320. $mediaId = $mediaResult['media_id'];
  321. $res = $officialAccount->broadcasting->previewImage($mediaId, $user['openid']);
  322. if (isset($res['errcode']) && $res['errcode'] != 0) {
  323. throw new Exception("高级群发测试发送失败:" . $res['errmsg'], 201);
  324. }
  325. } else {
  326. throw new Exception("高级群发测试发送失败:" . $mediaResult['errmsg'], 201);
  327. }
  328. $success++;
  329. }
  330. }
  331. } catch (Exception $e) {
  332. LogService::error("高级群发:error: {$e->getMessage()} 错误line: {$e->getLine()}");
  333. return LogService::toError(ErrorCode::EXCEPTION, '未知错误');
  334. }
  335. if($success>0){
  336. return LogService::toSuccess(ErrorCode::SUCCESS, '发送完成');
  337. }else{
  338. return LogService::toError(ErrorCode::PARAMS_ERROR_INVALID, '发送失败');
  339. }
  340. }
  341. /**
  342. * 处理内容中的图片
  343. * @param $channelId
  344. * @param $content
  345. * @return mixed
  346. * @throws Exception
  347. * @throws InvalidArgumentException
  348. */
  349. private function parseContentImage($channelId, $content)
  350. {
  351. $imgPaths = [];
  352. if (preg_match_all("/src=['|\"]([^\s]*)['|\"]/i", $content, $m)) {
  353. $imgPaths = $m[1];
  354. }
  355. if ($imgPaths) {
  356. $mediaArr = [];
  357. foreach ($imgPaths as $k => $imgPath) {
  358. // if (is_file($imgPath) && file_exists($imgPath)) {
  359. $res = $this->image2media($channelId, $imgPath);
  360. $mediaArr[$k] = $res['url'];
  361. // }
  362. }
  363. $content = str_replace($imgPaths, $mediaArr, $content);
  364. }
  365. return $content;
  366. }
  367. /**
  368. * 返回链接地址
  369. * @param $channelId
  370. * @param $params
  371. * @return string
  372. */
  373. public function buildUrl($channelId, $params)
  374. {
  375. $type = $params['type'];
  376. $url = '';
  377. switch ($type) {
  378. case 0:
  379. $url = $this->_buildBookUrl($channelId, $params);
  380. break;
  381. case 1:
  382. $url = $this->_buildActivityUrl($channelId, $params);
  383. break;
  384. case 2:
  385. $url = $this->_buildRecentUrl($channelId);
  386. break;
  387. case 3:
  388. $url = $this->_buildCampaignUrl($channelId, $params);
  389. break;
  390. default:
  391. break;
  392. }
  393. return $url;
  394. }
  395. /**
  396. * 处理小程序
  397. */
  398. public function __setMiniBatch(&$item,$channelId)
  399. {
  400. \app\main\service\LogService::info('图文消息-小程序1'.$item['content']);
  401. if (!isset($item['mini']) || empty($item['mini']) ){
  402. return '';
  403. }
  404. $miniContent = $item['mini'];
  405. foreach ($miniContent as $k =>$value){
  406. if ($value['type'] == 3){//小程序卡片
  407. $res = $this->image2media($channelId, $value['pic']);
  408. $value['pic'] = $res['url'];
  409. }
  410. $c = MiniProgramService::instance()->getMiniProgram($value,$channelId);
  411. if ($value['type'] == 4 && $c){//小程序码
  412. $c = '<p><img src=\''.$c.'\'></p>';
  413. }
  414. $item['content'] = str_replace( $value['tag'], $c,$item['content']);
  415. }
  416. // print_r($item['content']);exit;
  417. \app\main\service\LogService::info('图文消息-小程序'.$item['content']);
  418. unset($miniContent);
  419. }
  420. /**
  421. * 根据参数,生成阅读页链接
  422. * @param $channelId
  423. * @param $params
  424. * @return string
  425. * @throws \Exception
  426. */
  427. private function _buildBookUrl($channelId, $params)
  428. {
  429. try {
  430. $url = '';
  431. if ($params['type'] == Message::MESSAGE_LINK_TYPE_BOOK) {
  432. $sourceUrl = '/index/book/chapter?book_id=' . $params['book_id'] . '&chapter_id=' . $params['chapter_id'];
  433. $url = getCurrentDomain($channelId, $sourceUrl);
  434. }
  435. return $url;
  436. } catch (\Exception $e) {
  437. throw $e;
  438. }
  439. }
  440. /**
  441. * 返回渠道活动地址
  442. * @param $channelId
  443. * @param $params
  444. * @param $message
  445. * @return string
  446. * @throws \think\exception\DbException
  447. */
  448. private function _buildActivityUrl($channelId, $params)
  449. {
  450. $activityObj = Activity::get(['id' => $params['activity_id']]);
  451. if (($activityObj->status != '1') || ($activityObj->endtime <= time())) {
  452. //活动无效
  453. LogService::info("活动状态无效 channel_id:{$channelId} params:" . json_encode($params));
  454. return "";
  455. }
  456. $url = '';
  457. if ($activityObj->type == ActivityConstants::ACTIVITY_TYPE_CUSTOM) {
  458. $config_id = $activityObj->config_id;
  459. $activity_config = Config::get('site.activity_config');
  460. //判断是否是VIP创建的活动
  461. if ($activityObj->admin_id != $channelId) {
  462. //拉取绑定关系
  463. $row = model("VipActivityRelation")
  464. ->field("activity.id, activity.admin_id, activity.status, activity.endtime")
  465. ->join("activity", "activity.id = vip_activity_relation.slave_activity_id")
  466. ->where('vip_activity_relation.master_activity_id', 'eq', $activityObj->id)
  467. ->where('vip_activity_relation.status', 'eq', 'normal')
  468. ->where('activity.admin_id', 'eq', $channelId)
  469. ->find();
  470. if ($row) {
  471. if (($row->status != '1') || ($row->endtime <= time())) {
  472. //活动无效
  473. LogService::info("活动状态无效 channel_id:{$row['admin_id']} activity_id: {$row['id']} params:" . json_encode($params));
  474. return "";
  475. }
  476. $url = getCurrentDomain($channelId,
  477. '/s/' . $row['id'] . '/r/' . $activity_config['config'][$config_id]['resource_id']);
  478. } else {
  479. LogService::error("活动不存在,channel_id: {$channelId}, activity_id: {$params['activity_id']}");
  480. }
  481. } else {
  482. $url = getCurrentDomain($channelId,
  483. '/s/' . $activityObj->id . '/r/' . $activity_config['config'][$config_id]['resource_id']);
  484. }
  485. }
  486. elseif($activityObj->type == ActivityConstants::ACTIVITY_TYPE_PLAT){
  487. $url = getCurrentDomain($channelId, '/s/' . $activityObj->id);
  488. }
  489. elseif($activityObj->type == ActivityConstants::ACTIVITY_TYPE_GIVE) {
  490. $config_id = $activityObj->config_id;
  491. $activity_config = Config::get('site.activity_give_config');
  492. $url = getCurrentDomain($channelId,
  493. '/s/' . $activityObj->id . '/r/' . $activity_config['config'][$config_id]['resource_id']);
  494. }
  495. return $url;
  496. }
  497. /**
  498. * 获取消耗活动的链接
  499. * @param $channelId
  500. * @param $params
  501. * @return string
  502. */
  503. private function _buildCampaignUrl($channelId, $params)
  504. {
  505. $url = '/index/recharge/campaignIndex?active_id='.$params['campaign_match_id'];
  506. $activityUrl = getCurrentDomain($channelId, $url, [], true);
  507. return $activityUrl;
  508. }
  509. /**
  510. * 获取最近阅读的链接
  511. * @param int $channelId
  512. * @return string
  513. */
  514. private function _buildRecentUrl($channelId)
  515. {
  516. $recentUrl = Message::getKeepReadingFullPath($channelId);
  517. return $recentUrl;
  518. }
  519. /**
  520. * 构造url的打点信息
  521. * @param $channelId
  522. * @param $msgType
  523. * @param $url
  524. * @param $sendTime
  525. * @param $channelMessageId
  526. * @param $idx
  527. * @return string
  528. * @throws \Exception
  529. */
  530. public function buildPointInfo($channelId, $msgType, $url, $sendTime, $channelMessageId, $idx)
  531. {
  532. //占位符替换
  533. $url = UrlService::instance()->replaceReferralHost($channelId, $url)->data;
  534. $shortUrlService = new ShortUrlService();
  535. if ($msgType == 1) {
  536. $mark = BigData::BIG_DATA_MARK_HIGH_MSG_TEXT;
  537. } elseif ($msgType == 2) {
  538. $mark = BigData::BIG_DATA_MARK_HIGH_MSG_IMG_TXT;
  539. }
  540. $url = $this->_urlBuildExt($url, $mark, $sendTime, $channelMessageId, $idx + 1);
  541. $shortUrl = $shortUrlService->create($url, $channelId);
  542. return $shortUrl;
  543. }
  544. /**
  545. * 推广链接js打点相关参数
  546. * @param $url
  547. * @param $mark
  548. * @param $sendTime
  549. * @param $channelMessageId
  550. * @param $idx
  551. * @return string
  552. */
  553. private function _urlBuildExt($url, $mark, $sendTime, $channelMessageId, $idx)
  554. {
  555. $url = trim($url);
  556. if (!strpos($url, '{$ophost}')) {
  557. // 如果 url中没有 域名占位符,不加入ext参数
  558. $url = $this->_rejectUrlExt($url);
  559. return trim($url, '?');
  560. } else {
  561. $ext = [
  562. 'mark' => $mark,
  563. 'push_time' => $sendTime,
  564. 'push_id' => $channelMessageId,
  565. 'push_idx' => $idx,
  566. ];
  567. $strExt = json_encode($ext);
  568. if (strpos($url, '?') === false) {
  569. $url .= '?ext=' . $strExt;
  570. } else {
  571. $url .= '&ext=' . $strExt;
  572. }
  573. }
  574. return trim($url, '?');
  575. }
  576. /**
  577. * @param $url
  578. * @return string
  579. */
  580. private function _rejectUrlExt($url)
  581. {
  582. $url_data = parse_url($url);
  583. $query = isset($url_data['query']) ? $url_data['query'] : '';
  584. parse_str($query, $q_arr);
  585. if (!empty($q_arr['ext'])) {
  586. unset($q_arr['ext']);
  587. }
  588. $url_data['query'] = http_build_query($q_arr);
  589. $url = $this->_unparse_url($url_data);
  590. return $url;
  591. }
  592. /**
  593. * @param $parsed_url
  594. * @return string
  595. */
  596. private function _unparse_url($parsed_url)
  597. {
  598. $scheme = isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : '';
  599. $host = isset($parsed_url['host']) ? $parsed_url['host'] : '';
  600. $port = isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '';
  601. $user = isset($parsed_url['user']) ? $parsed_url['user'] : '';
  602. $pass = isset($parsed_url['pass']) ? ':' . $parsed_url['pass'] : '';
  603. $pass = ($user || $pass) ? "$pass@" : '';
  604. $path = isset($parsed_url['path']) ? $parsed_url['path'] : '';
  605. $query = isset($parsed_url['query']) ? '?' . $parsed_url['query'] : '';
  606. $fragment = isset($parsed_url['fragment']) ? '#' . $parsed_url['fragment'] : '';
  607. return "$scheme$user$pass$host$port$path$query$fragment";
  608. }
  609. /**
  610. * 返回渠道信息
  611. * @param $adminId
  612. * @return mixed
  613. */
  614. private function getAdminConfig($channelId)
  615. {
  616. if (!isset(self::$adminConfig[$channelId])) {
  617. self::$adminConfig[$channelId] = $this->getAdminConfigModel()->getAdminInfoAll($channelId);
  618. }
  619. return self::$adminConfig[$channelId];
  620. }
  621. /**
  622. * 返回渠道信息
  623. * @param $channelId
  624. * @return WeChatObject
  625. */
  626. public function getWechatObj($channelId): WeChatObject
  627. {
  628. if (!isset(self::$wechatObj[$channelId])) {
  629. $adminConfig = $this->getAdminConfig($channelId);
  630. self::$wechatObj[$channelId] = new WeChatObject($adminConfig);
  631. }
  632. return self::$wechatObj[$channelId];
  633. }
  634. }