Wechat.php 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960
  1. <?php
  2. /**
  3. * Niushop商城系统 - 团队十年电商经验汇集巨献!
  4. * =========================================================
  5. * Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
  6. * ----------------------------------------------
  7. * 官方网址: https://www.niushop.com
  8. * =========================================================
  9. */
  10. namespace addon\wechat\model;
  11. use addon\wxoplatform\model\OpenPlatform;
  12. use addon\wxoplatform\model\Oplatform;
  13. use EasyWeChat\Factory;
  14. use EasyWeChat\Kernel\Messages\Article;
  15. use EasyWeChat\Kernel\Messages\Text;
  16. use EasyWeChat\Kernel\Messages\News;
  17. use EasyWeChat\Kernel\Messages\NewsItem;
  18. use app\model\BaseModel;
  19. use think\facade\Cache;
  20. /**
  21. * 微信公众号
  22. */
  23. class Wechat extends BaseModel
  24. {
  25. public $app;//微信公众对象
  26. private $site_id;//站点
  27. //公众号类型
  28. public $service_type = array (
  29. 0 => "订阅号",
  30. 1 => "由历史老帐号升级后的订阅号",
  31. 2 => "服务号",
  32. );
  33. //公众号认证类型
  34. public $verify_type = array (
  35. -1 => "未认证",
  36. 0 => "微信认证",
  37. 1 => "新浪微博认证",
  38. 2 => "腾讯微博认证",
  39. 3 => "已资质认证通过但还未通过名称认证",
  40. 4 => "已资质认证通过、还未通过名称认证,但通过了新浪微博认证",
  41. 5 => "已资质认证通过、还未通过名称认证,但通过了腾讯微博认证",
  42. );
  43. //business_info 说明
  44. public $business_type = array (
  45. 'open_store' => "是否开通微信门店功能",
  46. 'open_scan' => "是否开通微信扫商品功能",
  47. 'open_pay' => "是否开通微信支付功能",
  48. 'open_card' => "是否开通微信卡券功能",
  49. 'open_shake' => "是否开通微信摇一摇功能",
  50. );
  51. public function __construct($site_id = 0)
  52. {
  53. $this->site_id = $site_id;
  54. // $response = $this->app->server->serve();
  55. // 将响应输出
  56. // $response->send();exit; // Laravel 里请使用:return $response;
  57. }
  58. /**
  59. * 授权实例
  60. */
  61. public function app()
  62. {
  63. $config_model = new Config();
  64. $config_result = $config_model->getWechatConfig($this->site_id);
  65. $config = $config_result[ "data" ];
  66. if (!empty($config)) {
  67. $config_info = $config[ "value" ];
  68. }
  69. //授权方式 手动授权 或 自动授权(通过开放平台)
  70. $auth_type = $config_info[ "is_authopen" ] ?? '';
  71. if ($auth_type == "1") {
  72. $oplatform_model = new Oplatform();
  73. $config_info[ 'type' ] = 'wechat';
  74. $this->app = $oplatform_model->app($config_info);
  75. } else {
  76. $config = [
  77. 'app_id' => $config_info[ "appid" ] ?? '',
  78. 'secret' => $config_info[ "appsecret" ] ?? '',
  79. 'token' => $config_info[ "token" ] ?? '', // Token
  80. 'aes_key' => $config_info[ 'encodingaeskey' ] ?? '', // EncodingAESKey,兼容与安全模式下请一定要填写!!!
  81. // 指定 API 调用返回结果的类型:array(default)/collection/object/raw/自定义类名
  82. 'response_type' => 'array',
  83. /**
  84. * 日志配置
  85. *
  86. * level: 日志级别, 可选为:debug/info/notice/warning/error/critical/alert/emergency
  87. * permission:日志文件权限(可选),默认为null(若为null值,monolog会取0644)
  88. * file:日志文件位置(绝对路径!!!),要求可写权限
  89. */
  90. 'log' => [
  91. 'level' => 'debug',
  92. 'permission' => 0777,
  93. 'file' => 'runtime/log/wechat/easywechat.logs',
  94. ],
  95. ];
  96. if (empty($config[ 'app_id' ]) || empty($config[ 'secret' ])) {
  97. throw new \Exception('商家公众号配置有误,请联系平台管理员');
  98. }
  99. $this->app = Factory::officialAccount($config);
  100. }
  101. return $this->app;
  102. }
  103. /**
  104. * 创建微信菜单
  105. * @param $buttons
  106. */
  107. public function menu($buttons)
  108. {
  109. try {
  110. $result = $this->app()->menu->create($buttons);
  111. if ($result[ 'errcode' ] == 0) {
  112. return $this->success();
  113. } else {
  114. return $this->error($result, $result[ "errmsg" ]);
  115. }
  116. } catch (\Exception $e) {
  117. return $this->error([], $e->getMessage());
  118. }
  119. }
  120. /**
  121. * 拉取粉丝列表
  122. * @param $nextOpenId
  123. * @return \multitype
  124. * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
  125. */
  126. public function user($nextOpenId = null)
  127. {
  128. try {
  129. $result = $this->app()->user->list($nextOpenId); // $nextOpenId 可选
  130. if (isset($result[ 'errcode' ]) && $result[ 'errcode' ] != 0) {
  131. return $this->error($result, $result[ "errmsg" ]);
  132. }
  133. return $this->success($result);
  134. } catch (\Exception $e) {
  135. return $this->error([], $e->getMessage());
  136. }
  137. }
  138. /**
  139. * 查询多个粉丝信息
  140. * @param $user_list 数组 [$openId1, $openId2, ...]
  141. */
  142. public function selectUser($user_list)
  143. {
  144. try {
  145. $result = $this->app()->user->select($user_list); // $nextOpenId 可选
  146. if (isset($result[ 'errcode' ]) && $result[ 'errcode' ] != 0) {
  147. return $this->error($result, $result[ "errmsg" ]);
  148. }
  149. return $this->success($result);
  150. } catch (\Exception $e) {
  151. return $this->error([], $e->getMessage());
  152. }
  153. }
  154. /**
  155. * 得到粉丝信息
  156. */
  157. public function getUser($openId)
  158. {
  159. try {
  160. $result = $this->app()->user->get($openId); // $nextOpenId 可选
  161. if (isset($result[ 'errcode' ]) && $result[ 'errcode' ] != 0) {
  162. return $this->error($result, $result[ "errmsg" ]);
  163. }
  164. return $this->success($result);
  165. } catch (\Exception $e) {
  166. return $this->error([], $e->getMessage());
  167. }
  168. }
  169. /**
  170. * TODO
  171. * 根据 Code 获取用户 session 信息
  172. * @param $param
  173. * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
  174. */
  175. public function authCodeToOpenid($params = [])
  176. {
  177. try {
  178. if (empty($_REQUEST[ "code" ])) {
  179. $auth_result = $this->getAuthCode(request()->url(true));
  180. if ($auth_result[ "code" ] >= 0) {
  181. Header("Location: " . $auth_result[ "data" ]);
  182. } else {
  183. return $auth_result;
  184. }
  185. }
  186. $user = $this->app()->oauth->user();//获取授权用户
  187. $data = [
  188. 'openid' => $user->getId(),
  189. 'userinfo' => [
  190. 'avatarUrl' => $user->getAvatar(),
  191. 'nickName' => $user->getNickname()
  192. ]
  193. ];
  194. return $this->success($data);
  195. } catch (\Exception $e) {
  196. if (property_exists($e, 'body')) {
  197. return $this->handleError($e->body[ 'errcode' ], $e->body[ 'errmsg' ]);
  198. }
  199. return $this->error([], $e->getMessage());
  200. }
  201. }
  202. /**
  203. * 根据code获取授权信息
  204. * @param $code
  205. * @return array
  206. */
  207. public function getAuthByCode($params)
  208. {
  209. try {
  210. $user = $this->app()->oauth->userByCode($params[ 'code' ]);//获取授权用户
  211. $original = $user->getOriginal();
  212. $data = [
  213. 'openid' => $original[ 'openid' ],
  214. 'userinfo' => [
  215. 'avatarUrl' => $original[ 'headimgurl' ] ?? '',
  216. 'nickName' => $original[ 'nickname' ] ?? ''
  217. ]
  218. ];
  219. if (isset($original[ 'unionid' ])) {
  220. $data[ 'unionid' ] = $original[ 'unionid' ];
  221. }
  222. return $this->success($data);
  223. } catch (\Exception $e) {
  224. if (property_exists($e, 'body')) {
  225. return $this->handleError($e->body[ 'errcode' ], $e->body[ 'errmsg' ]);
  226. }
  227. return $this->error([], $e->getMessage());
  228. }
  229. }
  230. /**
  231. * 获取公众号网页授权code
  232. * @param $redirect
  233. * @param string $scopes snsapi_base:静默授权 snsapi_userinfo:用户授权
  234. * @return array
  235. */
  236. public function getAuthCode($redirect, $scopes = 'snsapi_base')
  237. {
  238. try {
  239. $response = $this->app()->oauth->scopes([ $scopes ])->redirect($redirect);
  240. return $this->success($response->getTargetUrl());
  241. } catch (\Exception $e) {
  242. return $this->error([], $e->getMessage());
  243. }
  244. }
  245. /**
  246. * 获取永久二维码
  247. * @return unknown
  248. */
  249. public function getQrcode($uid)
  250. {
  251. $result = $this->app()->qrcode->forever($uid);
  252. if (isset($result[ 'errcode' ]) && $result[ 'errcode' ] != 0) {
  253. return $this->error($result, $result[ "errmsg" ]);
  254. }
  255. $url = $this->app()->qrcode->url($result[ 'data' ][ 'ticket' ]);
  256. if (isset($url[ 'errcode' ]) && $url[ 'errcode' ] != 0) {
  257. return $this->error($url, $url[ "errmsg" ]);
  258. }
  259. return $this->success($url);
  260. }
  261. /**
  262. * 获取临时二维码
  263. * @param $scene
  264. * @return array
  265. */
  266. public function getTempQrcode($scene, $seconds)
  267. {
  268. try {
  269. $result = $this->app()->qrcode->temporary($scene, $seconds);
  270. if (isset($result[ 'errcode' ]) && $result[ 'errcode' ] != 0) {
  271. return $this->error($result, $result[ "errmsg" ]);
  272. }
  273. $url = $this->app()->qrcode->url($result[ 'ticket' ]);
  274. if (isset($url[ 'errcode' ]) && $url[ 'errcode' ] != 0) {
  275. return $this->handleError($url[ 'errcode' ], $url[ "errmsg" ]);
  276. }
  277. return $this->success($url);
  278. } catch (\Exception $e) {
  279. if (property_exists($e, 'body')) {
  280. return $this->handleError($e->body[ 'errcode' ], $e->body[ 'errmsg' ]);
  281. }
  282. return $this->error([], $e->getMessage());
  283. }
  284. }
  285. /**
  286. * 获取jssdk配置
  287. * @param unknown $url
  288. */
  289. public function getJssdkConfig($url)
  290. {
  291. try {
  292. $this->app()->jssdk->setUrl($url);
  293. $res = $this->app->jssdk->buildConfig([], false, false, false);
  294. return $this->success($res);
  295. } catch (\Exception $e) {
  296. if (property_exists($e, 'body')) {
  297. return $this->handleError($e->body[ 'errcode' ], $e->body[ 'errmsg' ]);
  298. }
  299. return $this->error([], $e->getMessage());
  300. }
  301. }
  302. /********************************************************** 数据统计与分析start *******************************************************************/
  303. /********************************************************** 数据统计与分析end *******************************************************************/
  304. /*******************************************************************************微信接口连接开始*****************************************************/
  305. /*******************************************************************************微信接口连接结束*****************************************************/
  306. /***************************************************************** 微信公众号 统计 start *****************************************************************************************/
  307. /***************************************************************** 微信公众号 统计 end *****************************************************************************************/
  308. /****************************************************************************** 数据统计与分析***********************************************************/
  309. /**
  310. * 获取用户增减数据, 最大时间跨度:7;
  311. * @param $from
  312. * @param $to
  313. */
  314. public function userSummary($from, $to)
  315. {
  316. try {
  317. $result = $this->app()->data_cube->userSummary($from, $to);
  318. if (isset($result[ 'errcode' ]) && $result[ 'errcode' ] != 0) {
  319. return $this->error([], $result[ "errmsg" ]);
  320. }
  321. return $this->success($result[ "list" ]);
  322. } catch (\Exception $e) {
  323. return $this->error([], $e->getMessage());
  324. }
  325. }
  326. /**
  327. * 获取累计用户数据, 最大时间跨度:7
  328. * @param $from
  329. * @param $to
  330. */
  331. public function userCumulate($from, $to)
  332. {
  333. try {
  334. $result = $this->app()->data_cube->userCumulate($from, $to);
  335. if (isset($result[ 'errcode' ]) && $result[ 'errcode' ] != 0) {
  336. return $this->error([], $result[ "errmsg" ]);
  337. }
  338. return $this->success($result[ "list" ]);
  339. } catch (\Exception $e) {
  340. return $this->error([], $e->getMessage());
  341. }
  342. }
  343. /**
  344. * 获取接口分析分时数据, 最大时间跨度:1;
  345. * @param $from
  346. * @param $to
  347. * @return array|\multitype
  348. */
  349. public function interfaceSummaryHourly($from, $to)
  350. {
  351. try {
  352. $result = $this->app()->data_cube->interfaceSummaryHourly($from, $to);
  353. if (isset($result[ 'errcode' ]) && $result[ 'errcode' ] != 0) {
  354. return $this->error([], $result[ "errmsg" ]);
  355. }
  356. return $this->success($result[ "list" ]);
  357. } catch (\Exception $e) {
  358. return $this->error([], $e->getMessage());
  359. }
  360. }
  361. /**
  362. * 获取接口分析数据, 最大时间跨度:30;
  363. * @param $from
  364. * @param $to
  365. * @return array|\multitype
  366. */
  367. public function interfaceSummary($from, $to)
  368. {
  369. try {
  370. $result = $this->app()->data_cube->interfaceSummary($from, $to);
  371. if (isset($result[ 'errcode' ]) && $result[ 'errcode' ] != 0) {
  372. return $this->error([], $result[ "errmsg" ]);
  373. }
  374. return $this->success($result[ "list" ]);
  375. } catch (\Exception $e) {
  376. return $this->error([], $e->getMessage());
  377. }
  378. }
  379. /****************************************************************************** 数据统计与分析***********************************************************/
  380. /****************************************************************************** 素材start***********************************************************/
  381. /**
  382. * 上传图片
  383. * @param $path
  384. * @return array
  385. */
  386. function uploadImage($path)
  387. {
  388. $result = $this->app()->material->uploadImage($path);
  389. if (isset($result[ 'errcode' ]) && $result[ 'errcode' ] != 0) {
  390. return $this->error($result, $result[ "errmsg" ]);
  391. }
  392. return $this->success($result);
  393. }
  394. /**
  395. * 上传语音
  396. * @param $path
  397. * @return array
  398. */
  399. function uploadVoice($path)
  400. {
  401. $result = $this->app()->material->uploadVoice($path);
  402. if (isset($result[ 'errcode' ]) && $result[ 'errcode' ] != 0) {
  403. return $this->error($result, $result[ "errmsg" ]);
  404. }
  405. return $this->success($result);
  406. }
  407. /**
  408. * 上传视频
  409. * @param $path
  410. * @return array
  411. */
  412. function uploadVideo($path)
  413. {
  414. $result = $this->app()->material->uploadVideo($path);
  415. if (isset($result[ 'errcode' ]) && $result[ 'errcode' ] != 0) {
  416. return $this->error($result, $result[ "errmsg" ]);
  417. }
  418. return $this->success($result);
  419. }
  420. /**
  421. * 上传缩略图
  422. * @param $path
  423. * @return array
  424. */
  425. function uploadThumb($path)
  426. {
  427. $result = $this->app()->material->uploadThumb($path);
  428. if (isset($result[ 'errcode' ]) && $result[ 'errcode' ] != 0) {
  429. return $this->error($result, $result[ "errmsg" ]);
  430. }
  431. return $this->success($result);
  432. }
  433. /**
  434. * 上传图文
  435. * @param $data
  436. */
  437. public function uploadArticle($data)
  438. {
  439. $article_data = [];
  440. foreach ($data as $k => $v) {
  441. $article_data[] = new Article($v);
  442. }
  443. $result = $this->app()->material->uploadArticle($article_data);
  444. if (isset($result[ 'errcode' ]) && $result[ 'errcode' ] != 0) {
  445. return $this->error($result, $result[ "errmsg" ]);
  446. }
  447. return $this->success($result);
  448. }
  449. /**
  450. * 修改图文
  451. * @param $mediaId
  452. * @param $data 文章详情
  453. * @param int $index 多图文中的第几篇
  454. * @return array
  455. */
  456. public function updateArticle($mediaId, $data, $index = 0)
  457. {
  458. $result = $this->app()->material->updateArticle($mediaId, $data, $index);
  459. if (isset($result[ 'errcode' ]) && $result[ 'errcode' ] != 0) {
  460. return $this->error($result, $result[ "errmsg" ]);
  461. }
  462. return $this->success($result);
  463. }
  464. /**
  465. * 上传图文消息图片
  466. * @param $path
  467. * @return array
  468. * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
  469. * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
  470. */
  471. public function uploadArticleImage($path)
  472. {
  473. $result = $this->app()->material->uploadArticleImage($path);
  474. if (isset($result[ 'errcode' ]) && $result[ 'errcode' ] != 0) {
  475. return $this->error($result, $result[ "errmsg" ]);
  476. }
  477. return $this->success($result);
  478. }
  479. /**
  480. * 获取永久素材
  481. * @param $mediaId
  482. * @return array
  483. */
  484. public function getMaterial($mediaId)
  485. {
  486. $result = $this->app()->material->get($mediaId);
  487. if (isset($result[ 'errcode' ]) && $result[ 'errcode' ] != 0) {
  488. return $this->error($result, $result[ "errmsg" ]);
  489. }
  490. return $this->success($result);
  491. }
  492. /**
  493. * 删除永久素材
  494. * @param $mediaId
  495. * @return array
  496. */
  497. public function deleteMaterial($mediaId)
  498. {
  499. $result = $this->app()->material->delete($mediaId);
  500. if (isset($result[ 'errcode' ]) && $result[ 'errcode' ] != 0) {
  501. return $this->error($result, $result[ "errmsg" ]);
  502. }
  503. return $this->success($result);
  504. }
  505. /****************************************************************************** 素材end***********************************************************/
  506. /****************************************************************************** 回复start***********************************************************/
  507. /**
  508. * 用户事件
  509. * @return array
  510. */
  511. public function relateWeixin()
  512. {
  513. $server = $this->app->server;
  514. $message = $server->getMessage();
  515. if (isset($message[ 'MsgType' ])) {
  516. switch ( $message[ 'MsgType' ] ) {
  517. case 'event':
  518. $this->app->server->push(function($res) {
  519. if ($res[ 'Event' ] == 'subscribe') {
  520. // 关注公众号
  521. $Userstr = $this->getUser($res[ 'FromUserName' ]);
  522. //获取用户信息
  523. $wechat_user = $this->app->user->get($res[ 'FromUserName' ]);
  524. if (preg_match("/^qrscene_/", $res[ 'EventKey' ])) {
  525. $source_uid = substr($res[ 'EventKey' ], 8);
  526. $_SESSION[ 'source_uid' ] = $source_uid;
  527. } elseif (!empty($_SESSION[ 'source_uid' ])) {
  528. $source_uid = $_SESSION[ 'source_uid' ];
  529. } else {
  530. $source_uid = 0;
  531. }
  532. if (preg_match("/^qrscene_key_/", $res[ 'EventKey' ])) {
  533. //新增2021.06.02
  534. $key = substr($res[ 'EventKey' ], 12);
  535. $cache = Cache::get('wechat_' . $key);
  536. if (!empty($cache)) {
  537. Cache::set('wechat_' . $key, $wechat_user);
  538. }
  539. }
  540. if (preg_match("/^verify_/", $res[ 'EventKey' ])) {
  541. $cache = Cache::get($res[ 'EventKey' ]);
  542. if (empty($cache)) {
  543. Cache::set($res[ 'EventKey' ], $wechat_user, 7200);
  544. }
  545. }
  546. $nickname_decode = preg_replace('/[\x{10000}-\x{10FFFF}]/u', '', $wechat_user[ 'nickname' ]);
  547. $headimgurl = $wechat_user[ 'headimgurl' ];
  548. $sex = $wechat_user[ 'sex' ];
  549. $language = $wechat_user[ 'language' ];
  550. $country = $wechat_user[ 'country' ];
  551. $province = $wechat_user[ 'province' ];
  552. $city = $wechat_user[ 'city' ];
  553. $district = "无";
  554. $openid = $wechat_user[ 'openid' ];
  555. $nickname = $wechat_user[ 'nickname' ];
  556. if (!empty($wechat_user[ 'unionid' ])) {
  557. $unionid = $wechat_user[ 'unionid' ];
  558. } else {
  559. $unionid = '';
  560. }
  561. $memo = $wechat_user[ 'remark' ];
  562. $data = array (
  563. 'site_id' => $this->site_id,
  564. 'nickname' => $nickname,
  565. 'nickname_decode' => $nickname_decode,
  566. 'headimgurl' => $headimgurl,
  567. 'sex' => $sex,
  568. 'language' => $language,
  569. 'country' => $country,
  570. 'province' => $province,
  571. 'city' => $city,
  572. 'district' => $district,
  573. 'openid' => $openid,
  574. 'unionid' => $unionid,
  575. 'groupid' => '',
  576. 'is_subscribe' => 1,
  577. 'remark' => $memo,
  578. 'subscribe_time' => $wechat_user[ 'subscribe_time' ] ?? 0,
  579. 'subscribe_scene' => $wechat_user[ 'subscribe_scene' ] ?? 0,
  580. 'unsubscribe_time' => $wechat_user[ 'unsubscribe_time' ] ?? 0,
  581. 'update_date' => time()
  582. );
  583. $fans = new Fans();
  584. $fans_info = $fans->getFansInfo([ [ 'openid', '=', $openid ], [ 'site_id', '=', $this->site_id ] ]);
  585. if (empty($fans_info[ 'data' ])) {
  586. $fans->addFans($data);
  587. } else {
  588. $fans->editFans($data, [ [ 'openid', '=', $openid ], [ 'site_id', '=', $this->site_id ] ]);
  589. }
  590. //获取关注发送消息内容
  591. $replay = new Replay();
  592. $replay_content = $replay->getWechatFollowReplay($this->site_id);
  593. return new Text($replay_content[ 'data' ]);
  594. } else if ($res[ 'Event' ] == 'unsubscribe') {
  595. //取消关注
  596. $fans = new Fans();
  597. $openid = $res[ 'FromUserName' ];
  598. $fans->unfollowWechat((string) $openid);
  599. } else if ($res[ 'Event' ] == 'unsubscribe') {
  600. //取消关注
  601. $fans = new Fans();
  602. $openid = $res[ 'FromUserName' ];
  603. $fans->unfollowWechat((string) $openid);
  604. } else if ($res[ 'Event' ] == 'SCAN') {
  605. // SCAN事件 - 用户已关注时的事件推送 - 扫描带参数二维码事件
  606. $openid = $res[ 'FromUserName' ];
  607. $data = $res[ 'EventKey' ];
  608. if (preg_match("/^key_/", $data)) {
  609. $key = substr($data, 4);
  610. $cache = Cache::get('wechat_' . $key);
  611. if (!empty($cache)) {
  612. $wechat_user = $this->app->user->get($res[ 'FromUserName' ]);
  613. Cache::set('wechat_' . $key, $wechat_user);
  614. }
  615. }
  616. if (preg_match("/^verify_/", $res[ 'EventKey' ])) {
  617. $cache = Cache::get($res[ 'EventKey' ]);
  618. if (empty($cache)) {
  619. $wechat_user = $this->app->user->get($res[ 'FromUserName' ]);
  620. Cache::set($res[ 'EventKey' ], $wechat_user, 7200);
  621. }
  622. }
  623. return new Text('扫码成功。');
  624. } else if ($res[ 'Event' ] == 'CLICK') {
  625. // CLICK事件 - 自定义菜单事件
  626. $openid = $res[ 'FromUserName' ];
  627. $data = $res[ 'EventKey' ];
  628. if (strpos($res[ 'EventKey' ], 'MATERIAL_GRAPHIC_MESSAGE_') === 0) {
  629. $material_id = substr($res[ 'EventKey' ], 25);
  630. $material_type = 1;
  631. } else if (strpos($res[ 'EventKey' ], 'MATERIAL_PICTURE_') === 0) {
  632. $material_id = substr($res[ 'EventKey' ], 17);
  633. $material_type = 2;
  634. } else if (strpos($res[ 'EventKey' ], 'MATERIAL_TEXT_MESSAGE_') === 0) {
  635. $material_id = substr($res[ 'EventKey' ], 22);
  636. $material_type = 5;
  637. }
  638. $material = new Material();
  639. $media_info = $material->getMaterialInfo([ [ 'id', '=', $material_id, 'type', '=', $material_type ] ]);
  640. $media_info = $media_info[ 'data' ];
  641. if ($media_info) {
  642. $value = json_decode($media_info[ 'value' ], true);
  643. if ($material_type == 1) {
  644. //图文
  645. $url = __ROOT__;
  646. $url = $url . '/index.php/wechat/api/auth/wechatArticle?id=' . $media_info[ 'id' ];
  647. $items = [
  648. new NewsItem([
  649. 'title' => $value[ 0 ][ 'title' ],
  650. 'description' => strip_tags($value[ 0 ][ 'content' ]),
  651. 'url' => $url,
  652. 'image' => $value[ 0 ][ 'cover' ][ 'path' ],
  653. ]),
  654. ];
  655. return new News($items);
  656. } else if ($material_type == 2) {
  657. //图片
  658. } else if ($material_type == 5) {
  659. //文字
  660. return new Text($value[ 'content' ]);
  661. }
  662. }
  663. } else if ($res[ 'Event' ] == 'weapp_audit_success') {
  664. // 小程序审核通过 自动发布
  665. if (addon_is_exit('wxoplatform')) {
  666. $weapp_original = $res[ 'ToUserName' ];
  667. $site_info = model('config')->getInfo([ [ 'app_module', '=', 'shop' ], [ 'config_key', '=', 'WEAPP_CONFIG' ], [ 'value', 'like', '%is_authopen%' ], [ 'value', 'like', '%' . $weapp_original . '%' ] ], 'site_id');
  668. if (!empty($site_info)) {
  669. // 先将审核中的变更为审核成功
  670. model('weapp_audit_record')->update([ 'status' => 1, 'audit_time' => time() ], [ [ 'status', '=', 0 ], [ 'site_id', '=', $site_info[ 'site_id' ] ] ]);
  671. $platform = new OpenPlatform($site_info[ 'site_id' ]);
  672. $result = $platform->release();
  673. if ($result[ 'code' ] >= 0) {
  674. model('weapp_audit_record')->update([ 'status' => 5, 'release_time' => time() ], [ [ 'status', '=', 1 ], [ 'site_id', '=', $site_info[ 'site_id' ] ] ]);
  675. }
  676. }
  677. }
  678. }
  679. });
  680. $response = $this->app->server->serve();
  681. // 将响应输出
  682. return $response->send();
  683. break;
  684. case 'text':
  685. $this->app->server->push(function($res) {
  686. $replay = new Replay();
  687. $rule = $replay->getSiteWechatKeywordsReplay($res[ 'Content' ], $this->site_id);
  688. if ($rule[ 'data' ]) {
  689. if ($rule[ 'data' ][ 'type' ] == 'text') {
  690. //文字
  691. return new Text($rule[ 'data' ][ 'reply_content' ]);
  692. } else {
  693. $material = new Material();
  694. $media_info = $material->getMaterialInfo([ [ 'media_id', '=', $rule[ 'data' ][ 'media_id' ] ] ]);
  695. $media_info = $media_info[ 'data' ];
  696. if ($media_info) {
  697. $material_type = $media_info[ 'type' ];
  698. $value = json_decode($media_info[ 'value' ], true);
  699. if ($material_type == 1) {
  700. $url = __ROOT__;
  701. $url = $url . '/index.php/wechat/api/auth/wechatArticle?id=' . $media_info[ 'id' ];
  702. $items = [
  703. new NewsItem([
  704. 'title' => $value[ 0 ][ 'title' ],
  705. 'description' => strip_tags($value[ 0 ][ 'content' ]),
  706. 'url' => $url,
  707. 'image' => $value[ 0 ][ 'cover' ][ 'path' ],
  708. ]),
  709. ];
  710. return new News($items);
  711. } else if ($material_type == 2) {
  712. //图片
  713. }
  714. }
  715. }
  716. }
  717. });
  718. $response = $this->app->server->serve();
  719. // 将响应输出
  720. return $response->send();
  721. break;
  722. case 'image':
  723. // return '收到图片消息';
  724. break;
  725. case 'voice':
  726. // return '收到语音消息';
  727. break;
  728. case 'video':
  729. // return '收到视频消息';
  730. break;
  731. case 'location':
  732. //return '收到坐标消息';
  733. break;
  734. case 'link':
  735. //return '收到链接消息';
  736. break;
  737. case 'file':
  738. ///return '收到文件消息';
  739. // ... 其它消息
  740. default:
  741. //return '收到其它消息';
  742. break;
  743. }
  744. }
  745. $response = $this->app->server->serve();
  746. return $response->send();
  747. }
  748. /****************************************************************************** 回复end***********************************************************/
  749. /****************************************************************************** 模板消息start ***********************************************************/
  750. /**
  751. * 添加模板消息
  752. * @param unknown $shortId
  753. */
  754. public function getTemplateId($shortId)
  755. {
  756. try {
  757. $res = $this->app()->template_message->addTemplate($shortId);
  758. if (isset($res[ 'errcode' ]) && $res[ 'errcode' ] == 0) return $res;
  759. $errormsg = [
  760. '45026' => '模板数量超出限制'
  761. ];
  762. return [ 'errcode' => $res[ 'errcode' ], 'errmsg' => $errormsg[ $res[ 'errcode' ] ] ?? $res[ 'errmsg' ] ];
  763. } catch (\Exception $e) {
  764. return [ 'errcode' => -1, 'errmsg' => $e->getMessage() ];
  765. }
  766. }
  767. /**
  768. * 删除模板消息
  769. * @param unknown $shortId
  770. */
  771. public function deleteTemplate($templateId)
  772. {
  773. try {
  774. $res = $this->app()->template_message->deletePrivateTemplate($templateId);
  775. if (isset($res[ 'errcode' ]) && $res[ 'errcode' ] == 0) return $res;
  776. $errormsg = [
  777. '45026' => '模板数量超出限制'
  778. ];
  779. return [ 'errcode' => $res[ 'errcode' ], 'errmsg' => $errormsg[ $res[ 'errcode' ] ] ?? $res[ 'errmsg' ] ];
  780. } catch (\Exception $e) {
  781. return [ 'errcode' => -1, 'errmsg' => $e->getMessage() ];
  782. }
  783. }
  784. /**
  785. * 发送模板消息
  786. * @param array $param
  787. * @return Ambigous <\Psr\Http\Message\ResponseInterface, \EasyWeChat\Kernel\Support\Collection, multitype:, object, string>
  788. */
  789. public function sendTemplateMessage(array $param)
  790. {
  791. $result = $this->app()->template_message->send([
  792. 'touser' => $param[ 'openid' ], // openid
  793. 'template_id' => $param[ 'template_id' ],// 模板id
  794. 'url' => $param[ 'url' ],// 跳转链接
  795. 'miniprogram' => $param[ 'miniprogram' ], // 跳转小程序 ['appid' => 'xxxxxxx','pagepath' => 'pages/xxx',]
  796. 'data' => $param[ 'data' ] // 模板变量
  797. ]);
  798. if (isset($result[ 'errcode' ]) && $result[ 'errcode' ] != 0) {
  799. return $this->error($result, $result[ "errmsg" ]);
  800. }
  801. return $this->success($result);
  802. }
  803. /****************************************************************************** 模板消息end***********************************************************/
  804. /******************************************************************************* 开放平台start *************************************************************************/
  805. /**
  806. * 将公众号或小程序绑定到指定开放平台帐号下
  807. */
  808. public function bindTo($open_appid)
  809. {
  810. try {
  811. $res = $this->app()->account->bindTo($open_appid);
  812. return $res;
  813. } catch (\Exception $e) {
  814. return [ 'errcode' => -1, 'errmsg' => $e->getMessage() ];
  815. }
  816. }
  817. /**
  818. * 将公众号/小程序从开放平台帐号下解绑
  819. */
  820. public function unbindFrom($open_appid)
  821. {
  822. try {
  823. $res = $this->app()->account->unbindFrom($open_appid);
  824. return $res;
  825. } catch (\Exception $e) {
  826. return [ 'errcode' => -1, 'errmsg' => $e->getMessage() ];
  827. }
  828. }
  829. /**
  830. * 获取公众号/小程序所绑定的开放平台帐号
  831. */
  832. public function getBinding()
  833. {
  834. try {
  835. $res = $this->app()->account->getBinding();
  836. return $res;
  837. } catch (\Exception $e) {
  838. return [ 'errcode' => -1, 'errmsg' => $e->getMessage() ];
  839. }
  840. }
  841. /**
  842. * 获取关注二维码
  843. * @param $fans_id
  844. * @return array|mixed
  845. */
  846. public function getFollowQrcode($fans_id)
  847. {
  848. $cache = Cache::get('wechat_follow_qrcode_' . $fans_id);
  849. if ($cache) return $cache;
  850. $res = $this->getTempQrcode('follow_key_' . $fans_id, 1728000);
  851. if ($res[ 'code' ] != 0) return $res;
  852. $data = $this->success([
  853. 'qrcode' => $res[ 'data' ],
  854. 'site_id' => $this->site_id,
  855. 'fans_id' => $fans_id
  856. ]);
  857. Cache::set('wechat_follow_qrcode_' . $fans_id, $data, 1728000);
  858. return $data;
  859. }
  860. /******************************************************************************* 开放平台end *************************************************************************/
  861. /**
  862. * 处理错误信息
  863. * @param $errcode
  864. * @param string $message
  865. * @return array
  866. */
  867. public function handleError($errcode, $message = '')
  868. {
  869. $error = require 'addon/wechat/config/wechat_error.php';
  870. return $this->error([], $error[ $errcode ] ?? $message);
  871. }
  872. }