背景
公司為客戶開發(fā)微信公眾號相關(guān)服務(wù)時,有時未能準(zhǔn)備好公眾號,所以需要使用公司的公眾號,但是大家都知道微信網(wǎng)頁授權(quán)域名最多只支持兩個,這就造成了如果有多個項目需要同時開發(fā)時產(chǎn)生了如下問題:
- 網(wǎng)頁授權(quán)地址不夠用
- 公眾號不夠用
- 某功能比如微信快捷登錄突然失效(授權(quán)地址被改掉)
解決方案
關(guān)于域名占用的問題,其實在github
上已經(jīng)有現(xiàn)成的方法了,可以實現(xiàn)多域名的授權(quán),而且實現(xiàn)內(nèi)容也比較簡單,就是一個粗暴的靜態(tài)html
文件去處理授權(quán)用的參數(shù)。博主之前曾經(jīng)做過一個網(wǎng)頁授權(quán)掃碼登錄的Demo
就用到了這個靜態(tài)文件。
正常情況下如果用到了網(wǎng)頁授權(quán)獲取用戶信息,一般是需要一臺服務(wù)器一個備案過的域名的,那么如果沒有服務(wù)器改咋整呢?
云函數(shù)很巧妙地解決了這個問題,我們只需要一個自己的域名(不用其實也可以)就可以通過云函數(shù)來托管這個授權(quán)用的文件來實現(xiàn)通用的授權(quán)服務(wù)。
下面我們來看一下如何去做這么一個簡易的基礎(chǔ)服務(wù)。
需求分析
首先我們知道配置網(wǎng)頁授權(quán)域名的時候需要在公眾號添加這個域名,要求我們在服務(wù)器上上傳一個驗證文件,并且這個文件要掛在根目錄下才可以訪問到,這就要求我們增加一個文件上傳的功能。
這種情況下云函數(shù)就需要具備如下能力:
- 靜態(tài)文件托管
txt
驗證文件上傳
顯然自己手動從零編寫一個云函數(shù)就有些繁瑣了,不過還有我們有內(nèi)置應(yīng)用模板幫助簡化工作量。
實現(xiàn)步驟
應(yīng)用創(chuàng)建
在云函數(shù)的后臺直接創(chuàng)建應(yīng)用,使用koa模板。
應(yīng)用修改
應(yīng)用創(chuàng)建好之后會在云函數(shù)列表里出現(xiàn)名為koa-starter
的函數(shù),我們需要修改這個函數(shù)的代碼。
應(yīng)用模板的源碼在github上就可以獲取->koa-starter。
這里講解一下幾個核心修改的實現(xiàn)吧:
app.js
內(nèi)增加文件上傳的支持,小文件是可以直接上傳的。
app.use( koaBody({ multipart: true, formidable: { multipart: true, maxFileSize: 400 * 1024 * 1024 // 設(shè)置上傳文件大小最大限制,默認(rèn)4M } }))
- 然后增加一些全局的處理
// 全局異常處理app.use(async (ctx, next) => { try { await next() } catch (err) { ctx.body = { code: -1, data: ctx.data, message: ctx.msg || err.message || 服務(wù)開小差了,請稍后再試, etime: Date.now() } }})// pretty json resultapp.use(async (ctx, next) => { await next() if (ctx.data) { ctx.set(Content-Type, application/json) ctx.body = { code: ctx.code || 0, data: ctx.data, message: ctx.msg || success, etime: Date.now() } }})
- 在
routes/index.js
中增加上傳文件的路由處理
router.post("/uptxt", async (ctx, next) => { if (!ctx.request.files) { ctx.data = 未選擇文件 await next() return } // 獲取上傳文件 let file = ctx.request.files.file // 創(chuàng)建可讀流 let reader = fs.createReadStream(file.path) let filePath = `/tmp/${file.name}` // 創(chuàng)建可寫流 const upStream = fs.createWriteStream(filePath) await reader.pipe(upStream); ctx.data = file.name ctx.code = 0 ctx.msg = 上傳驗證文件成功 await next()});
- 前端的模板目錄
views
下面增加兩份頁面代碼。auth.html
文件,用于授權(quán)處理,代碼參考。up.html
文件,用于文件上傳。
文件上傳功能我們需要注意一點:
- 云函數(shù)在執(zhí)行過程中,都擁有一塊500MB的臨時磁盤空間 /tmp,用戶可以在執(zhí)行代碼時對該空間進行一些讀寫操作,也可以創(chuàng)建子目錄,但這部分?jǐn)?shù)據(jù)在函數(shù)執(zhí)行完成后不會保留。
因為需要上傳一個驗證文件所以這個臨時目錄自然會有這個txt文件,但是微信需要驗證這個文件的有效性,所以這就意味著tmp目錄下的東西需要被我們訪問到,那該怎么辦?
解決辦法當(dāng)然是有的,那就是手動修改靜態(tài)資源目錄為tmp。
修改app.js文件:
app.use(require(koa-static)(/tmp))
這樣在上傳之后就可以直接訪問到了。
- 首頁及上傳頁的路由處理:
router.get("/", async (ctx, next) => { await ctx.render("index");});router.get("/up", async (ctx, next) => { await ctx.render("up");});
- 授權(quán)頁的訪問路由處理:
router.get("/auth.html", async (ctx, next) => { await ctx.render("auth");});
- 保存代碼并配置訪問服務(wù)。
前端接入
vue項目為例
插件引入:
在項目中加入生成回調(diào)地址的wechatAuth.js
文件。
部分代碼參考:
// 引入插件import wechatAuth from @/plugins/wechatAuth// 設(shè)置APPIDwechatAuth.setAppId(process.env.VUE_APP_WECHAT_APPID)// 使用插件生成授權(quán)回調(diào)地址wechatAuth.redirect_uri = processUrl()/** * 處理url鏈接 * @returns {string} */function processUrl() { // 本地環(huán)境拿code if (process.env.NODE_ENV === development) { // 中間授權(quán)頁地址 return `${process.env.VUE_APP_WECHAT_AUTH_URL}?backUrl=${window.location.href}` } const url = window.location.href // 解決多次登錄url添加重復(fù)的code與state問題 const urlParams = qs.parse(url.split(?)[1]) let redirectUrl = url if (urlParams.code && urlParams.state) { delete urlParams.code delete urlParams.state const query = qs.stringify(urlParams) if (query.length) { redirectUrl = `${url.split(?)[0]}?${query}` } else { redirectUrl = `${url.split(?)[0]}` } } return redirectUrl}
環(huán)境變量配置:
#appid 可填入申請的測試公眾號id或者其它準(zhǔn)備好的IDVUE_APP_WECHAT_APPID=#authUrl 網(wǎng)頁授權(quán)中間頁VUE_APP_WECHAT_AUTH_URL=云函數(shù)http訪問服務(wù)地址/auth.html
整個授權(quán)服務(wù)的流程可概括為下圖:
因為我們只是把獲取微信授權(quán)code的過程統(tǒng)一放到了云函數(shù)去處理,所以多個項目在調(diào)試時都可以使用同一個地址,減少了資源占用,不失為一個可用方案。
我們僅需要一個云函數(shù)就可以實現(xiàn)微信授權(quán)的本地調(diào)試以及幾個項目幾個公眾號共用一個授權(quán)服務(wù),免去獨立域名、獨立服務(wù)器的煩惱。
服務(wù)Demo演示
這里提供了一個云函數(shù)網(wǎng)頁授權(quán)服務(wù)的Demo地址:
http://cloud.xuedingmiao.com/
參考資料
本文作者:薛定喵君
原文地址:http://xuedingmiao.com/blog/scf_wx_page_auth_service.html