本文目錄 :上傳圖文素材的圖片上傳其他素材關(guān)鍵的http表單請(qǐng)求代碼小結(jié)參考文檔前言:我在實(shí)現(xiàn)微信公眾平臺(tái)上傳素材的時(shí)候遇到了許多問(wèn)題,但最終還是成功實(shí)現(xiàn)這一功能,特此在這里做一下總結(jié)和記錄。文中遇到諸如 ...
本文目錄 :
上傳圖文素材的圖片
上傳其他素材
關(guān)鍵的http表單請(qǐng)求代碼
小結(jié)
參考文檔
前言:
我在實(shí)現(xiàn)微信公眾平臺(tái)上傳素材的時(shí)候遇到了許多問(wèn)題,但最終還是成功實(shí)現(xiàn)這一功能,特此在這里做一下總結(jié)和記錄。
文中遇到諸如 getAccessToken() 等關(guān)鍵函數(shù)卻沒(méi)有找到實(shí)現(xiàn)時(shí),可參考前面的這兩篇文章:
1、微信開(kāi)發(fā)之獲取用戶(hù)詳細(xì)列表
2、微信開(kāi)發(fā)之向用戶(hù)群發(fā)文本消息
1、 上傳圖文素材的圖片
首先選一個(gè)簡(jiǎn)單的接口來(lái)做說(shuō)明例子,這個(gè)上傳素材的接口在所有上傳素材的接口中是參數(shù)最簡(jiǎn)單的,而且還單獨(dú)享用一個(gè)URL, 作為入門(mén)例子再合適不過(guò)了。
注意,本文主要側(cè)重點(diǎn)是代碼層面的實(shí)現(xiàn),而不是微信官方一大堆規(guī)則的講解,如果你有需要此方面的介紹,下面已給出官方鏈接不謝。
官方文檔:
新增永久素材
官方給的這個(gè)接口,除了需要慣例的 access_token ,還需要一個(gè)文件的參數(shù),一般而言,只需要一個(gè)文件路徑,其他文件參數(shù)通過(guò)這個(gè)路徑獲取解析則可,做成一個(gè)黑匣子,簡(jiǎn)單易用。
我知道,有人就是專(zhuān)門(mén)找下邊的 Requests::request() 的實(shí)現(xiàn)的,可在這就沒(méi)看到實(shí)現(xiàn),別急,下面就有。
public function uploadNewsImage($path)
{
$access_token = $this->getAccessToken();
if (!$access_token) {
return false;
}
$path = realpath($path);
$post = ['media '=> '@'.$path];
$url ="https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token={$access_token}";
$return = $this->requestAndCheck($url, 'POST', $post);
if ($return === false) {
return false;
}
return $return;
}
/**
* 專(zhuān)門(mén)用來(lái)檢查微信接口返回值的。
* 是的,這個(gè)接口比上一兩篇文章的接口更加好用。東西一般做多,就知道要抽象了,如果還沒(méi)有那水平的話(huà)。
*/
public function requestAndCheck($url, $method = 'GET', $fields = [])
{
$return = Requests::request($url, $method, $fields);
if ($return === false) {
$this->setError("request出錯(cuò)! " . Requests::$error);
return false;
}
$wxdata = json_decode($return, true);
if (isset($wxdata['errcode']) && $wxdata['errcode'] != 0) {
$this->setError("微信錯(cuò)誤代碼:{$wxdata['errcode']};<br>錯(cuò)誤信息:{$wxdata['errmsg']}<br>請(qǐng)求鏈接:$url");
return false;
}
if (strtoupper($method) === 'GET' && empty($wxdata)) {
$this->setError("微信http請(qǐng)求返回為空!<br>請(qǐng)求鏈接:$url");
return false;
}
return $wxdata;
}
2、 上傳其他素材 懂得上面的流程,其他的上傳素材的接口,無(wú)非就是加多個(gè) GET 和 POST 參數(shù),主流程沒(méi)變。 其他相關(guān)接口列舉如下: 1、新增永久圖文素材:https://api.weixin.qq.com/cgi-bin/material/add_news?access_token=ACCESS_TOKEN 2、新增其他類(lèi)型永久素材:https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=ACCESS_TOKEN&type=TYPE 3、新增臨時(shí)素材:https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE
功能的約束和細(xì)節(jié)還望參考官方文檔: 1、新增永久素材 2、新增臨時(shí)素材
3、 關(guān)鍵的http表單請(qǐng)求代碼 先上代碼:(這里邊已經(jīng)簡(jiǎn)化很多附加功能,比如可以改變header之類(lèi)的功能,該代碼主要參考一些開(kāi)源的項(xiàng)目)
public static function request($url, $method = 'GET', $fields = [])
{
self::$ch = curl_init();
curl_setopt(self::$ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt(self::$ch, CURLOPT_CONNECTTIMEOUT, 10);
$method = strtoupper($method);
if ($method == 'GET' && !empty($fields)) {
$url = $url . (strpos($url,"?")===false ? "?" : "&") . http_build_query($fields);
}
curl_setopt(self::$ch, CURLOPT_URL, $url);
if ($method != 'GET') {
curl_setopt(self::$ch, CURLOPT_POST, true);
if (!empty($fields)) {
if (is_array($fields)) {
/* 支持文件上傳 */
if (class_exists('\CURLFile')) {
curl_setopt(self::$ch, CURLOPT_SAFE_UPLOAD, true);
foreach ($fields as $key => $value) {
if (is_string($value) && strpos($value, '@') === 0) {
$fields[$key] = new CURLFile(realpath(ltrim($value, '@')),
'image/jpg', basename(ltrim($value, '@')));
}
}
} elseif (defined('CURLOPT_SAFE_UPLOAD')) {
curl_setopt(self::$ch, CURLOPT_SAFE_UPLOAD, false);
}
}
curl_setopt(self::$ch, CURLOPT_POSTFIELDS, $fields);
}
}
/* 關(guān)閉https驗(yàn)證 */
if ("https" == substr($url, 0, 5)) {
curl_setopt(self::$ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt(self::$ch, CURLOPT_SSL_VERIFYHOST, false);
}
self::$content = curl_exec(self::$ch);
curl_close(self::$ch);
return self::$content;
}
重點(diǎn)分析:
/* 支持文件上傳 */
if (class_exists('\CURLFile')) {
curl_setopt(self::$ch, CURLOPT_SAFE_UPLOAD, true);
foreach ($fields as $key => $value) {
if (is_string($value) && strpos($value, '@') === 0) {
$fields[$key] = new CURLFile(realpath(ltrim($value, '@')));
}
}
} elseif (defined('CURLOPT_SAFE_UPLOAD')) {
curl_setopt(self::$ch, CURLOPT_SAFE_UPLOAD, false);
}
這里面有個(gè)PHP版本的坑,5.4版本只支持用 @ 來(lái)進(jìn)行上傳文件,5.5是個(gè)過(guò)渡版本,支持 @ 和 CURLFile 兩種方式上傳文件,而到了5.6,就只支持 CURLFile 了。所以需要用兼容模式來(lái)適應(yīng)不同版本。
關(guān)于為什么不用php版本號(hào)來(lái)判斷呢?你用版本號(hào)誰(shuí)知道你是要來(lái)判斷啥呢?難道加個(gè)注釋?zhuān)?nbsp;
而常量 CURLOPT_SAFE_UPLOAD 是用來(lái)開(kāi)啟是否支持 @ 的,當(dāng)然,5.6版本設(shè)置了也沒(méi)有。
還有,要上傳file的時(shí)候,一定要用數(shù)組給 curl_setopt(self::fields); 傳值,而不能用 http_build_query() ,一個(gè)的http請(qǐng)求頭中的 content-type 是 multipart/form-date ,另一個(gè)是 application/x-www-form-urlencoded 。file用二進(jìn)制編碼進(jìn)行傳輸,而普通的post數(shù)據(jù)是文本傳輸。
上面的相關(guān)知識(shí)還請(qǐng)?jiān)斂?參考文檔。
小結(jié):
如果你已有上傳文件的接口,其實(shí)這個(gè)功能不算啥,按照官方文檔進(jìn)行 post url 即可。如果沒(méi)有,或者沒(méi)有實(shí)現(xiàn)文件上傳功能,就要對(duì) curl 研究一下了,還要踩一下php版本的坑。。。不過(guò)對(duì) curl 掌握就更加全面而牢固了,這難道不是我們的目的?
主要參考文檔:
1、微信公眾號(hào)開(kāi)發(fā)文檔
2、Multipart/form-data POST文件上傳詳解
3、PHP的CURLOPT_POSTFIELDS參數(shù)使用數(shù)組和字符串的區(qū)別
4、The CURLFile class
5、考慮 PHP 5.0~5.6 各版本兼容性的 cURL 文件上傳
-end-