本篇文章更新時間:2026/03/03
如有資訊過時或語誤之處,歡迎使用 Contact 功能通知或向一介資男的 LINE 社群反應。
如果本站內容對你有幫助,歡迎贊助支持 。
本系列文參考自 WordPress.org 官方外掛開發文件 - HTTP API 的繁體中文版本,並加入作者實務開發經驗補充。
WordPress HTTP API 是外掛開發中與外部服務溝通的標準介面。無論你要串接第三方金流、取得社群平台資料、或是與自家後端 API 互動,都應該透過 WordPress 內建的 HTTP API 來發送請求。這套 API 封裝了 PHP 底層各種 HTTP 傳輸方式(cURL、fopen、fsockopen 等),自動選擇當前伺服器環境中最適合的方法執行請求,讓開發者只需要關注業務邏輯,而不用擔心底層相容性問題。本文將從 WordPress 為何規定必須使用 HTTP API 開始,逐步介紹 GET、POST 請求的使用方式、回應處理、進階設定,以及實務上的快取與錯誤處理策略。
內容目錄
為什麼要使用 HTTP API - 不能直接用 cURL 的原因
很多 PHP 開發者的第一直覺是直接使用 curl_init()、file_get_contents() 或其他原生 PHP 函式來發送 HTTP 請求。但在 WordPress 外掛開發中,這是被明確禁止的做法——如果你的外掛要上架到 WordPress.org,審核團隊會因為直接使用 cURL 而退回你的外掛。
WordPress.org 外掛審核指南明確要求:所有 HTTP 請求必須使用 WordPress HTTP API(即 wp_remote_get()、wp_remote_post() 等函式)。理由如下:
- 伺服器相容性:並非所有主機都安裝了 cURL 擴充。WordPress HTTP API 會自動偵測可用的傳輸方式,確保在任何環境都能正常運作。
- 安全性一致:WordPress HTTP API 內建 SSL 驗證、重導向限制、逾時控制等安全機制,使用統一的 API 才能確保這些防護一致生效。
- 可過濾性:透過 HTTP API 發出的請求,其他外掛可以透過
pre_http_request、http_response等 Filter 進行攔截或修改。直接使用 cURL 會完全繞過 WordPress 的 Hook 系統。 - 測試友善:在單元測試中,可以透過 filter 模擬 HTTP 回應,而不需要實際發送網路請求。如果直接使用 cURL,測試時就必須依賴真實的外部服務。
// ❌ 錯誤做法 - 直接使用 cURL(外掛審核不會通過)
$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, 'https://api.example.com/data' );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
$result = curl_exec( $ch );
curl_close( $ch );
// ✅ 正確做法 - 使用 WordPress HTTP API
$response = wp_remote_get( 'https://api.example.com/data' );
$body = wp_remote_retrieve_body( $response );
簡單來說,只要你的程式碼是在 WordPress 環境中執行,就應該使用 HTTP API。這不只是規範問題,更是品質保證。
GET 請求 - wp_remote_get()
wp_remote_get() 是最常使用的 HTTP API 函式,用於從外部 URL 取得資料。它接受兩個參數:
/**
* 發送 GET 請求
*
* @param string $url 目標 URL
* @param array $args 選用參數(timeout, headers, cookies 等)
* @return array|WP_Error 回應陣列或 WP_Error 物件
*/
$response = wp_remote_get( $url, $args );
預設參數值如下:
method- GETtimeout- 5(秒)redirection- 5(最多跟隨幾次重導向)httpversion- 1.0blocking- true(是否等待回應完成才繼續執行)headers- array()body- nullcookies- array()
以下是一個完整的實務範例,從外部 API 取得 JSON 資料並解析:
/**
* 從 GitHub API 取得使用者公開資訊
*
* @param string $username GitHub 使用者名稱
* @return array|WP_Error 解析後的使用者資料或錯誤
*/
function myplugin_get_github_user( $username ) {
$url = sprintf( 'https://api.github.com/users/%s', sanitize_text_field( $username ) );
$response = wp_remote_get( $url, array(
'timeout' => 10,
'headers' => array(
'Accept' => 'application/vnd.github.v3+json',
),
) );
// 檢查是否為 WP_Error(網路錯誤、DNS 解析失敗等)
if ( is_wp_error( $response ) ) {
return $response;
}
// 檢查 HTTP 狀態碼
$status_code = wp_remote_retrieve_response_code( $response );
if ( 200 !== $status_code ) {
return new WP_Error(
'github_api_error',
sprintf( 'GitHub API 回傳非預期的狀態碼:%d', $status_code )
);
}
// 取得並解析回應內容
$body = wp_remote_retrieve_body( $response );
$data = json_decode( $body, true );
if ( json_last_error() !== JSON_ERROR_NONE ) {
return new WP_Error( 'json_parse_error', 'JSON 解析失敗' );
}
return $data;
}
// 使用範例
$user_data = myplugin_get_github_user( 'developer-name' );
if ( is_wp_error( $user_data ) ) {
error_log( 'GitHub API 錯誤:' . $user_data->get_error_message() );
} else {
echo '使用者名稱:' . esc_html( $user_data['name'] );
echo '公開 Repo 數:' . intval( $user_data['public_repos'] );
}
這個範例展示了標準的 API 呼叫流程:發送請求 → 檢查錯誤 → 驗證狀態碼 → 解析回應。接下來的章節會詳細說明每個步驟的回應處理方式。
POST 請求 - wp_remote_post()
wp_remote_post() 用於向外部 API 發送資料,函式簽名與 wp_remote_get() 完全相同,差別在於 HTTP 方法為 POST,且通常需要透過 body 參數傳送資料:
/**
* 發送 POST 請求到外部 API
*
* @param string $url 目標 URL
* @param array $args 請求參數(body, headers 等)
* @return array|WP_Error 回應陣列或 WP_Error 物件
*/
$response = wp_remote_post( $url, $args );
以下是一個向外部 API 送出表單資料的範例:
/**
* 送出聯絡表單資料到外部 CRM API
*
* @param array $form_data 表單資料
* @return bool|WP_Error 成功回傳 true,失敗回傳 WP_Error
*/
function myplugin_submit_to_crm( $form_data ) {
$response = wp_remote_post( 'https://api.example-crm.com/v1/contacts', array(
'timeout' => 15,
'headers' => array(
'Content-Type' => 'application/json',
'Authorization' => 'Bearer ' . get_option( 'myplugin_crm_api_key' ),
),
'body' => wp_json_encode( array(
'name' => sanitize_text_field( $form_data['name'] ),
'email' => sanitize_email( $form_data['email'] ),
'subject' => sanitize_text_field( $form_data['subject'] ),
'message' => sanitize_textarea_field( $form_data['message'] ),
) ),
) );
if ( is_wp_error( $response ) ) {
return $response;
}
$status_code = wp_remote_retrieve_response_code( $response );
if ( $status_code >= 200 && $status_code < 300 ) {
return true;
}
$body = wp_remote_retrieve_body( $response );
return new WP_Error(
'crm_api_error',
sprintf( 'CRM API 回傳錯誤(%d):%s', $status_code, $body )
);
}
幾個重要注意事項:
- 當
body傳入陣列時,WordPress 會自動以application/x-www-form-urlencoded格式編碼(類似標準 HTML 表單送出)。伺服器端可透過$_POST讀取。 - 如果 API 要求 JSON 格式,需要手動設定
Content-Type為application/json,並用wp_json_encode()將 body 編碼為 JSON 字串。 - API 金鑰等敏感資訊應該儲存在
wp_options中,透過get_option()讀取,切勿寫死在程式碼裡。
除了 GET 和 POST 之外,WordPress 也提供了 wp_remote_head() 用於只取得回應標頭而不下載內容(適合檢查資源是否存在或是否有更新),以及 wp_remote_request() 可以指定任意 HTTP 方法(PUT、DELETE、PATCH 等),適用於 RESTful API 的完整操作:
// 使用 HEAD 請求檢查資源是否存在
$response = wp_remote_head( 'https://api.example.com/resource/123' );
$status = wp_remote_retrieve_response_code( $response );
// 使用 DELETE 方法刪除遠端資源
$response = wp_remote_request( 'https://api.example.com/resource/123', array(
'method' => 'DELETE',
'headers' => array(
'Authorization' => 'Bearer ' . $api_token,
),
) );
// 使用 PUT 方法更新遠端資源
$response = wp_remote_request( 'https://api.example.com/resource/123', array(
'method' => 'PUT',
'headers' => array(
'Content-Type' => 'application/json',
'Authorization' => 'Bearer ' . $api_token,
),
'body' => wp_json_encode( array( 'status' => 'published' ) ),
) );
回應處理 - retrieve 函式與錯誤檢查
WordPress HTTP API 的所有請求函式(wp_remote_get()、wp_remote_post() 等)都回傳相同的資料結構:一個包含完整回應資訊的陣列,或者在連線失敗時回傳 WP_Error 物件。WordPress 提供了一組 retrieve 輔助函式來安全地從回應中取得所需資訊:
is_wp_error() - 檢查是否發生錯誤
在處理回應之前,必須先檢查請求是否成功。is_wp_error() 用於判斷回傳值是否為 WP_Error 物件。會觸發 WP_Error 的情況包括:DNS 解析失敗、連線逾時、SSL 憑證問題等網路層面的錯誤。
$response = wp_remote_get( 'https://api.example.com/data' );
if ( is_wp_error( $response ) ) {
$error_message = $response->get_error_message();
$error_code = $response->get_error_code();
error_log( "HTTP 請求失敗 [{$error_code}]:{$error_message}" );
return false;
}
wp_remote_retrieve_response_code() - 取得 HTTP 狀態碼
即使請求本身成功了(沒有回傳 WP_Error),伺服器也可能回傳 4xx 或 5xx 的錯誤狀態碼:
$status_code = wp_remote_retrieve_response_code( $response );
if ( 200 !== $status_code ) {
// 依據不同狀態碼做不同處理
switch ( $status_code ) {
case 401:
case 403:
error_log( 'API 認證失敗,請檢查 API 金鑰' );
break;
case 404:
error_log( '請求的資源不存在' );
break;
case 429:
error_log( 'API 請求頻率超過限制' );
break;
case 500:
case 503:
error_log( '外部 API 伺服器錯誤' );
break;
default:
error_log( "未預期的狀態碼:{$status_code}" );
}
return false;
}
wp_remote_retrieve_body() - 取得回應內容
取得回應的 body 內容。大多數 API 回傳的是 JSON 格式,需要進一步解析:
$body = wp_remote_retrieve_body( $response );
$data = json_decode( $body, true );
// 驗證 JSON 解析結果
if ( null === $data && json_last_error() !== JSON_ERROR_NONE ) {
error_log( 'JSON 解析失敗:' . json_last_error_msg() );
return false;
}
wp_remote_retrieve_headers() - 取得回應標頭
取得全部或特定的回應標頭:
// 取得所有回應標頭
$headers = wp_remote_retrieve_headers( $response );
// 取得特定標頭
$content_type = wp_remote_retrieve_header( $response, 'content-type' );
$rate_limit = wp_remote_retrieve_header( $response, 'x-ratelimit-remaining' );
// 實務應用:根據 Rate Limit 標頭控制請求頻率
if ( $rate_limit !== '' && intval( $rate_limit ) < 10 ) {
error_log( '警告:API Rate Limit 即將耗盡,剩餘 ' . $rate_limit . ' 次' );
}
完整的回應處理範本
以下是一個可以在實務中直接套用的標準回應處理流程:
/**
* 標準 API 請求處理範本
*
* @param string $endpoint API 端點
* @return array|WP_Error 解析後的資料或錯誤
*/
function myplugin_api_request( $endpoint ) {
$response = wp_remote_get( $endpoint, array(
'timeout' => 10,
'headers' => array(
'Accept' => 'application/json',
),
) );
// 第一層:檢查網路層面錯誤
if ( is_wp_error( $response ) ) {
return $response;
}
// 第二層:檢查 HTTP 狀態碼
$status_code = wp_remote_retrieve_response_code( $response );
if ( $status_code < 200 || $status_code >= 300 ) {
return new WP_Error(
'api_http_error',
sprintf( 'API 回傳 HTTP %d', $status_code ),
array( 'status' => $status_code )
);
}
// 第三層:解析回應內容
$body = wp_remote_retrieve_body( $response );
$data = json_decode( $body, true );
if ( null === $data && json_last_error() !== JSON_ERROR_NONE ) {
return new WP_Error( 'api_json_error', 'JSON 解析失敗:' . json_last_error_msg() );
}
return $data;
}
進階設定 - timeout、headers、sslverify 與認證
WordPress HTTP API 的第二個參數 $args 允許你精細控制請求的各種行為。以下是最常用的進階設定:
timeout - 連線逾時設定
預設的 timeout 是 5 秒。對於大多數 API 呼叫來說這是合理的,但某些情況下你可能需要調整:
// 較慢的 API 或大量資料下載,延長 timeout
$response = wp_remote_get( $url, array(
'timeout' => 30, // 最多等待 30 秒
) );
// 非關鍵的背景請求,縮短 timeout 避免阻塞
$response = wp_remote_get( $url, array(
'timeout' => 3,
) );
注意:在 WordPress 的 AJAX 或 Cron 請求中,PHP 本身可能有更短的執行時間限制。設定過長的 timeout 不一定有效,需要同時考慮 max_execution_time 的限制。
headers - 自訂請求標頭
許多 API 要求傳送特定的 Header,常見的用途包括認證、指定回應格式、API 版本控制等:
$response = wp_remote_get( $url, array(
'headers' => array(
'Accept' => 'application/json', // 期望的回應格式
'Authorization' => 'Bearer ' . $api_token, // Bearer Token 認證
'X-API-Version' => '2.0', // API 版本
'User-Agent' => 'MyPlugin/1.0', // 自訂 User-Agent
),
) );
sslverify - SSL 驗證
sslverify 預設為 true,這是正確且安全的預設值。在正式環境中絕對不應該關閉 SSL 驗證。但在本地開發環境中,自簽憑證可能會導致請求失敗,此時可以暫時關閉:
// ⚠️ 僅在本地開發環境使用,正式環境絕不關閉
$response = wp_remote_get( $url, array(
'sslverify' => defined( 'WP_DEBUG' ) && WP_DEBUG ? false : true,
) );
重要:如果你在正式環境遇到 SSL 驗證錯誤,正確的處理方式是修正伺服器的 CA 憑證設定,而不是關閉驗證。WordPress 會使用自帶的 CA bundle 檔案(位於 wp-includes/certificates/ca-bundle.crt)進行驗證。
常見的認證方式
不同的 API 使用不同的認證機制,以下是最常見的三種:
// 方式一:Basic Authentication(帳號密碼)
$response = wp_remote_get( $url, array(
'headers' => array(
'Authorization' => 'Basic ' . base64_encode( $username . ':' . $password ),
),
) );
// 方式二:Bearer Token(OAuth 2.0 常用)
$response = wp_remote_get( $url, array(
'headers' => array(
'Authorization' => 'Bearer ' . $access_token,
),
) );
// 方式三:API Key 放在 Header
$response = wp_remote_get( $url, array(
'headers' => array(
'X-API-Key' => $api_key,
),
) );
// 方式四:API Key 放在 Query String
$url_with_key = add_query_arg( 'api_key', $api_key, $url );
$response = wp_remote_get( $url_with_key );
blocking - 非阻塞請求
如果你只需要「發出去」但不關心回應結果(例如觸發遠端 webhook 或記錄事件),可以將 blocking 設為 false:
// 非阻塞請求:發送後立即繼續執行,不等待回應
wp_remote_post( 'https://webhook.example.com/event', array(
'blocking' => false,
'body' => array(
'event' => 'order_completed',
'order_id' => $order_id,
),
) );
使用非阻塞請求時,回應內容會是空的,你無法得知請求是否成功。只有在確定不需要處理回應時才使用此設定。
實務建議
作者實務經驗分享:
1. 善用 Transients API 快取 API 回應:外部 API 呼叫是效能瓶頸的主要來源之一。每次頁面載入都發送 HTTP 請求不僅拖慢網站速度,也容易觸發 API 的 Rate Limit。使用 WordPress 的 Transients API 將 API 回應快取一段時間,是最基本也最有效的優化策略:
function myplugin_get_external_data() { // 先檢查快取 $cached = get_transient( 'myplugin_api_data' ); if ( false !== $cached ) { return $cached; } // 快取不存在或已過期,重新請求 $response = wp_remote_get( 'https://api.example.com/data', array( 'timeout' => 10, ) ); if ( is_wp_error( $response ) ) { return $response; } $data = json_decode( wp_remote_retrieve_body( $response ), true ); if ( null === $data ) { return new WP_Error( 'parse_error', '資料解析失敗' ); } // 寫入快取,有效期 1 小時 set_transient( 'myplugin_api_data', $data, HOUR_IN_SECONDS ); return $data; }2. 建立統一的錯誤處理模式:在外掛中統一封裝 API 呼叫,建立一致的錯誤處理與日誌記錄機制。不要在每個呼叫點各自處理錯誤,而是建立一個共用的 API Client 類別或函式。這樣不僅減少重複程式碼,也讓除錯更容易。上面的「標準 API 請求處理範本」就是一個好的起點。
3. API 金鑰的安全管理:將 API 金鑰儲存在
wp_options中,透過後台設定頁面讓管理員輸入,並在顯示時遮蔽部分字元。絕對不要將 API 金鑰寫死在原始碼中,也不要將包含金鑰的設定檔提交到版本控制系統。更多安全性的實務建議,請參考「WordPress 安全性完整教學」。4. 處理外部服務不可用的情況:外部 API 隨時可能故障。你的外掛應該優雅地處理這種情況——顯示快取的舊資料、顯示友善的錯誤訊息,或者提供降級功能。絕對不要因為外部 API 無回應就讓整個頁面輸出 PHP 錯誤訊息。
5. 注意 timeout 對使用者體驗的影響:如果 API 呼叫發生在前台頁面的渲染流程中,5 秒的 timeout 就意味著使用者可能要多等 5 秒才能看到頁面。盡量將 API 呼叫放在背景處理(如 WP-Cron),前台只讀取快取資料。
6. 請求前先做資料驗證與清理:所有傳送到外部 API 的資料都應該先經過 WordPress 的 sanitize 函式處理,所有從外部 API 接收的資料在輸出前都應該先經過 esc 函式跳脫。外部 API 的回傳資料等同於不可信的使用者輸入,千萬不要直接輸出。
本文是「WordPress 外掛開發完整指南」系列的第 11 篇。
上一篇:[WordPress] 使用者管理與角色權限開發教學
下一篇:[WordPress] WP-Cron 排程任務開發教學
