# 開發(fā)插件
開發(fā)插件前,請閱讀了解 《小程序插件接入指南》 了解開通流程及開放范圍,并開通插件功能。如果未開通插件功能,將無法上傳插件。
# 創(chuàng)建插件項(xiàng)目
插件類型的項(xiàng)目可以在開發(fā)者工具中直接創(chuàng)建。詳情

新建插件類型的項(xiàng)目后,如果創(chuàng)建示例項(xiàng)目,則項(xiàng)目中將包含三個(gè)目錄:
plugin目錄:插件代碼目錄。miniprogram目錄:放置一個(gè)小程序,用于調(diào)試插件。doc目錄:用于放置插件開發(fā)文檔。
miniprogram 目錄內(nèi)容可以當(dāng)成普通小程序來編寫,用于插件調(diào)試、預(yù)覽和審核。下面的內(nèi)容主要介紹 plugin 中的插件代碼及 doc 中的插件開發(fā)文檔。
我們提供了 一個(gè)可以直接在微信開發(fā)者工具中查看的完整插件示例,開發(fā)者可以和本文互相對照以便理解。請注意:
- 由于插件需要 appid 才能工作,請?zhí)钊胍粋€(gè) appid;
- 由于當(dāng)前代碼片段的限制,打開該示例后請 手動(dòng)將 appid 填寫到
miniprogram/app.json中(如下圖)使示例正常運(yùn)行。

# 插件目錄結(jié)構(gòu)
一個(gè)插件可以包含若干個(gè)自定義組件、頁面,和一組 js 接口。插件的目錄內(nèi)容如下:
plugin
├── components
│?? ├── hello-component.js // 插件提供的自定義組件(可以有多個(gè))
│?? ├── hello-component.json
│?? ├── hello-component.wxml
│?? └── hello-component.wxss
├── pages
│?? ├── hello-page.js // 插件提供的頁面(可以有多個(gè),自小程序基礎(chǔ)庫版本 2.1.0 開始支持)
│?? ├── hello-page.json
│?? ├── hello-page.wxml
│?? └── hello-page.wxss
├── index.js // 插件的 js 接口
└── plugin.json // 插件配置文件
# 插件配置文件
向使用者小程序開放的所有自定義組件、頁面和 js 接口都必須在插件配置文件 plugin.json 列出,格式如下:
代碼示例:
{
"publicComponents": {
"hello-component": "components/hello-component"
},
"pages": {
"hello-page": "pages/hello-page"
},
"main": "index.js"
}
這個(gè)配置文件將向使用者小程序開放一個(gè)自定義組件 hello-component,一個(gè)頁面 hello-page 和 index.js 下導(dǎo)出的所有 js 接口。
# 進(jìn)行插件開發(fā)
請注意:在插件開發(fā)中,只有 部分接口 可以直接調(diào)用;另外還有部分能力(如 獲取用戶信息 和 發(fā)起支付 等)可以通過 插件功能頁 的方式使用。
# 自定義組件
插件可以定義若干個(gè)自定義組件,這些自定義組件都可以在插件內(nèi)相互引用。但提供給使用者小程序使用的自定義組件必須在配置文件的 publicComponents 段中列出(參考上文)。
除去接口限制以外,自定義組件的編寫和組織方式與一般的自定義組件相同,每個(gè)自定義組件由 wxml, wxss, js 和 json 四個(gè)文件組成。具體可以參考 自定義組件的文檔。
# 頁面
插件從小程序基礎(chǔ)庫版本 2.1.0 開始支持頁面。插件可以定義若干個(gè)插件頁面,可以從本插件的自定義組件、其他頁面中跳轉(zhuǎn),或從使用者小程序中跳轉(zhuǎn)。所有頁面必須在配置文件的 pages 段中列出(參考上文)。
除去接口限制以外,插件的頁面編寫和組織方式與一般的頁面相同,每個(gè)頁面由 wxml, wxss, js 和 json 四個(gè)文件組成。具體可以參考其他關(guān)于頁面的文檔。
插件執(zhí)行頁面跳轉(zhuǎn)的時(shí)候,可以使用 navigator 組件。當(dāng)插件跳轉(zhuǎn)到自身頁面時(shí), url 應(yīng)設(shè)置為這樣的形式:plugin-private://PLUGIN_APPID/PATH/TO/PAGE 。需要跳轉(zhuǎn)到其他插件時(shí),也可以這樣設(shè)置 url 。
代碼示例:
<navigator url="plugin-private://wxidxxxxxxxxxxxxxx/pages/hello-page">
Go to pages/hello-page!
</navigator>
自基礎(chǔ)庫版本 2.2.2 開始,在插件自身的頁面中,插件還可以調(diào)用 wx.navigateTo 來進(jìn)行頁面跳轉(zhuǎn), url 格式與使用 navigator 組件時(shí)相仿。
# 接口
插件可以在接口文件(在配置文件中指定,詳情見上文)中 export 一些 js 接口,供插件的使用者調(diào)用,如:
代碼示例:
module.exports = {
hello: function() {
console.log('Hello plugin!')
}
}
# 獲取小程序?qū)С?/h3> 在開發(fā)者工具中預(yù)覽效果,需要手動(dòng)填寫一下 miniprogram/app.json 中的插件 AppID
在開發(fā)者工具中預(yù)覽效果,需要手動(dòng)填寫一下 miniprogram/app.json 中的插件 AppID
從基礎(chǔ)庫 2.11.1 起,在插件中有全局函數(shù) requireMiniProgram,可以獲取由使用者小程序?qū)С龅膬?nèi)容。
例如,使用者小程序做了如下導(dǎo)出:
// 使用者小程序
module.exports = {
greeting() {
return 'Greetings from Weixin MiniProgram!';
}
}
那么在插件中,可以這樣獲得內(nèi)容:
// 插件
const miniProgramExports = requireMiniProgram();
miniProgramExports.greeting(); // 'Greetings from Weixin MiniProgram!'
另外也可以 參考使用者小程序的相關(guān)文檔
# 引用小程序的自定義組件
在開發(fā)者工具中預(yù)覽效果,需要手動(dòng)填寫一下
miniprogram/app.json中的插件 AppID
有時(shí),插件可能需要在頁面或者自定義組件中,將一部分區(qū)域交給使用的小程序來渲染,因此需要能夠引用小程序的自定義組件。但由于插件中不能直接指定小程序的自定義組件路徑,因此無法直接通過 usingComponents 的方式來引用。這里介紹通過 抽象節(jié)點(diǎn)(generics) 來實(shí)現(xiàn)引用的方式。
如果是插件自定義組件(例如 plugin-view),那么我們可以通過聲明一個(gè) generic:
// plugin/components/plugin-view.json
{ "componentGenerics": { "mp-view": true } }
并在希望顯示小程序組件的位置引用:
<!-- plugin/components/plugin-view.wxml -->
<view>小程序組件:</view>
<mp-view /><!-- 這里是一個(gè)小程序自定義組件 -->
在小程序中引用 plugin-view 時(shí),就可以傳遞組件給插件進(jìn)行渲染了:
<!-- miniprogram/page/index.wxml -->
<plugin-view generic:mp-view="comp-from-miniprogram" />
如果是插件頁,插件頁本身就是一個(gè)頁面頂層組件,小程序不會引用它,無法通過 generic:xxx="" 的方式來指定抽象節(jié)點(diǎn)實(shí)現(xiàn);因此,從基礎(chǔ)庫 2.12.2 起,小程序可以在插件的配置里為插件頁指定抽象節(jié)點(diǎn)實(shí)現(xiàn)。例如插件頁面名為 plugin-index,則可以:
{
"myPlugin": {
"provider": "wxAPPID",
"version": "1.0.0",
"genericsImplementation": {
"plugin-index": {
"mp-view": "components/comp-from-miniprogram"
}
}
}
}
另外也可以 參考使用者小程序的相關(guān)文檔
# 預(yù)覽、上傳和發(fā)布
插件可以像小程序一樣預(yù)覽和上傳,但插件沒有體驗(yàn)版。
插件會同時(shí)有多個(gè)線上版本,由使用插件的小程序決定具體使用的版本號。
手機(jī)預(yù)覽和提審插件時(shí),會使用一個(gè)特殊的小程序來套用項(xiàng)目中 miniprogram 文件夾下的小程序,從而預(yù)覽插件。
- (建議的方式)如果當(dāng)前開發(fā)者有 測試號,則會使用這個(gè)測試號;在測試號的設(shè)置頁中可以看到測試號的
appid、appsecret并設(shè)置域名列表。 - 否則,將使用“插件開發(fā)助手”,它具有一個(gè)特定的
appid。
# 在開發(fā)版小程序中測試
通常情況下,可以將 miniprogram 下的代碼當(dāng)做使用插件的小程序代碼,來進(jìn)行插件的調(diào)試和測試。
但有時(shí),需要將插件的代碼放在實(shí)際運(yùn)行的小程序中進(jìn)行調(diào)試、測試。此時(shí),可以使用開發(fā)版的小程序直接引用開發(fā)版插件。方法如下:
- 在開發(fā)者工具的插件項(xiàng)目中上傳插件,此時(shí),在上傳成功的通知信息中將包含這次上傳獲得的插件開發(fā)版 ID (一個(gè)英文、數(shù)字組成的隨機(jī)字符串);
- 點(diǎn)擊開發(fā)者工具右下角的通知按鈕,可以打開通知欄,看到新生成的 ID ;
- 在需要使用開發(fā)版本插件的小程序項(xiàng)目中,將插件 version 設(shè)置為
"version": "dev-[開發(fā)版 ID]"的形式,如"version": "dev-abcdef0123456789abcdef0123456789"即可。
如果開發(fā)版小程序引用了開發(fā)版插件,此時(shí)這個(gè)小程序就不能上傳發(fā)布了。必須要將插件版本設(shè)為正式版本之后,小程序才可以正常上傳、發(fā)布。
注意事項(xiàng):
- 每次上傳插件所生成的 ID 不一定相同,即使是同一個(gè)插件和同一個(gè)開發(fā)者,多次上傳也可能會改變 ID;
- 每個(gè)開發(fā)者在每個(gè)插件中只會同時(shí)存在一個(gè)有效的開發(fā)版插件,即只有最新上傳的開發(fā)版 ID 有效(使用舊的 ID 會提示失效);
- 同一個(gè)插件不同開發(fā)者上傳的開發(fā)版互不影響,可以同時(shí)有效;
- 開發(fā)版插件沒有時(shí)間限制,長期有效。
# 插件開發(fā)文檔
在使用者小程序使用插件時(shí),插件代碼并不可見。因此,除了插件代碼,我們還支持插件開發(fā)者上傳一份插件開發(fā)文檔。這份開發(fā)文檔將展示在插件詳情頁,供其他開發(fā)者在瀏覽插件和使用插件時(shí)進(jìn)行閱讀和參考。插件開發(fā)者應(yīng)在插件開發(fā)文檔中對插件提供的自定義組件、頁面、接口等進(jìn)行必要的描述和解釋,方便使用者小程序正確使用插件。
插件開發(fā)文檔必須放置在插件項(xiàng)目根目錄中的 doc 目錄下,目錄結(jié)構(gòu)如下:
doc
├── README.md // 插件文檔,應(yīng)為 markdown 格式
└── picture.jpg // 其他資源文件,僅支持圖片
其中,README.md 的編寫有一定的 限制條件,具體來說:
- 引用到的圖片資源不能是網(wǎng)絡(luò)圖片,且必須放在這個(gè)目錄下;
- 文檔中的鏈接只能鏈接到:
- 微信開發(fā)者社區(qū)(developers.weixin.qq.com)
- 微信公眾平臺(m.ceconline.net)
- GitHub(github.com)
編輯 README.md 之后,可以在開發(fā)者工具左側(cè)資源管理器的文件欄中右鍵單擊 README.md,并選擇上傳文檔。發(fā)布上傳文檔后,文檔不會立刻發(fā)布。此時(shí)可以使用賬號和密碼登錄 管理后臺 ,在 小程序插件 > 基本設(shè)置 中預(yù)覽、發(fā)布插件文檔。
插件文檔總大小不能大于 2M,超過時(shí)上傳將返回錯(cuò)誤碼 80051。
# 其他注意事項(xiàng)
# 插件間互相調(diào)用
插件不能直接引用其他插件。但如果小程序引用了多個(gè)插件,插件之間是可以互相調(diào)用的。
一個(gè)插件調(diào)用另一個(gè)插件的方法,與插件調(diào)用自身的方法類似??梢允褂?plugin-private://APPID 訪問插件的自定義組件、頁面(暫不能使用 plugin:// )。
對于 js 接口,可使用 requirePlugin ,但目前尚不能在文件一開頭就使用 requirePlugin ,因?yàn)楸灰蕾嚨牟寮赡苓€沒有初始化,請考慮在更晚的時(shí)機(jī)調(diào)用 requirePlugin ,如接口被實(shí)際調(diào)用時(shí)、組件 attached 時(shí)。(未來會修復(fù)這個(gè)問題。)
# 插件請求簽名
插件在使用 wx.request 等 API 發(fā)送網(wǎng)絡(luò)請求時(shí),將會額外攜帶一個(gè)簽名 HostSign ,用于驗(yàn)證請求來源于小程序插件。這個(gè)簽名位于請求頭中,形如:
X-WECHAT-HOSTSIGN: {"noncestr":"NONCESTR", "timestamp":"TIMESTAMP", "signature":"SIGNATURE"}
其中, NONCESTR 是一個(gè)隨機(jī)字符串, TIMESTAMP 是生成這個(gè)隨機(jī)字符串和 SIGNATURE 的 UNIX 時(shí)間戳。它們是用于計(jì)算簽名 SIGNATRUE 的參數(shù),簽名算法為:
SIGNATURE = sha1([APPID, NONCESTR, TIMESTAMP, TOKEN].sort().join(''))
其中,APPID 是 所在小程序 的 AppId (可以從請求頭的 referrer 中獲得);TOKEN 是插件 Token,可以在小程序插件基本設(shè)置中找到。
網(wǎng)絡(luò)請求的 referer 格式固定為 https://servicewechat.com/{appid}/{version}/page-frame.html,其中 {appid} 為小程序的 appid,{version} 為小程序的版本號,版本號為 0 表示為開發(fā)版、體驗(yàn)版以及審核版本,版本號為 devtools 表示為開發(fā)者工具,其余為正式版本。
插件開發(fā)者可以在服務(wù)器上按以下步驟校驗(yàn)簽名:
sort對APPIDNONCESTRTIMESTAMPTOKEN四個(gè)值表示成字符串形式,按照字典序排序(同 JavaScript 數(shù)組的 sort 方法);join將排好序的四個(gè)字符串直接連接在一起;- 對連接結(jié)果使用
sha1算法,其結(jié)果即SIGNATURE。
自基礎(chǔ)庫版本 2.0.7 開始,在小程序運(yùn)行期間,若網(wǎng)絡(luò)狀況正常, NONCESTR 和 TIMESTAMP 會每 10 分鐘變更一次。如有必要,可以通過判斷 TIMESTAMP 來確定當(dāng)前簽名是否依舊有效。