背景
在Koa系框架(如EggJS)中進行微信支付
開發時,遇到一個問題:微信支付平台會發送一個回調請求,通知支付訂單的處理結果。該請求傳入的參數是xml格式,而Koa中間件koa-bodyparser
對xml格式的請求參數沒有做處理,這就需要我們在程序中自行處理
通用處理邏輯
網上通用的處理邏輯,都是類似如下的代碼:
const bb = require('bluebird');
const xml = await bb.fromCallback(cb => {
let data = '';
this.ctx.req.setEncoding('utf8');
this.ctx.req.on('data', function(chunk) {
data += chunk;
});
this.ctx.req.on('end', function() {
cb(null, data);
});
});
分析與疑問
上面這段代碼通過響應request對象的事件接收xml數據,對於微信支付
這個場景簡單有效,但是作為一個通用的xml處理機制,還是有所欠缺。request對象有如下事件:aborted
、close
、data
、end
、error
,此外,請求參數還有可能使用了壓縮算法。如何對這些場景做更完整的處理呢?
借用中間件koa-bodyparser
由於Koa系框架(如EggJS)使用中間件koa-bodyparser
對請求參數做預處理工作。那么最完整的處理邏輯也一定在中間件koa-bodyparser
中。具體的源碼這里不列出,可以參考如下鏈接:
通過分析中間件koa-bodyparser
所引用的源碼,我們就可以得到一個更簡潔的xml處理代碼,而且適應場景也更廣,代碼如下:
const raw = require('raw-body');
const inflate = require('inflation');
const xml = await raw(inflate(this.ctx.req));
CabloyJS的進一步封裝
CabloyJS后端是基於EggJS定制的上層應用框架。CabloyJS通過向context對象注入一個通用的方法getPayload
,那么在實際的開發場景中就更加方便了
注入方法
async getPayload(options) {
return await raw(inflate(this.req), options);
}
實際調用
const xml = await this.ctx.getPayload();