使用php呼叫微信介面上傳永久素材

crelaber發表於2016-06-03

功能需求

公司新開的公眾號需要將公司平臺現在的所有精品文章都匯入,手動匯入會有很多的工作量,所以採用自動化同步文章的方式來達到效果

開發說明

微信open api提供了新增永久素材的介面,本次功能是基於這個介面進行資料同步的

使用到的介面

獲取永久素材列表介面:material/batchget_material
新增永久素材介面:material/add_news
新增媒體檔案介面:material/add_material
圖文型別

單圖文(要求有預設的封面,需要提前上傳到微信公眾號後臺)

環境要求

php版本:5.5以下(因為下面程式碼中的上傳媒體檔案必須要求在此環境,否則會呼叫微信介面失敗)

開發流程

1、從公司平臺獲取所有的文章列表
2、遍歷文章列表,檢視文章是否有圖片附件,若有進行第三步,否則進行第四步
3、檢測所有的附件,取出第一個圖片附件,並呼叫新增媒體檔案介面上傳圖片獲得返回後的media_id
4、呼叫素材列表介面獲取預設的封面圖片,並從中得到的資料中獲取media_id
5、根據返回獲取到的media_id開始呼叫上傳圖文介面上傳素材
6、記錄返回資訊

介面設計

獲取微信素材列表介面

此介面是用於獲取預設的圖片media_id
同步平臺資料介面

此介面是使用者同步我們自己的文章資料到微信
功能實現

介面常量

private $app_id = `wx189ae9fa8816b131`;
private $app_secret = `36f5f430c591acbae3505fe877733283`;
const API_URL_PREFIX = `https://api.weixin.qq.com/cgi-bin`;
const MEDIA_FOREVER_UPLOAD_URL = `/material/add_material?`;
const MEDIA_FOREVER_NEWS_UPLOAD_URL = `/material/add_news?`;
const MEDIA_FOREVER_NEWS_UPDATE_URL = `/material/update_news?`;
const MEDIA_FOREVER_GET_URL = `/material/get_material?`;
const MEDIA_FOREVER_DEL_URL = `/material/del_material?`;
const MEDIA_FOREVER_COUNT_URL = `/material/get_materialcount?`;
const MEDIA_FOREVER_BATCHGET_URL = `/material/batchget_material?`;

獲取微信素材列表介面

action介面方法

說明:該方法為此介面的入口方法
呼叫方式:http://${domain}/weixin/get_articles/

 /**
     * 獲取圖片素材介面
     */
    public function get_articles_action(){
      $token = $this->get_access_token();
      $list = $this->getForeverList($token,`image`,0,20);
      echo json_encode($list);
    }
    get_access_token方法
    
    private function get_access_token() {
      $access_token = AWS_APP::cache()->get(`access_token`);
      if(!$access_token){
        error_log(`get access_token from weixin `);
        $appId = $this->app_id;
        $appSecret = $this->app_secret;
        $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=$appId&secret=$appSecret";
        $res = json_decode($this -> httpGet($url));
        $access_token = $res -> access_token;
        AWS_APP::cache()->set(`access_token`,$access_token,time()+3600);
      }else{
        error_log(`get access_token from cache `);
      }
      error_log(`access_token is :`.$access_token);
      return $access_token;
    }

呼叫微信素材介面方法

說明:該方法為呼叫微信獲取永久素材列表介面方法

 /**
    * 獲取永久素材列表
    * @param $token
    * @param $type 型別有image,vedio和audio
    * @param $offset 起始位置,0表示從第一個
    * @param $count 個數,區間為0~20
    */
    public function getForeverList($token,$type,$offset,$count){
      $data = array(
        `type` => $type,
        `offset` => $offset,
        `count` => $count,
      );
      $result = $this->http_post(
                  self::API_URL_PREFIX.self::MEDIA_FOREVER_BATCHGET_URL.`access_token=`.$token,
                  self::json_encode($data)
                 );
      error_log(`forever list is :`.$result);
      if ($result)
      {
        $json = json_decode($result,true);
        if (isset($json[`errcode`])) {
        $this->errCode = $json[`errcode`];
        $this->errMsg = $json[`errmsg`];
        return false;
        }
        return $json;
      }
      return false;
    }

同步文章到微信介面

action方法

說明:該方法為此介面的入口方法
呼叫方式:http://${domain}/weixin/upload_article/

/**
 * 同步問答的文章到訂閱號上介面
 */
public function index_action(){
  $article_list = $this->model(`article`)->get_articles_list(null, 1, 18, `add_time DESC`);
  $access_token = $this->get_access_token();
  $base_url = `http://wenda.qiezilife.com/article/`;
  foreach ($article_list as $key => $article){

    if($article[`has_attach`]){
      $attaches = $this->model(`publish`)->get_attach(`article`, $article[`id`], `max`);
      foreach ($attaches as $i => $a){
        //過濾獲取第一張圖片
        if($a[`is_image`]){
          $attache = $a;
          break;
        }
      }

      $img = $attache[`path`];
      $size = filesize($img);
      echo $img.`,size is :`.$size;
      echo `<br/>`;
      $file_info = array(
        `filename` => $img,
        `content-type` => `image/jpg`, //檔案型別
        `filelength` => $size
      );
      $upload_img_result = $this->upload_meterial($file_info,$access_token);
      $media_id = $upload_img_result;
      error_log(`media_id is ===============>`.$media_id);
    }else{
      $media_id = `1PoTp0SqruwWu_HX0HR_jUp4STX5HSpYkibb1Ca8ZQA`;
    }

    $articles =array();
    //上傳圖片成功了就開始上傳圖文
    $upload_article_data = array(
      `title` => $article[`title`],
      `thumb_media_id` => $media_id,
      `author` => `茄子營養師`,
      `digest` => `茄子生活,你的品質生活指南`,
      `show_cover_pic` => 1,
      `content` => $article[`message`],
      `content_source_url` => $base_url.$article[`id`]
    );

    $articles[] = $upload_article_data;

    $data = array(
      `articles` => $articles
    );
    $result= $this->uploadForeverArticles($access_token,$data);
    echo self::json_encode($result);
    error_log(`upload_article result is : `.json_encode($result));
    error_log(`============================upload end============================`);

    }
}

uploadForeverArticles方法

說明:該方法為呼叫微信上傳永久素材介面方法

/**
 * 上傳永久圖文素材(認證後的訂閱號可用)
 * 新增的永久素材也可以在公眾平臺官網素材管理模組中看到
 * @param array $data 訊息結構{"articles":[{...}]}
 * @return boolean|array
 */
public function uploadForeverArticles($access_token,$data){
  error_log(`post data is=======> `.self::json_encode($data));
  $url = self::API_URL_PREFIX.self::MEDIA_FOREVER_NEWS_UPLOAD_URL.`access_token=`.$access_token;
  $result = HTTP::request($url, `POST`, self::json_encode($data));
  error_log(`weixin return result is =====>`.$result);
  if ($result)
  {
    $json = json_decode($result,true);
    if (!$json || !empty($json[`errcode`])) {
      $this->errCode = $json[`errcode`];
      $this->errMsg = $json[`errmsg`];
      return false;
    }
    return $json;
  }
  return false;
}

upload_meterial方法

說明:該方法為呼叫微信上傳永久素材介面方法

    /**
     * 請注意該方法必須保證php的版本在5.6以下,否則會爆40015錯誤
     */
    function upload_meterial($file_info,$access_token){
      $url="https://api.weixin.qq.com/cgi-bin/material/add_material?access_token={$access_token}&type=image";
      $ch1 = curl_init ();
      $timeout = 5;
      $real_path="{$file_info[`filename`]}";
      //$real_path=str_replace("/", "\", $real_path);
      $data= array("media"=>"@{$real_path}",`form-data`=>$file_info);
      curl_setopt ( $ch1, CURLOPT_URL, $url );
      curl_setopt ( $ch1, CURLOPT_POST, 1 );
      curl_setopt ( $ch1, CURLOPT_RETURNTRANSFER, 1 );
      curl_setopt ( $ch1, CURLOPT_CONNECTTIMEOUT, $timeout );
      curl_setopt ( $ch1, CURLOPT_SSL_VERIFYPEER, FALSE );
      curl_setopt ( $ch1, CURLOPT_SSL_VERIFYHOST, false );
      curl_setopt ( $ch1, CURLOPT_POSTFIELDS, $data );
      $result = curl_exec ( $ch1 );
      echo `<br/>`;
      echo `reulst is ==========>`.$result;
      curl_close ( $ch1 );
      if(curl_errno()==0){
        $result=json_decode($result,true);
        //var_dump($result);
        return $result[`media_id`];
      }else {
        return false;
      }
    }

http_post方法

說明:該方法為調http post請求方法

/**
 * POST 請求
 * @param string $url
 * @param array $param
 * @param boolean $post_file 是否檔案上傳
 * @return string content
 */
private function http_post($url,$param,$post_file=false){
  $oCurl = curl_init();
  if(stripos($url,"https://")!==FALSE){
    curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($oCurl, CURLOPT_SSLVERSION, 1); //CURL_SSLVERSION_TLSv1
  }
  if (is_string($param) || $post_file) {
    $strPOST = $param;
  } else {
    $aPOST = array();
    foreach($param as $key=>$val){
      $aPOST[] = $key."=".urlencode($val);
    }
    $strPOST =  join("&", $aPOST);
  }
  curl_setopt($oCurl, CURLOPT_URL, $url);
  curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, 1 );
  curl_setopt($oCurl, CURLOPT_POST,true);
  curl_setopt($oCurl, CURLOPT_POSTFIELDS,$strPOST);
  $sContent = curl_exec($oCurl);
  $aStatus = curl_getinfo($oCurl);
  curl_close($oCurl);
  if(intval($aStatus["http_code"])==200){
    return $sContent;
  }else{
    return false;
  }
}

遇到的問題

在開發的過程中,在呼叫微信上傳媒體檔案時候始終得到的返回資料為

{"errcode":41005,"errmsg":"media data missing  hint: [3fSt_0048e297]"}

原因:php版本的問題,我本機的版本5.6,而帶有@識別的php方法必須是5.5以下才能識別,5.5以上的版本將這個特性去除了,上傳方法如下圖
解決方法:更換php的版本到5.5或者5.5以下,不更換php的版本的方法暫時沒有找到
blob.png

相關文章