sWechatAccessToken.'_'.$this->sAppID); //判断缓存是否存在 if (!$sToken) { //不存在 //组装接口地址 $sUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . $this->sAppID . "&secret=" . $this->sAppSecret; $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $sUrl); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($curl, CURLOPT_TIMEOUT, $this->timeout); $result = curl_exec($curl); //请求失败 if (curl_errno($curl)){ $this->sError = curl_errno($curl); curl_close($curl); return FALSE; } $result = json_decode($result, true); if (!empty($result['access_token'])) { $sToken = $result['access_token']; Cache::set($this->sWechatAccessToken.'_'.$this->sAppID, $sToken, 7000); // 有效期7200秒 } curl_close($curl); } return $sToken; } /** * CURL 发送请求上传永久素材 * @param $sToken Token * @param $sPath 图片地址 */ public function uploadMaterial($aParam = []) { $aParam = empty($aParam) ? $this->request->post() : $aParam; //图片地址 $sPath = empty($aParam['image_url']) ? '' : $aParam['image_url']; if(empty($sPath)){ return json_encode(['status' => 2,'msg' => 'Please choose to upload materials']); } // 获取微信公众号APPID和APPKEY $this->sAppID = empty($aParam['wechat_app_id']) ? '' : $aParam['wechat_app_id']; $this->sAppSecret = empty($aParam['wechat_app_secret']) ? '' : $aParam['wechat_app_secret']; if(empty($this->sAppID) || empty($this->sAppSecret)){ return json_encode(['status' => 2,'msg' => 'Please configure the AppID and AppSecret']); } $sType = empty($aParam['type']) ? 'image' : $aParam['type'];//文件类型 // 验证文件有效性 if (!file_exists($sPath)) { return json_encode(['status' => 3,'msg' => 'The material does not exist'.$sPath]); } if (!is_readable($sPath)) { return json_encode(['status' => 3,'msg' => 'The material is unreadable']); } if (filesize($sPath) > 10 * 1024 * 1024) { return json_encode(['status' => 4,'msg' => 'The material cannot exceed 10MB']); } //获取Token $sToken = $this->getAccessToken(); if (empty($sToken)) { return json_encode(['status' => 5, 'msg' => 'Failed to obtain access_token']); } //CURL 请求接口 //文件参数 $data = [ 'media' => new \CURLFile( realpath($sPath), mime_content_type($sPath), // 自动检测MIME类型 basename($sPath) // 上传后的文件名 ), // 关键:使用CURLFile对象 ]; $sUrl = "https://api.weixin.qq.com/cgi-bin/material/add_material?access_token={$sToken}&type={$sType}"; $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $sUrl); curl_setopt($curl, CURLOPT_POST, true); //设置为POST方式 curl_setopt($curl, CURLOPT_POSTFIELDS, $data); curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE) ; // 获取数据返回 curl_setopt($curl, CURLOPT_PROXY,$this->proxy); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER,true); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,false); //执行 $response = curl_exec($curl); //请求失败 if (curl_errno($curl)){ curl_close($curl); return json_encode(['status' => 6,'msg' => "Network request failed: " . curl_errno($curl)]); } curl_close($curl);//关闭请求 //获取返回结果 $response = json_decode($response, true); if (!empty($response['errcode']) && $response['errcode'] != 0) { return json_encode(['status' => 7,'msg' => "WeChat interface error: [{$response['errcode']}] {$response['errmsg']}"]); } //插入数据库 if(empty($response['media_id'])){ return json_encode(['status' => 8,'msg' => "Unable to obtain uploaded materials"]); } return json_encode(['status' => 1,'msg' => 'success','data' => $response]); } /** * CURL 发送请求到 微信公众号 * @param $messages 内容 * @param $model 模型类型 */ private function curlWechatApi($sUrl = '',$sJsonData = ''){ //发送CURL请求 $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $sUrl); curl_setopt($curl, CURLOPT_POST, true); curl_setopt($curl, CURLOPT_POSTFIELDS, $sJsonData); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_HTTPHEADER, [ 'Content-Type: application/json', 'Content-Length: ' . strlen($sJsonData) ]); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true); // 关闭SSL验证(生产环境建议开启) $response = curl_exec($curl); //请求失败 if (curl_errno($curl)){ curl_close($curl); return ['status' => 2,'msg' => "Network request failed: " . curl_errno($curl)]; } curl_close($curl);//关闭请求 // 数据处理 $response = json_decode($response, true); if (!empty($response['errcode'])) { return ['status' => 3, 'msg' => 'WeChat interface error:'.$response['errmsg'] ?? $response['errcode']]; } return ['status' => 1,'msg' => 'success','data' => $response]; } /** * CURL 添加文章到草稿箱 * @param $sToken Token * @param $sPath 图片地址 */ public function addDraft($aParam = []){ $aParam = empty($aParam) ? $this->request->post() : $aParam; //文章ID $iArticleId = empty($aParam['article_id']) ? '' : $aParam['article_id']; if(empty($iArticleId)){ return json_encode(['status' => 2,'msg' => 'article_id is empty']); } //模版ID $iTemplateId = empty($aParam['template_id']) ? '' : $aParam['template_id']; if(empty($iTemplateId)){ return json_encode(['status' => 2,'msg' => 'Template ID is empty']); } //发布公众号ID $sWechatId = empty($aParam['wechat_id']) ? 0 : $aParam['wechat_id']; if(empty($sWechatId)){ return json_encode(['status' => 2,'msg' => 'Please select the official account to be pushed']); } //生成模版内容 $sContent = empty($aParam['content']) ? '' : $aParam['content']; if(empty($sContent)){ return json_encode(['status' => 2,'msg' => 'The published content is empty']); } // 获取微信公众号APPID和APPKEY $this->sAppID = empty($aParam['wechat_app_id']) ? '' : $aParam['wechat_app_id']; $this->sAppSecret = empty($aParam['wechat_app_secret']) ? '' : $aParam['wechat_app_secret']; if(empty($this->sAppID) || empty($this->sAppSecret)){ return json_encode(['status' => 2,'msg' => 'Please configure the AppID and AppSecret']); } //获取Token $sToken = $this->getAccessToken(); if (empty($sToken)) { return json_encode(['status' => 5, 'msg' => 'Failed to obtain access_token']); } //发送CURL请求 $sUrl = "https://api.weixin.qq.com/cgi-bin/draft/add?access_token={$sToken}"; //参数组装 $sJsonData = json_encode([ 'articles' => [$aParam] ], JSON_UNESCAPED_UNICODE); $aCurlResult = $this->curlWechatApi($sUrl,$sJsonData); if($aCurlResult['status'] != 1){ return json_encode($aCurlResult); } $response = empty($aCurlResult['data']) ? [] : $aCurlResult['data']; //判断是否推送成功 if(empty($response['media_id'])){ return json_encode(['status' => 5,'msg' => "Unable to obtain the uploaded draft"]); } //判断文章类型 $article_type = empty($aParam['article_type']) ? 'news' : $aParam['article_type']; if(!in_array($article_type, ['news','newspic'])){ return json_encode(['status' => 6,'msg' => "The article type does not match"]); } //是否打开评论,0不打开(默认),1打开 $need_open_comment = empty($aParam['need_open_comment']) ? 1 : $aParam['need_open_comment']; //是否粉丝才可评论,0所有人可评论(默认),1粉丝才可评论 $only_fans_can_comment = empty($aParam['only_fans_can_comment']) ? 1 : $aParam['only_fans_can_comment']; //插入文章表 $aParam = ['media_id' => $response['media_id'],'update_time' => time(),'template_id' => $iTemplateId,'template_content' => $sContent,'article_id' => $iArticleId,'article_type' => $article_type,'need_open_comment' => $need_open_comment,'only_fans_can_comment' => $only_fans_can_comment,'template_id' => $iTemplateId,'create_time' => time(),'wechat_id' => $sWechatId]; $result = Db::name('ai_wechat_article')->insert($aParam); if($result === false){ return json_encode(['status' => 8,'msg' => "Article data insertion failed"]); } return json_encode(['status' => 1,'msg' => 'Upload draft box successfully','data' => []]); } /** * CURL 获取草稿箱的文章 * @param $sToken Token * @param media_id string 微信公众号media_id */ public function getDraft($sMediaId = ''){ //返回结果数组 $aResult = ['status' => 1,'msg' => 'Successfully obtained draft','data' => []]; //获取参数 $aParam = $this->request->post(); $sMediaId = empty($sMediaId) ? $aParam['media_id'] : $sMediaId; if(empty($sMediaId)){ return json_encode(['status' => 2, 'msg' => 'Parameter: media_id cannot be empty']); } //查询关联文章信息 $aArticle = Db::name('ai_wechat_article')->field('media_id')->where(['media_id'=>$sMediaId])->find(); if(empty($aArticle)){ return json_encode(['status' => 3,'msg' => 'The article does not exist']); } //获取Token $sToken = $this->getAccessToken(); if (empty($sToken)) { return json_encode(['status' => 4, 'msg' => 'Failed to obtain access_token']); } //CURL请求 $sUrl = "https://api.weixin.qq.com/cgi-bin/draft/get?access_token={$sToken}"; //参数组装 $sJsonData = json_encode([ 'media_id' => $aArticle['media_id'] ], JSON_UNESCAPED_UNICODE); //发送CURL请求 $aCurlResult = $this->curlWechatApi($sUrl,$sJsonData); if($aCurlResult['status'] != 1){ return json_encode(['status' => 5,'msg' => 'Acquisition failed']); } $response = empty($aCurlResult['data']) ? [] : $aCurlResult['data']; $aResult['data'] = $response['news_item'] ?? []; return json_encode($aResult); } /** * CURL 发布草稿箱的文章 * @param $sToken Token * @param article_id int 文章ID */ public function publishDraft($sMediaId = ''){ //返回结果数组 $aResult = ['status' => 1,'msg' => 'Draft box article successfully published','data' => []]; //获取参数 $aParam = $this->request->post(); $sMediaId = empty($sMediaId) ? $aParam['media_id'] : $sMediaId; if(empty($sMediaId)){//为空 //必填参数验证 //文章ID $iArticleId = empty($aParam['article_id']) ? '' : $aParam['article_id']; //模版ID $iTemplateId = empty($aParam['template_id']) ? '' : $aParam['template_id']; if(empty($iArticleId) || empty($iTemplateId)){ return json_encode(['status' => 2,'msg' => 'Please select the article or article template to publish']); } //获取文章信息 $aAiContent = json_decode($this->getAiArticle($iArticleId,1),true); $aAiContent = empty($aAiContent['data']) ? [] : $aAiContent['data']; $aAiArticle = empty($aAiContent['ai_article']) ? [] : $aAiContent['ai_article']; //判断是否生成AI内容 if(empty($aAiArticle)){ return json_encode(['status' => 3, 'msg' => 'The article content of WeChat official account has not been generated']); } //查询该模版是否推送到微信公众号 $aWhere['article_id'] = $iArticleId; $aWhere['template_id'] = $iTemplateId; } if(!empty($sMediaId)){ $aWhere['media_id'] = $sMediaId; } $aWechatArticle = Db::name('ai_wechat_article')->field('id,is_publish,media_id,publish_status')->where($aWhere)->find(); if(empty($aWechatArticle)){ return json_encode(['status' => 4, 'msg' => 'The article was not found in the draft box of WeChat official account']); } $iId = empty($aWechatArticle['id']) ? 0 : $aWechatArticle['id']; //判断是否发布 if($aWechatArticle['publish_status'] != '-1'){ return json_encode(['status' => 5, 'msg' => 'The article has been published, please confirm']); } //判断微信公众号media_id 是否为空 $sMediaId = empty($aWechatArticle['media_id']) ? '' : $aWechatArticle['media_id']; if(empty($sMediaId)){ return json_encode(['status' => 5,'msg' => 'The article has not been pushed to the draft box of WeChat official account, please confirm'],true); } //获取Token $sToken = $this->getAccessToken(); if (empty($sToken)) { return json_encode(['status' => 6, 'msg' => 'Failed to obtain access_token']); } //验证公众号是否存在该文章 $aInfo = json_decode($this->getDraft($sMediaId),true); if($aInfo['status'] != 1){ return json_encode($aInfo); } // //CURL请求 // $sUrl = "https://api.weixin.qq.com/cgi-bin/freepublish/submit?access_token={$sToken}"; // //参数组装 // $sJsonData = json_encode([ // 'media_id' => $sMediaId // ], JSON_UNESCAPED_UNICODE); // //发送CURL请求 // $aCurlResult = $this->curlWechatApi($sUrl,$sJsonData); // if($aCurlResult['status'] != 1){ // return $aCurlResult; // } // $response = empty($aCurlResult['data']) ? [] : $aCurlResult['data']; // //判断是否推送成功 // if(empty($response['publish_id'])){ // return json_encode(['status' => 9,'msg' => "未获取到发布草稿的publish_id"]); // } $response['publish_id'] = '100000001'; //更新文章表publish_id $aUpdate = ['update_time' => time(),'is_publish' => 1,'publish_id' => $response['publish_id'],'publish_status' => 1]; $result = Db::name('ai_wechat_article')->where('id',$iId)->limit(1)->update($aUpdate); if($result === false){ return json_encode(['status' => 9,'msg' => "Failed to update the status of the published article"]); } return json_encode($aResult); } /** * CURL 查询文章的发布状态 * @param $sToken Token * @param article_id array 文章ID */ public function freePublish(){ //返回结果数组 $aResult = ['status' => 1,'msg' => 'Successfully synchronized the publishing status of the article','data' => []]; //获取参数 $aParam = $this->request->post(); $aWhere = ['is_publish' => 1,'publish_id' => ['<>',''],'publish_status' => 1,'is_delete' => 2]; if(!empty($aParam['article_id'])){ $aWhere['id'] = $aParam['article_id']; } //查询文章发布ID $aArticlePublishId = Db::name('ai_wechat_article')->where($aWhere)->column('publish_id'); if(empty($aArticlePublishId)){ return json_encode(['status' => 2,'msg' => 'No articles requiring synchronization status were found'],true); } //循环查询 $aInsert = $aUpdate = []; foreach ($aArticlePublishId as $key => $value) { if(empty($value)){ continue; } $aResult = json_decode($this->_freePublish(100000001),true); if($aResult['status'] != 1){ continue; } $aData = empty($aResult['data']) ? [] : $aResult['data']; if(empty($aData)){ continue; } $aInsert[] = $aData; $aUpdate[$aData['publish_status']][] = $value; } //插入日志表 if(!empty($aInsert)){ $result = Db::name('wechat_article_publish_log')->insertAll($aInsert); } //更新文章表的发布状态 if(!empty($aUpdate)){ Db::startTrans(); foreach ($aUpdate as $key => $value) { if(empty($value)){ continue; } $result = Db::name('ai_wechat_article')->whereIn('publish_id',$value)->limit(count($value))->update(['publish_status' => $key,'update_time' => time()]); } Db::commit(); } return json_encode($aResult); } private function _freePublish($sPublishId = '100000001'){ //获取参数 // $aParam = $this->request->post(); // $sPublishId = empty($sPublishId) ? $aParam['publish_id']?? '' : $sPublishId;//文件地址 // if(empty($sPublishId)){ // return json_encode(['status' => 2, 'msg' => '请选择要查询的文章发布ID']); // } // //获取Token // $sToken = $this->getAccessToken(); // if (empty($sToken)) { // return json_encode(['status' => 3, 'msg' => 'Failed to obtain access_token']); // } // //CURL请求 // $sUrl = "https://api.weixin.qq.com/cgi-bin/freepublish/get?access_token={$sToken}"; // //参数组装 // $sJsonData = json_encode([ // 'publish_id' => $sPublishId // ], JSON_UNESCAPED_UNICODE); // //发送CURL请求 // $aCurlResult = $this->curlWechatApi($sUrl,$sJsonData); // if($aCurlResult['status'] != 1){ // return $aCurlResult; // } // $response = empty($aCurlResult['data']) ? [] : $aCurlResult['data']; $response = ['publish_id' => '1000001','publish_status' => 2,'article_id'=> '','article_detail','fail_idx' => [1,2]]; //log日志需要参数 $aField = ['publish_id','publish_status' ,'article_id' ,'article_detail' ,'fail_idx' ,'create_time']; $aInsert = []; foreach ($aField as $value) { if($value == 'create_time'){ $aInsert[$value] = time(); continue; } $aInsert[$value] = empty($response[$value]) ? ' ' : $response[$value]; if(is_array($aInsert[$value])){ $aInsert[$value] = json_encode($aInsert[$value]); } } $aResult['status'] = 1; $aResult['data'] = $aInsert; return json_encode($aResult); } }