token = $wxConfig['token']; $this->appid = $wxConfig['appid']; $this->appsecret = $wxConfig['appsecret']; } /** * Des:接收参数并处理返回值 * Name: exec * @return string * @author 倪宗锋 */ public function exec() { $content = $this->getContent();//获取参数并解析 if ($content['MsgType'] == 'text') { $this->response = $this->textMsg($content); } elseif ($content['MsgType'] == 'event') { $this->response = $this->eventMsg($content); } return $this->response; } /** * Des:用户输入内容处理 * Name: textMsg * @param $content * @return bool|string * @author 倪宗锋 */ public function textMsg($content) { // $textTpl = " // // // //%s // //"; // $resultStr = sprintf($textTpl, $content['FromUserName'], $content['ToUserName'], time()); // return $resultStr; $word = $content['Content']; return $this->send($word, $content, 'text'); } /** * Des:推送事件处理 * Name: eventMsg * @param $content * @return string * @author 倪宗锋 */ public function eventMsg($content) { if ($content['Event'] == 'subscribe') {//微信关注事件 发送欢迎语 $word = 'subscribe'; } elseif ($content['Event'] == 'unsubscribe') {//微信关注事件 发送欢迎语 $word = 'unsubscribe'; } elseif ($content['Event'] == 'SCAN') {//扫一扫 $word = 'SCAN'; } else if ($content['Event'] == 'VIEW' || empty($content['EventKey'])) { return false; } else { $word = $content['EventKey']; } if ($word == 'MSG_LIANXIKEFU') { return $this->callCuster($content); } return $this->send($word, $content, 'event'); } /** * Des:联系客服 * Name: sendText * @param $content * @return string * @author 倪宗锋 */ private function callCuster($content) { $textTpl = '' . " %s "; $resultStr = sprintf($textTpl, $content['FromUserName'], $content['ToUserName'], time()); return $resultStr; } /** * Des: 发送处理 * Name: send * @param $word * @param $content * @param string $type 触发类型:text用户输入 event推送事件 * @return string * @author 倪宗锋 */ public function send($word, $content, $type = 'text') { $weChatPayConfig = Util::getWeChatConfig(); $textConfig = require ROOT_PATH . '/common/config/wechatConfig/wxInterface/' . $weChatPayConfig['mch_id'] . '/Wx.' . $type . '.config.php'; if (empty($textConfig[$word]) == false) {//如果 有指定的配置就用指定的配置 $msgSend = $textConfig[$word]; } else if ($type == 'text') {//没有指定的配置 且 接收的是用户输入文本信息 // $info = new WxDoFunction(); // $getDoResult = $info->showOrderInfo($word);//获取订单信息暂时停止 //todo 获取订单信息 // if ($getDoResult == '') { // //默认联系客服 // $msgSend = $this->callCuster($content); // return $msgSend; // } else { // $msgSend = $getDoResult; // } //默认联系客服 $msgSend = $this->callCuster($content); return $msgSend; } else {//没有指定配置 且接收的是按钮或扫一扫则直接返回关注自动回复信息 $msgSend = $textConfig['subscribe']; } if (is_array($msgSend) && empty($msgSend['function']) == false) {//当推送事件有方法指定时,则调用该方法 $wxDoFunction = new WxDoFunction(); $function = $msgSend['function']; $wxDoFunction->$function($content); } if (isset($msgSend['type']) && $msgSend['type'] == 'news') {//如果是图文类型 return $this->sendNews($content, $msgSend['id']); } elseif (isset($msgSend['type']) && $msgSend['type'] == 'img') {//如果是图片类型 return $this->sendImage($content, $msgSend['id']); } elseif (isset($msgSend['type']) && $msgSend['type'] == 'voice') {//如果是语音类型 return $this->sendVoice($content, $msgSend['id']); } elseif (isset($msgSend['type']) && $msgSend['type'] == 'video') {//如果是视频类型 return $this->sendVideo($content, $msgSend); } else { return $this->sendText($content, $msgSend); } } /** * Des:发送文字 * Name: sendText * @param $content * @param $msgSend * @return string * @author 倪宗锋 */ private function sendText($content, $msgSend) { $textTpl = '' . " %s "; $msgType = "text"; if (is_array($msgSend)) { $msgSend = $msgSend['text']; } $resultStr = sprintf($textTpl, $content['FromUserName'], $content['ToUserName'], time(), $msgType, $msgSend); return $resultStr; } /** * Des:发送图文 * Name: sendNews * @param $content array * @param $mediaId string 素材图文 ID * @return string * @author 倪宗锋 */ private function sendNews($content, $mediaId) { $news = $this->getNewsByMediaId($mediaId); return $this->transmitNews($content, $news); } /** * Des:发送图片 * Name: sendImage * @param $content * @param $mediaId * @return string * @author 倪宗锋 */ private function sendImage($content, $mediaId) { $xmlTpl = '' . " %s "; $result = sprintf($xmlTpl, $content['FromUserName'], $content['ToUserName'], time(), $mediaId); return $result; } /** * Des:发送语音 * Name: sendVoice * @param $content * @param $mediaId * @return string * @author 倪宗锋 */ private function sendVoice($content, $mediaId) { $xmlTpl = '' . " %s "; $result = sprintf($xmlTpl, $content['FromUserName'], $content['ToUserName'], time(), $mediaId); return $result; } /** * Des:发送视频 * Name: sendVideo * @param $content * @param $sendMsg * @return string * @author 倪宗锋 */ private function sendVideo($content, $sendMsg) { $xmlTpl = '' . " %s "; $result = sprintf($xmlTpl, $content['FromUserName'], $content['ToUserName'], time(), $sendMsg['id'], $sendMsg["title"], $sendMsg["des"]); return $result; } /** * Des:根据ID获取图文信息 * Name: getNewsByMediaId * @param $data_media_id * @return array * @author 倪宗锋 */ public function getNewsByMediaId($data_media_id) { $data_media_id = '{"media_id":"' . $data_media_id . '"}'; $url = "https://api.weixin.qq.com/cgi-bin/material/get_material?access_token=" . $this->getAccessToken(); $response = $this->_requestPost($url, $data_media_id); $media = json_decode($response, true); $mediaArray = $media['news_item']; $content = array(); foreach ($mediaArray as $k => $v) { if ($k == 0 || $k == 1) $content[] = array("Title" => $v['title'], "Description" => $v['digest'], "PicUrl" => $v['thumb_url'], "Url" => $v['url']); elseif ($k == 2) { $content[] = array("Title" => $v['title'], "Description" => $v['digest'], "PicUrl" => $v['thumb_url'], "Url" => $v['content_source_url']); } else $content[] = array("Title" => $v['title'], "Description" => $v['digest'], "PicUrl" => $v['thumb_url'], "Url" => $v['content_source_url']); } return $content; } /** * Des:图文推送数据处理 * Name: transmitNews * @param $content * @param $newsArray * @return string * @author 倪宗锋 */ private function transmitNews($content, $newsArray) { if (!is_array($newsArray)) { return ''; } $itemTpl = '' . "<![CDATA[%s]]> "; $item_str = ""; foreach ($newsArray as $item) { $item_str .= sprintf($itemTpl, $item['Title'], $item['Description'], $item['PicUrl'], $item['Url']); } $xmlTpl = '' . " " . time() . " " . count($newsArray) . " $item_str "; return $xmlTpl; } /*************************=========第一次请求校验==========***********************************/ /** * Des:第一次校验 * Name: valid * @return bool * @author 倪宗锋 */ public function valid() { $echoStr = $_GET["echostr"]; if ($this->checkSignature()) { $this->response = $echoStr; } return $this->response; } /***********************************通用函数*******************************************************/ /** * Des:根据openid获取用户信息 * Name: getUserInfoByOpenid * @param $openid * @return array * @author 倪宗锋 */ public static function getUserInfoByOpenid($openid) { $token = static::getAccessToken(); $userInfo = static::getWeChatInfo($openid, $token); return $userInfo; } /** * Des:通用获取微信用户信息 * Name: getWeChatInfo * @param $openid * @param $accessToken string 基础公共access_token * @return array * @author 倪宗锋 */ public static function getWeChatInfo($openid, $accessToken) { $query = array( 'access_token' => $accessToken, 'openid' => $openid, 'lang' => 'zh_CN' ); $url = "https://api.weixin.qq.com/cgi-bin/user/info?"; $url .= http_build_query($query); $curl = new CurlInterface('', 4); $arr = $curl->execute($url); $return = [ 'nickname' => $arr['nickname'], 'headimgurl' => $arr['headimgurl'], 'sex' => $arr['sex'], 'country' => $arr['country'], 'city' => $arr['city'], 'province' => $arr['province'] ]; return $return; } /** * Des:授权登录获取用户信息 * Name: getAuthWeChatInfo * @param $openid * @param $accessToken string 授权获取的accessToken * @return array * @author 倪宗锋 */ public static function getAuthWeChatInfo($openid, $accessToken) { $query = array( 'access_token' => $accessToken, 'openid' => $openid, 'lang' => 'zh_CN' ); $url = "https://api.weixin.qq.com/sns/userinfo?"; $url .= http_build_query($query); $curl = new CurlInterface('', 4); $arr = $curl->execute($url); $return = [ 'nickname' => $arr['nickname'], 'headimgurl' => $arr['headimgurl'], 'sex' => $arr['sex'], 'country' => $arr['country'], 'city' => $arr['city'], 'province' => $arr['province'] ]; return $return; } /** * Des:数据校验 * Name: checkSignature * @return bool * @author 倪宗锋 */ private function checkSignature() { $token = $this->token; $signature = isset($_GET["signature"]) ? $_GET["signature"] : ""; $timestamp = isset($_GET["timestamp"]) ? $_GET["timestamp"] : ""; $nonce = isset($_GET["nonce"]) ? $_GET["nonce"] : ""; $tmpArr = array($token, $timestamp, $nonce); sort($tmpArr, SORT_STRING); $tmpStr = implode($tmpArr); $tmpStr = sha1($tmpStr); if ($tmpStr == $signature) { return true; } else { return false; } } /** * Des:参数解析 * Name: getContent * @author 倪宗锋 */ private function getContent() { $content = file_get_contents("php://input"); libxml_disable_entity_loader(true); $this->request = (array)simplexml_load_string($content, 'SimpleXMLElement', LIBXML_NOCDATA); return $this->request; } /** * Des:获取token * Name: getAccessToken * @param $appid * @return string * @author 倪宗锋 */ public static function getAccessToken($appid = '') { $wxConfig = Util::getWeChatConfig($appid); $appid = $wxConfig['appid']; $appsecret = $wxConfig['appsecret']; $access_token = static::getWxAccessToken($appid, $appsecret); return $access_token; } /** * Des:获取指定的微信公众号的token * Name: getWxAccessToken * @param $appid * @param $appsecret * @return mixed|string * @author 倪宗锋 */ public static function getWxAccessToken($appid, $appsecret) { $key = $appid . 'access_token'; $memcache = \Yii::$app->getCache(); $access_token = $memcache->get($key); if (empty($access_token)) { $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$appsecret}"; $getToken = self::_requestGet($url);//发起get请求获取token $res = json_decode($getToken, true);//json转换成数组 if (empty($res['access_token'])) { return ''; } $access_token = $res['access_token']; $memcache->set($key, $access_token, 3600); } return $access_token; } /** * Function Description:根据code获取token * Function Name: getToken * @param $code * * @return array * * @author 倪宗锋 */ public static function getToken($code) { $WxPayConfig = Util::getWeChatConfig(); $siteConfig = Util::getSiteConfig(); $urlObj["appid"] = $WxPayConfig['appid']; $urlObj["secret"] = $WxPayConfig['appsecret']; $urlObj["code"] = $code; $urlObj["grant_type"] = "authorization_code"; $bizString = http_build_query($urlObj); $url = $siteConfig['authTokenUrl'] . $bizString; $curlInterface = new CurlInterface('', 4); $curlInterface->setBaseUrl($url); $getToken = $curlInterface->execute('', 'GET'); if (empty($getToken['openid'])) { return Util::returnArrEr('参数无效!'); } return Util::returnArrSu('', $getToken); } /** * Des:发起get请求 * Name: _requestGet * @param $url string * @param bool|true $ssl * @return bool|mixed * @author 倪宗锋 */ public static function _requestGet($url, $ssl = true) { $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_AUTOREFERER, true); if ($ssl) { curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); } curl_setopt($curl, CURLOPT_HEADER, false); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($curl); if ($response === false) { return false; } return $response; } /** * Des:发起post请求 * Name: _requestPost * @param $url * @param $data * @param bool|true $ssl * @return bool|mixed * @author 倪宗锋 */ public static function _requestPost($url, $data, $ssl = true) { $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); $user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ''; curl_setopt($curl, CURLOPT_USERAGENT, $user_agent); curl_setopt($curl, CURLOPT_AUTOREFERER, true); if ($ssl) { curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); } curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, $data); curl_setopt($curl, CURLOPT_HEADER, false); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($curl); if ($response === false) { return false; } return $response; } /** * Des:获取 * Name: httpRequest * @param $url * @param null $data * @return mixed * @author 倪宗锋 */ static function httpRequest($url, $data = null) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); if (!empty($data)) { curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); } curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); $output = curl_exec($ch); curl_close($ch); return $output; } /** * 分销用户二维码 */ public static function getFxQrCode($fx_uid) { $config = Util::getSiteConfig(); $imgUrl = ROOT_PATH . '/web/fx/images/FxQrCode/' . $fx_uid . '.png'; $showUrl = $config['host_name'] . '/web/fx/images/FxQrCode/' . $fx_uid . '.png'; if (file_exists($imgUrl)) { return Util::returnArrSu('', array('url' => $showUrl)); } $logo = ROOT_PATH . '/web/fx/images/logo.png'; $qRCode = $config['host_name'] . '/shop/?r=weChat/we-chat/q-r-code-home&id=' . $fx_uid; $addFlag = Util::addQRCode($qRCode, $imgUrl, 1, true, false, $logo); if ($addFlag['flag'] == false) { return Util::returnArrEr('生成二维码失败!'); } return Util::returnArrSu('', array('url' => $showUrl)); } public static function getSignPackage($url) { $jsapiTicket = static::getJsApiTicket(); // 注意 URL 一定要动态获取,不能 hardcode. // $url = "http://nwx.zhizhuchuxing.cn/web/shop/test.html"; $timestamp = time(); $nonceStr = WeChatPay::getNonceStr(16); // 这里参数的顺序要按照 key 值 ASCII 码升序排序 $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr×tamp=$timestamp&url=$url"; $signature = sha1($string); $config = Util::getWeChatConfig(); $signPackage = array( "appId" => $config['appid'], "nonceStr" => $nonceStr, "timestamp" => $timestamp, "url" => $url, "signature" => $signature, "rawString" => $string ); return $signPackage; } public static function getJsApiTicket() { // jsapi_ticket 应该全局存储与更新,以下代码以写入到文件中做示例 $cache = \Yii::$app->cache; $data = $cache->get('jsapiticket'); if (empty($data['expire_time']) || $data['expire_time'] < time()) { $accessToken = static::getAccessToken(); // 如果是企业号用以下 URL 获取 ticket // $url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=$accessToken"; $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$accessToken"; $curl = new CurlInterface('', 5); $res = json_decode($curl->execute($url), true); $ticket = $res['ticket']; if ($ticket) { $data = []; $data['expire_time'] = time() + 7000; $data['jsapi_ticket'] = $ticket; $cache->set('jsapiticket', $data); } } else { $ticket = $data['jsapi_ticket']; } return $ticket; } /** * 发送自定义的模板消息 * @param $toUser * @param $template * @param $url * @param $data * @param $appid string 默认当前系统的微信配置 ,可更换为 其他微信公众号的配置 * @param string $topColor * @return bool */ public static function sendWxTemplate($toUser, $template, $url, $data, $topColor = '#7B68EE', $appid = '') { if ($appid != '') { Util::setSiteConfig('entryAuthWeChat', $appid);//变更微信公众号配置 } $wxConfig = Util::getWeChatConfig(); $template_config = require ROOT_PATH.'/common/config/wechatConfig/wxInterface/'.$wxConfig['mch_id'].'/Wx.msg.template.config.php'; if (empty($template_config[$template])){ return false; } $template = array( 'touser' => $toUser, 'template_id' => $template_config[$template], 'url' => $url, 'topcolor' => $topColor, 'data' => $data ); $token = static::getAccessToken(); $url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" . $token; $curl = new CurlInterface($template, 1); $dataRes = $curl->execute($url, 'post'); if ($dataRes['errcode'] == 0) { return true; } else { return false; } } }