前陣子,我的 WordPress Plugin:Muki Ai Summary 已通過官方審核並正式上架!期間跟 WordPress Plugin 的審核團隊信件溝通了好幾個月,學到了很多開發的細節,特別是在 PHP 安全性、程式碼品質和審核標準上的要求。
如果你也想開發自己的 WordPress Plugin 並順利上架,歡迎參考這篇文章,我會分享審核的整個過程,包含開發時要注意的事情、送審時遇到的問題,以及如何調整程式碼來通過審核,希望能幫助到各位開發者。
開發前的準備
確保 Plugin 符合 WordPress 標準
開發前可以先參考 WordPress Plugin 開發指南 以及 官方 Plugin 審核標準,確保你的 Plugin 符合以下基本要求:
- 遵循 WordPress Coding Standards (一定要遵守規範,不然退件機率很高)
- 提供完整的 Plugin 說明文件
readme.txt - 避免使用高風險函式,如
eval()、base64_decode() - 正確的處理 WordPress 安全機制,例如
Nonce
確保 Plugin 目錄結構
/my-plugin
/assets
banner-772x250.png
icon-256x256.png
screenshot-{*}.png
/tags
/1.0.0
/1.0.1
/trunk
/languages
/src
my-plugin.php
readme.txt
assets/
用於存放 Plugin 的縮圖以及截圖等資料,審核通過後會自動撈取圖片當作 Plugin 頁面的介紹,檔名要跟上面的一樣,才能自動讀取到圖片。
尺寸也已經寫在檔名後面,banner 是 772 x 250(px),icon 是 256 x 256(px),截圖從 screenshot-1.png 開始編碼,依序是 screenshot-2.png, screenshot-3.png... 依此類推。
這樣的結構不僅讓程式碼更清晰,之後維護也比較方便。
tags/ 與 trunk/
trunk/ 放的是最新的 Plugin 檔案,tags/ 用版本號當作目錄名稱,存放不同版本的 Plugin。
trunk/languages
存放 Plugin 的語系檔案,我是使用 Poedit 這套軟體製作 WordPress 的語系檔。我原本沒有做多語系的規劃,但沒想到被審核團隊退件,所以要開發的朋友可以考慮將多語系功能也納入考量。
my-plugin.php
這個是 Plugin 主要的執行檔案,基本上會跟你的外掛目錄同名,例如外掛目錄是 my-plugin/,那主要執行檔案就是 my-plugin.php
確保有多語系功能
如同前面提過,當時沒有規劃多語系就被審核團隊退件了,因此多語系可能是個必要條件,所有的文字都要使用 WordPress 的翻譯函式,如以下兩種寫法:
__('Hello, World!', 'my-plugin');
esc_html__('Settings', 'my-plugin');esc_html__() 是 WordPress 提供的一個 i18n 與安全性相關的函數,可以對翻譯的文字進行 escape 處理,以防止 XSS 攻擊。
❌ 常見的錯誤寫法:
// 使用變數作為翻譯內容 esc_html__($my_text, 'my-plugin');
WordPress 的翻譯工具 (如 Poedit) 會掃描程式碼中的 __()、esc_html__() 等函數,取得裡面的字串產生翻譯檔案,如果我們傳入變數,翻譯工具無法知道變數是什麼,所以就沒辦法產生翻譯檔案了
如果要使用變數,可以改用 esc_html()
$dynamic_text = get_dynamic_text();
echo sprintf(
esc_html__( 'Hello, %s!', 'my-plugin' ),
esc_html( $dynamic_text )
);處理 Plugin 的審核回饋
將 Plugin 上傳到 WordPress Plugin Repository 後,WordPress Plugin 團隊的志願審核者會檢查 Plugin,因為都是真人審核,所以要數天到數週不等,以下是我在審核過程中碰到的問題與解決方案:
Plugin 作者的資料認證
我在 plugin.php 有提供 Plugin 作者的網址:
Author URI: https://muki.tw
▼ 結果第一次審核就收到退件信

老實說,我當時沒有認真看信件,只覺得 10 多年前(乾,好老),我送審 Plugins 和 Themes 時明明都沒事啊,所以我就繼續提交審核,搞到後來對方超級生氣,還說你再繼續送件,我就把你變成黑名單!!!我這才幡然醒悟,才認真的看了信件的內容 囧,大家千萬不要跟我一樣當個奧客啊 🥹
簡單來說,就是現在的身份認證變嚴苛了,因為人人都能申請 gmail,團隊沒辦法確認我的 gmail 身份和這個 Plugin Author URL 是否為同一個人,而這個 Email 是怎麼來的?就是我們在 WordPress.org 的帳號。
所以我必須要把 WordPress.org 的帳號,改成可以證明我是 https://muki.tw 擁有者的那個 Email,就是要有 @muki.tw 的 Email 網域。
因此,我先透過主機商提供的 CPanel 開通了我的 Email 帳號 (例. [email protected]),再到 WordPress.org 修改我的 Email,最後再送審就可以解決這個問題啦。
▼ 登入 WordPress.org 後,選擇「Edit Profile」→「Account & Security」→「Account email」,輸入新的 email address,點擊「Update Email Address」

身份認證通過後,陸續碰到了以下問題:
禁止使用 HEREDOC/NOWDOC
HEREDOC / NOWDOC 是 PHP 的語法之一,旨在讓字串更好閱讀,但 WordPress 審核團隊不允許這種寫法,因為容易忽略輸出時的安全性問題。
🔹 我的錯誤程式碼
$prompt = <<<EOT This is an AI-generated summary. EOT;
🔹 解決方案:改用原始寫法 " 拼接字串
$prompt = "This is an AI-generated summary.";
如果有用到外部的 API,必須清楚說明
如果 Plugin 有呼叫外部 API (像是 OpenAI、Google API... ),一定要在 readme.txt 裡清楚說明:
- Plugin 用了哪些服務
- 傳送哪些資料
- API 服務的隱私政策連結
🔹 我的錯誤程式碼
wp_remote_post('https://api.openai.com/v1/chat/completions', ...);
🔹 解決方案:在 readme.txt 裡補充
== External Services == This plugin interacts with OpenAI's API service: * Purpose: Generate article summaries using artificial intelligence * API URL: - https://api.openai.com/v1/chat/completions * Data Transmission: - When: Only when generating a summary (manually or auto-generate if enabled) - Content Sent: Article title and content - Content Received: AI-generated summary text * Privacy & Terms: - OpenAI Privacy Policy: https://openai.com/privacy/ - OpenAI Terms of Service: https://openai.com/terms/ - OpenAI API Data Usage Policy: https://openai.com/policies/api-data-usage-policies Note: Your OpenAI API key and article content are sent directly to OpenAI's servers. Please review OpenAI's privacy policy and terms of service before using this plugin.
這樣審核團隊就能確認 Plugin 沒有隱藏的資料傳輸行為,也保護了開發者,避免後續的法律問題。
所有 POST 請求都有 Nonce 驗證和使用者權限檢查
WordPress 強烈建議在所有 POST 請求中加入 Nonce 驗證,以防止 CSRF (跨站請求偽造) 攻擊
🔹 我的錯誤程式碼
if ($_POST['action'] == 'save_settings') {
update_option('my_plugin_option', $_POST['value']);
}
🔹 解決方案: 加上 Nonce 驗證與權限檢查
if (isset($_POST['my_plugin_nonce']) && wp_verify_nonce($_POST['my_plugin_nonce'], 'save_settings')) {
if (current_user_can('manage_options')) {
update_option('my_plugin_option', sanitize_text_field($_POST['value']));
}
}
所有輸出變數都要經過適當的 Escape
如果 Plugin 有輸出變數,一定要適當 escape,不然可能會有 XSS (跨站腳本攻擊) 的風險,這就是前面在「確保多語系功能」段落提到的
🔹 我的錯誤程式碼
echo "<h1>" . __('Muki AI Summary Settings', 'muki-ai-summary') . "</h1>";
🔹 解決方案:使用 esc_html__()
echo "<h1>" . esc_html__('Muki AI Summary Settings', 'muki-ai-summary') . "</h1>";
這樣即使內容是來自使用者的輸入,也能確保 HTML 不會被惡意注入攻擊。
最終測試與重新送審
修改完這些問題後,官方建議在乾淨的 WordPress 安裝環境測試 Plugin,WordPress 也有提供 Playground 讓我們線上測試。
主要測試項目:
- 確認所有功能正常運作
- 確保程式碼符合安全性規範
- 確認
readme.txt資訊完整
最後重新送審 Plugin,並回覆審核團隊說明已修正的問題。
▼ 最最開心的就是收到這封信啦 🎉

結語
這次的 Plugin 上架經驗,讓我學到很多 WordPress Plugin 開發的細節,特別是在安全性與合規性上的要求。
如果你也想開發並上架 WordPress Plugin,這裡有幾點建議:
- 一開始就遵循 WordPress Coding Standards,避免後續修改麻煩。
- 確保所有輸出變數都經過
escape,這是 Plugin 安全性的基本要求。 - 如果 Plugin 連接外部 API,務必要在
readme.txt裡標示清楚。 POST請求一定要加Nonce驗證,這不只是審核標準,也是安全考量。- 提交前先在乾淨的 WordPress 安裝環境測試,確保所有功能正常運作。
來回的審核與修改其實略顯麻煩,但當 Plugin 被 WordPress 官方核准的那一刻,真的超有成就感 derrr。
希望這篇文章能幫助到想開發 WordPress Plugin 的你,也祝福各位開發順利,一次就上架成功 XXD。