Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 
 

730 строки
24 KiB

  1. <?php
  2. /**
  3. *
  4. * ============================================================================
  5. * * 版权所有 蜘蛛出行 * *
  6. * 网站地址: http://www.zhizhuchuxing.com
  7. * ----------------------------------------------------------------------------
  8. * 这不是一个自由软件!您只能在不用于商业目的的前提下对程序代码进行修改和
  9. * 使用;不允许对程序代码以任何形式任何目的的再发布。
  10. * ============================================================================
  11. * Author By: 倪宗锋
  12. * PhpStorm WeChatService.php
  13. * Create By 2017/6/7 11:09 $
  14. */
  15. namespace common\service;
  16. use common\config\wechatConfig\WxDoFunction;
  17. use common\service\pay\WeChatPay;
  18. use common\util\CurlInterface;
  19. use common\util\Util;
  20. class WeChatService
  21. {
  22. //配置参数
  23. private $request = array();
  24. private $response = false;
  25. private $token = '';
  26. private $appid = '';
  27. private $appsecret = '';
  28. public function __construct()
  29. {
  30. $wxConfig = Util::getWeChatConfig();
  31. $this->token = $wxConfig['token'];
  32. $this->appid = $wxConfig['appid'];
  33. $this->appsecret = $wxConfig['appsecret'];
  34. }
  35. /**
  36. * Des:接收参数并处理返回值
  37. * Name: exec
  38. * @return string
  39. * @author 倪宗锋
  40. */
  41. public function exec()
  42. {
  43. $content = $this->getContent();//获取参数并解析
  44. if ($content['MsgType'] == 'text') {
  45. $this->response = $this->textMsg($content);
  46. } elseif ($content['MsgType'] == 'event') {
  47. $this->response = $this->eventMsg($content);
  48. }
  49. return $this->response;
  50. }
  51. /**
  52. * Des:用户输入内容处理
  53. * Name: textMsg
  54. * @param $content
  55. * @return bool|string
  56. * @author 倪宗锋
  57. */
  58. public function textMsg($content)
  59. {
  60. // $textTpl = "
  61. //<xml>
  62. //<ToUserName><![CDATA[%s]]></ToUserName>
  63. //<FromUserName><![CDATA[%s]]></FromUserName>
  64. //<CreateTime>%s</CreateTime>
  65. //<MsgType><![CDATA[transfer_customer_service]]></MsgType>
  66. //</xml>";
  67. // $resultStr = sprintf($textTpl, $content['FromUserName'], $content['ToUserName'], time());
  68. // return $resultStr;
  69. $word = $content['Content'];
  70. return $this->send($word, $content, 'text');
  71. }
  72. /**
  73. * Des:推送事件处理
  74. * Name: eventMsg
  75. * @param $content
  76. * @return string
  77. * @author 倪宗锋
  78. */
  79. public function eventMsg($content)
  80. {
  81. if ($content['Event'] == 'subscribe') {//微信关注事件 发送欢迎语
  82. $word = 'subscribe';
  83. } elseif ($content['Event'] == 'unsubscribe') {//微信关注事件 发送欢迎语
  84. $word = 'unsubscribe';
  85. } elseif ($content['Event'] == 'SCAN') {//扫一扫
  86. $word = 'SCAN';
  87. } else if ($content['Event'] == 'VIEW' || empty($content['EventKey'])) {
  88. return false;
  89. } else {
  90. $word = $content['EventKey'];
  91. }
  92. if ($word == 'MSG_LIANXIKEFU') {
  93. return $this->callCuster($content);
  94. }
  95. return $this->send($word, $content, 'event');
  96. }
  97. /**
  98. * Des:联系客服
  99. * Name: sendText
  100. * @param $content
  101. * @return string
  102. * @author 倪宗锋
  103. */
  104. private function callCuster($content)
  105. {
  106. $textTpl = '' . "
  107. <xml>
  108. <ToUserName><![CDATA[%s]]></ToUserName>
  109. <FromUserName><![CDATA[%s]]></FromUserName>
  110. <CreateTime>%s</CreateTime>
  111. <MsgType><![CDATA[transfer_customer_service]]></MsgType>
  112. </xml>";
  113. $resultStr = sprintf($textTpl, $content['FromUserName'], $content['ToUserName'], time());
  114. return $resultStr;
  115. }
  116. /**
  117. * Des: 发送处理
  118. * Name: send
  119. * @param $word
  120. * @param $content
  121. * @param string $type 触发类型:text用户输入 event推送事件
  122. * @return string
  123. * @author 倪宗锋
  124. */
  125. public function send($word, $content, $type = 'text')
  126. {
  127. $weChatPayConfig = Util::getWeChatConfig();
  128. $textConfig = require ROOT_PATH . '/common/config/wechatConfig/wxInterface/' . $weChatPayConfig['mch_id'] . '/Wx.' . $type . '.config.php';
  129. if (empty($textConfig[$word]) == false) {//如果 有指定的配置就用指定的配置
  130. $msgSend = $textConfig[$word];
  131. } else if ($type == 'text') {//没有指定的配置 且 接收的是用户输入文本信息
  132. // $info = new WxDoFunction();
  133. // $getDoResult = $info->showOrderInfo($word);//获取订单信息暂时停止 //todo 获取订单信息
  134. // if ($getDoResult == '') {
  135. // //默认联系客服
  136. // $msgSend = $this->callCuster($content);
  137. // return $msgSend;
  138. // } else {
  139. // $msgSend = $getDoResult;
  140. // }
  141. //默认联系客服
  142. $msgSend = $this->callCuster($content);
  143. return $msgSend;
  144. } else {//没有指定配置 且接收的是按钮或扫一扫则直接返回关注自动回复信息
  145. $msgSend = $textConfig['subscribe'];
  146. }
  147. if (is_array($msgSend) && empty($msgSend['function']) == false) {//当推送事件有方法指定时,则调用该方法
  148. $wxDoFunction = new WxDoFunction();
  149. $function = $msgSend['function'];
  150. $wxDoFunction->$function($content);
  151. }
  152. if (isset($msgSend['type']) && $msgSend['type'] == 'news') {//如果是图文类型
  153. return $this->sendNews($content, $msgSend['id']);
  154. } elseif (isset($msgSend['type']) && $msgSend['type'] == 'img') {//如果是图片类型
  155. return $this->sendImage($content, $msgSend['id']);
  156. } elseif (isset($msgSend['type']) && $msgSend['type'] == 'voice') {//如果是语音类型
  157. return $this->sendVoice($content, $msgSend['id']);
  158. } elseif (isset($msgSend['type']) && $msgSend['type'] == 'video') {//如果是视频类型
  159. return $this->sendVideo($content, $msgSend);
  160. } else {
  161. return $this->sendText($content, $msgSend);
  162. }
  163. }
  164. /**
  165. * Des:发送文字
  166. * Name: sendText
  167. * @param $content
  168. * @param $msgSend
  169. * @return string
  170. * @author 倪宗锋
  171. */
  172. private function sendText($content, $msgSend)
  173. {
  174. $textTpl = '' . "
  175. <xml>
  176. <ToUserName><![CDATA[%s]]></ToUserName>
  177. <FromUserName><![CDATA[%s]]></FromUserName>
  178. <CreateTime>%s</CreateTime>
  179. <MsgType><![CDATA[%s]]></MsgType>
  180. <Content><![CDATA[%s]]></Content>
  181. </xml>";
  182. $msgType = "text";
  183. if (is_array($msgSend)) {
  184. $msgSend = $msgSend['text'];
  185. }
  186. $resultStr = sprintf($textTpl, $content['FromUserName'], $content['ToUserName'], time(), $msgType, $msgSend);
  187. return $resultStr;
  188. }
  189. /**
  190. * Des:发送图文
  191. * Name: sendNews
  192. * @param $content array
  193. * @param $mediaId string 素材图文 ID
  194. * @return string
  195. * @author 倪宗锋
  196. */
  197. private function sendNews($content, $mediaId)
  198. {
  199. $news = $this->getNewsByMediaId($mediaId);
  200. return $this->transmitNews($content, $news);
  201. }
  202. /**
  203. * Des:发送图片
  204. * Name: sendImage
  205. * @param $content
  206. * @param $mediaId
  207. * @return string
  208. * @author 倪宗锋
  209. */
  210. private function sendImage($content, $mediaId)
  211. {
  212. $xmlTpl = '' . "<xml>
  213. <ToUserName><![CDATA[%s]]></ToUserName>
  214. <FromUserName><![CDATA[%s]]></FromUserName>
  215. <CreateTime>%s</CreateTime>
  216. <MsgType><![CDATA[image]]></MsgType>
  217. <Image>
  218. <MediaId><![CDATA[%s]]></MediaId>
  219. </Image>
  220. </xml>";
  221. $result = sprintf($xmlTpl, $content['FromUserName'], $content['ToUserName'], time(), $mediaId);
  222. return $result;
  223. }
  224. /**
  225. * Des:发送语音
  226. * Name: sendVoice
  227. * @param $content
  228. * @param $mediaId
  229. * @return string
  230. * @author 倪宗锋
  231. */
  232. private function sendVoice($content, $mediaId)
  233. {
  234. $xmlTpl = '' . "<xml>
  235. <ToUserName><![CDATA[%s]]></ToUserName>
  236. <FromUserName><![CDATA[%s]]></FromUserName>
  237. <CreateTime>%s</CreateTime>
  238. <MsgType><![CDATA[voice]]></MsgType>
  239. <Voice>
  240. <MediaId><![CDATA[%s]]></MediaId>
  241. </Voice>
  242. </xml>";
  243. $result = sprintf($xmlTpl, $content['FromUserName'], $content['ToUserName'], time(), $mediaId);
  244. return $result;
  245. }
  246. /**
  247. * Des:发送视频
  248. * Name: sendVideo
  249. * @param $content
  250. * @param $sendMsg
  251. * @return string
  252. * @author 倪宗锋
  253. */
  254. private function sendVideo($content, $sendMsg)
  255. {
  256. $xmlTpl = '' . "<xml>
  257. <ToUserName><![CDATA[%s]]></ToUserName>
  258. <FromUserName><![CDATA[%s]]></FromUserName>
  259. <CreateTime>%s</CreateTime>
  260. <MsgType><![CDATA[video]]></MsgType>
  261. <Video>
  262. <MediaId><![CDATA[%s]]></MediaId>
  263. <Title><![CDATA[%s]]></Title>
  264. <Description><![CDATA[%s]]></Description>
  265. </Video>
  266. </xml>";
  267. $result = sprintf($xmlTpl, $content['FromUserName'], $content['ToUserName'], time(), $sendMsg['id'], $sendMsg["title"], $sendMsg["des"]);
  268. return $result;
  269. }
  270. /**
  271. * Des:根据ID获取图文信息
  272. * Name: getNewsByMediaId
  273. * @param $data_media_id
  274. * @return array
  275. * @author 倪宗锋
  276. */
  277. public function getNewsByMediaId($data_media_id)
  278. {
  279. $data_media_id = '{"media_id":"' . $data_media_id . '"}';
  280. $url = "https://api.weixin.qq.com/cgi-bin/material/get_material?access_token=" . $this->getAccessToken();
  281. $response = $this->_requestPost($url, $data_media_id);
  282. $media = json_decode($response, true);
  283. $mediaArray = $media['news_item'];
  284. $content = array();
  285. foreach ($mediaArray as $k => $v) {
  286. if ($k == 0 || $k == 1)
  287. $content[] = array("Title" => $v['title'], "Description" => $v['digest'], "PicUrl" => $v['thumb_url'], "Url" => $v['url']);
  288. elseif ($k == 2) {
  289. $content[] = array("Title" => $v['title'], "Description" => $v['digest'], "PicUrl" => $v['thumb_url'], "Url" => $v['content_source_url']);
  290. } else
  291. $content[] = array("Title" => $v['title'], "Description" => $v['digest'], "PicUrl" => $v['thumb_url'], "Url" => $v['content_source_url']);
  292. }
  293. return $content;
  294. }
  295. /**
  296. * Des:图文推送数据处理
  297. * Name: transmitNews
  298. * @param $content
  299. * @param $newsArray
  300. * @return string
  301. * @author 倪宗锋
  302. */
  303. private function transmitNews($content, $newsArray)
  304. {
  305. if (!is_array($newsArray)) {
  306. return '';
  307. }
  308. $itemTpl = '' . "<item><Title><![CDATA[%s]]></Title>
  309. <Description><![CDATA[%s]]></Description>
  310. <PicUrl><![CDATA[%s]]></PicUrl>
  311. <Url><![CDATA[%s]]></Url></item>";
  312. $item_str = "";
  313. foreach ($newsArray as $item) {
  314. $item_str .= sprintf($itemTpl, $item['Title'], $item['Description'], $item['PicUrl'], $item['Url']);
  315. }
  316. $xmlTpl = '' . "<xml>
  317. <ToUserName><![CDATA[{$content['FromUserName']}]]></ToUserName>
  318. <FromUserName><![CDATA[{$content['ToUserName']}]]></FromUserName>
  319. <CreateTime>" . time() . "</CreateTime>
  320. <MsgType><![CDATA[news]]></MsgType>
  321. <ArticleCount>" . count($newsArray) . "</ArticleCount>
  322. <Articles>$item_str</Articles>
  323. </xml>";
  324. return $xmlTpl;
  325. }
  326. /*************************=========第一次请求校验==========***********************************/
  327. /**
  328. * Des:第一次校验
  329. * Name: valid
  330. * @return bool
  331. * @author 倪宗锋
  332. */
  333. public function valid()
  334. {
  335. $echoStr = $_GET["echostr"];
  336. if ($this->checkSignature()) {
  337. $this->response = $echoStr;
  338. }
  339. return $this->response;
  340. }
  341. /***********************************通用函数*******************************************************/
  342. /**
  343. * Des:根据openid获取用户信息
  344. * Name: getUserInfoByOpenid
  345. * @param $openid
  346. * @return array
  347. * @author 倪宗锋
  348. */
  349. public static function getUserInfoByOpenid($openid)
  350. {
  351. $token = static::getAccessToken();
  352. $userInfo = static::getWeChatInfo($openid, $token);
  353. return $userInfo;
  354. }
  355. /**
  356. * Des:通用获取微信用户信息
  357. * Name: getWeChatInfo
  358. * @param $openid
  359. * @param $accessToken string 基础公共access_token
  360. * @return array
  361. * @author 倪宗锋
  362. */
  363. public static function getWeChatInfo($openid, $accessToken)
  364. {
  365. $query = array(
  366. 'access_token' => $accessToken,
  367. 'openid' => $openid,
  368. 'lang' => 'zh_CN'
  369. );
  370. $url = "https://api.weixin.qq.com/cgi-bin/user/info?";
  371. $url .= http_build_query($query);
  372. $curl = new CurlInterface('', 4);
  373. $arr = $curl->execute($url);
  374. $return = [
  375. 'nickname' => $arr['nickname'],
  376. 'headimgurl' => $arr['headimgurl'],
  377. 'sex' => $arr['sex'],
  378. 'country' => $arr['country'],
  379. 'city' => $arr['city'],
  380. 'province' => $arr['province']
  381. ];
  382. return $return;
  383. }
  384. /**
  385. * Des:授权登录获取用户信息
  386. * Name: getAuthWeChatInfo
  387. * @param $openid
  388. * @param $accessToken string 授权获取的accessToken
  389. * @return array
  390. * @author 倪宗锋
  391. */
  392. public static function getAuthWeChatInfo($openid, $accessToken)
  393. {
  394. $query = array(
  395. 'access_token' => $accessToken,
  396. 'openid' => $openid,
  397. 'lang' => 'zh_CN'
  398. );
  399. $url = "https://api.weixin.qq.com/sns/userinfo?";
  400. $url .= http_build_query($query);
  401. $curl = new CurlInterface('', 4);
  402. $arr = $curl->execute($url);
  403. $return = [
  404. 'nickname' => $arr['nickname'],
  405. 'headimgurl' => $arr['headimgurl'],
  406. 'sex' => $arr['sex'],
  407. 'country' => $arr['country'],
  408. 'city' => $arr['city'],
  409. 'province' => $arr['province']
  410. ];
  411. return $return;
  412. }
  413. /**
  414. * Des:数据校验
  415. * Name: checkSignature
  416. * @return bool
  417. * @author 倪宗锋
  418. */
  419. private function checkSignature()
  420. {
  421. $token = $this->token;
  422. $signature = isset($_GET["signature"]) ? $_GET["signature"] : "";
  423. $timestamp = isset($_GET["timestamp"]) ? $_GET["timestamp"] : "";
  424. $nonce = isset($_GET["nonce"]) ? $_GET["nonce"] : "";
  425. $tmpArr = array($token, $timestamp, $nonce);
  426. sort($tmpArr, SORT_STRING);
  427. $tmpStr = implode($tmpArr);
  428. $tmpStr = sha1($tmpStr);
  429. if ($tmpStr == $signature) {
  430. return true;
  431. } else {
  432. return false;
  433. }
  434. }
  435. /**
  436. * Des:参数解析
  437. * Name: getContent
  438. * @author 倪宗锋
  439. */
  440. private function getContent()
  441. {
  442. $content = file_get_contents("php://input");
  443. libxml_disable_entity_loader(true);
  444. $this->request = (array)simplexml_load_string($content, 'SimpleXMLElement', LIBXML_NOCDATA);
  445. return $this->request;
  446. }
  447. /**
  448. * Des:获取token
  449. * Name: getAccessToken
  450. * @param $appid
  451. * @return string
  452. * @author 倪宗锋
  453. */
  454. public static function getAccessToken($appid = '')
  455. {
  456. $wxConfig = Util::getWeChatConfig($appid);
  457. $appid = $wxConfig['appid'];
  458. $appsecret = $wxConfig['appsecret'];
  459. $access_token = static::getWxAccessToken($appid, $appsecret);
  460. return $access_token;
  461. }
  462. /**
  463. * Des:获取指定的微信公众号的token
  464. * Name: getWxAccessToken
  465. * @param $appid
  466. * @param $appsecret
  467. * @return mixed|string
  468. * @author 倪宗锋
  469. */
  470. public static function getWxAccessToken($appid, $appsecret)
  471. {
  472. $key = $appid . 'access_token';
  473. $memcache = \Yii::$app->getCache();
  474. $access_token = $memcache->get($key);
  475. if (empty($access_token)) {
  476. $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$appsecret}";
  477. $getToken = self::_requestGet($url);//发起get请求获取token
  478. $res = json_decode($getToken, true);//json转换成数组
  479. if (empty($res['access_token'])) {
  480. return '';
  481. }
  482. $access_token = $res['access_token'];
  483. $memcache->set($key, $access_token, 3600);
  484. }
  485. return $access_token;
  486. }
  487. /**
  488. * Function Description:根据code获取token
  489. * Function Name: getToken
  490. * @param $code
  491. *
  492. * @return array
  493. *
  494. * @author 倪宗锋
  495. */
  496. public static function getToken($code)
  497. {
  498. $WxPayConfig = Util::getWeChatConfig();
  499. $siteConfig = Util::getSiteConfig();
  500. $urlObj["appid"] = $WxPayConfig['appid'];
  501. $urlObj["secret"] = $WxPayConfig['appsecret'];
  502. $urlObj["code"] = $code;
  503. $urlObj["grant_type"] = "authorization_code";
  504. $bizString = http_build_query($urlObj);
  505. $url = $siteConfig['authTokenUrl'] . $bizString;
  506. $curlInterface = new CurlInterface('', 4);
  507. $curlInterface->setBaseUrl($url);
  508. $getToken = $curlInterface->execute('', 'GET');
  509. if (empty($getToken['openid'])) {
  510. return Util::returnArrEr('参数无效!');
  511. }
  512. return Util::returnArrSu('', $getToken);
  513. }
  514. /**
  515. * Des:发起get请求
  516. * Name: _requestGet
  517. * @param $url string
  518. * @param bool|true $ssl
  519. * @return bool|mixed
  520. * @author 倪宗锋
  521. */
  522. public static function _requestGet($url, $ssl = true)
  523. {
  524. $curl = curl_init();
  525. curl_setopt($curl, CURLOPT_URL, $url);
  526. curl_setopt($curl, CURLOPT_AUTOREFERER, true);
  527. if ($ssl) {
  528. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  529. curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
  530. }
  531. curl_setopt($curl, CURLOPT_HEADER, false);
  532. curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  533. $response = curl_exec($curl);
  534. if ($response === false) {
  535. return false;
  536. }
  537. return $response;
  538. }
  539. /**
  540. * Des:发起post请求
  541. * Name: _requestPost
  542. * @param $url
  543. * @param $data
  544. * @param bool|true $ssl
  545. * @return bool|mixed
  546. * @author 倪宗锋
  547. */
  548. public static function _requestPost($url, $data, $ssl = true)
  549. {
  550. $curl = curl_init();
  551. curl_setopt($curl, CURLOPT_URL, $url);
  552. $user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '';
  553. curl_setopt($curl, CURLOPT_USERAGENT, $user_agent);
  554. curl_setopt($curl, CURLOPT_AUTOREFERER, true);
  555. if ($ssl) {
  556. curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  557. curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
  558. }
  559. curl_setopt($curl, CURLOPT_POST, true);
  560. curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
  561. curl_setopt($curl, CURLOPT_HEADER, false);
  562. curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  563. $response = curl_exec($curl);
  564. if ($response === false) {
  565. return false;
  566. }
  567. return $response;
  568. }
  569. /**
  570. * Des:获取
  571. * Name: httpRequest
  572. * @param $url
  573. * @param null $data
  574. * @return mixed
  575. * @author 倪宗锋
  576. */
  577. static function httpRequest($url, $data = null)
  578. {
  579. $ch = curl_init();
  580. curl_setopt($ch, CURLOPT_URL, $url);
  581. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  582. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  583. if (!empty($data)) {
  584. curl_setopt($ch, CURLOPT_POST, 1);
  585. curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
  586. }
  587. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  588. $output = curl_exec($ch);
  589. curl_close($ch);
  590. return $output;
  591. }
  592. /**
  593. * 分销用户二维码
  594. */
  595. public static function getFxQrCode($fx_uid)
  596. {
  597. $config = Util::getSiteConfig();
  598. $imgUrl = ROOT_PATH . '/web/fx/images/FxQrCode/' . $fx_uid . '.png';
  599. $showUrl = $config['host_name'] . '/web/fx/images/FxQrCode/' . $fx_uid . '.png';
  600. if (file_exists($imgUrl)) {
  601. return Util::returnArrSu('', array('url' => $showUrl));
  602. }
  603. $logo = ROOT_PATH . '/web/fx/images/logo.png';
  604. $qRCode = $config['host_name'] . '/shop/?r=weChat/we-chat/q-r-code-home&id=' . $fx_uid;
  605. $addFlag = Util::addQRCode($qRCode, $imgUrl, 1, true, false, $logo);
  606. if ($addFlag['flag'] == false) {
  607. return Util::returnArrEr('生成二维码失败!');
  608. }
  609. return Util::returnArrSu('', array('url' => $showUrl));
  610. }
  611. public static function getSignPackage($url)
  612. {
  613. $jsapiTicket = static::getJsApiTicket();
  614. // 注意 URL 一定要动态获取,不能 hardcode.
  615. // $url = "http://nwx.zhizhuchuxing.cn/web/shop/test.html";
  616. $timestamp = time();
  617. $nonceStr = WeChatPay::getNonceStr(16);
  618. // 这里参数的顺序要按照 key 值 ASCII 码升序排序
  619. $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr&timestamp=$timestamp&url=$url";
  620. $signature = sha1($string);
  621. $config = Util::getWeChatConfig();
  622. $signPackage = array(
  623. "appId" => $config['appid'],
  624. "nonceStr" => $nonceStr,
  625. "timestamp" => $timestamp,
  626. "url" => $url,
  627. "signature" => $signature,
  628. "rawString" => $string
  629. );
  630. return $signPackage;
  631. }
  632. public static function getJsApiTicket()
  633. {
  634. // jsapi_ticket 应该全局存储与更新,以下代码以写入到文件中做示例
  635. $cache = \Yii::$app->cache;
  636. $data = $cache->get('jsapiticket');
  637. if (empty($data['expire_time']) || $data['expire_time'] < time()) {
  638. $accessToken = static::getAccessToken();
  639. // 如果是企业号用以下 URL 获取 ticket
  640. // $url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=$accessToken";
  641. $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$accessToken";
  642. $curl = new CurlInterface('', 5);
  643. $res = json_decode($curl->execute($url), true);
  644. $ticket = $res['ticket'];
  645. if ($ticket) {
  646. $data = [];
  647. $data['expire_time'] = time() + 7000;
  648. $data['jsapi_ticket'] = $ticket;
  649. $cache->set('jsapiticket', $data);
  650. }
  651. } else {
  652. $ticket = $data['jsapi_ticket'];
  653. }
  654. return $ticket;
  655. }
  656. /**
  657. * 发送自定义的模板消息
  658. * @param $toUser
  659. * @param $template
  660. * @param $url
  661. * @param $data
  662. * @param $appid string 默认当前系统的微信配置 ,可更换为 其他微信公众号的配置
  663. * @param string $topColor
  664. * @return bool
  665. */
  666. public static function sendWxTemplate($toUser, $template, $url, $data, $topColor = '#7B68EE', $appid = '')
  667. {
  668. if ($appid != '') {
  669. Util::setSiteConfig('entryAuthWeChat', $appid);//变更微信公众号配置
  670. }
  671. $wxConfig = Util::getWeChatConfig();
  672. $template_config = require ROOT_PATH.'/common/config/wechatConfig/wxInterface/'.$wxConfig['mch_id'].'/Wx.msg.template.config.php';
  673. if (empty($template_config[$template])){
  674. return false;
  675. }
  676. $template = array(
  677. 'touser' => $toUser,
  678. 'template_id' => $template_config[$template],
  679. 'url' => $url,
  680. 'topcolor' => $topColor,
  681. 'data' => $data
  682. );
  683. $token = static::getAccessToken();
  684. $url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" . $token;
  685. $curl = new CurlInterface($template, 1);
  686. $dataRes = $curl->execute($url, 'post');
  687. if ($dataRes['errcode'] == 0) {
  688. return true;
  689. } else {
  690. return false;
  691. }
  692. }
  693. }