- 使用 soapUI 获取 xml 传输配置
- 使用 request 封装 xml
const urlencode = require("urlencode");
const Parser = require("fast-xml-parser").j2xParser;
const parser = require("fast-xml-parser");
const request = require('request');
const crypto = require('crypto');
const fs = require('fs');
const _ = require('lodash');
module.exports = class extends think.Service{
constructor(){
super();
this.fileSignModelIns = think.model('fileSign', {}, think.config('custom.appModules.web'));
this.option = {
url: think.config('custom.certsercureService'),
method: 'POST',
body: '',
headers: {
'Content-Type':'text/xml;charset=utf-8',
'Accept-Encoding': 'gzip,deflate',
'Content-Length':0,
'SOAPAction':"",
'Connection':"Keep-Alive"
}
};
}
/**
* 生成签名
* @params Object 参数需要签名的body
*/
async createEncryption(params) {
let xmlString = this.getXmlString(params, '方法2');
let options = this.getOption(xmlString);
let body = await this.httprequest(options);
let body_ = parser.parse(body);
let return_ = body_['soap:Envelope']['soap:Body']['ns2:xxxxxx'];
return return_.return;
}
/**
* 验证签名
* @params Object 参数需要签名的body
*/
async verifyEncryption(params, arg3) {
let xmlString = this.getXmlString(params, '方法1', arg3);
let options = this.getOption(xmlString);
let body = await this.httprequest(options);
let body_ = parser.parse(body);
let return_ = body_['soap:Envelope']['soap:Body']['ns2:xxxxx'];
return return_.return;
}
/**
* 异步请求
* @param options
* @returns {Promise<*|Promise<unknown>>}
*/
async httprequest(options){
return new Promise((resolve, reject)=>{
request(options, function(error, response, body) {
if (!error && response.statusCode == 200) {
resolve(body)
}
});
})
}
/**
* 获取option
* @xmlString xml字符串
*/
getOption(xmlString){
let headers = Object.assign({}, this.option.headers);
headers['Content-Length'] = xmlString.length;
let options = Object.assign({}, this.option);
return Object.assign(options, {body: xmlString, headers} );
}
/**
* @params json 参数需要签名的body
* @type string 签名操作类型(生成,确认,更新,销毁)
*/
getXmlString(params, type, arg3 = ''){
let json = {
"root":{
"body": Object.assign({"systemId": "xxxxx"}, params)
}
};
let xml = urlencode(new Parser().parse(json), 'utf-8');
if(arg3 != ''){
return `<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:guot="http://xxxxxx.com/">
<soapenv:Header/>
<soapenv:Body>
<guot:${type}>
<!--Optional:-->
<arg0>xxxx</arg0>
<!--Optional:-->
<arg1>${arg3}</arg1>
<arg2>${xml}</arg2>
</guot:${type}>
</soapenv:Body>
</soapenv:Envelope>`;
}
return `<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:guot="http://xxxxxx.com/">
<soapenv:Header/>
<soapenv:Body>
<guot:${type}>
<!--Optional:-->
<arg0>xxxx</arg0>
<!--Optional:-->
<arg1>${xml}</arg1>
</guot:${type}>
</soapenv:Body>
</soapenv:Envelope>`;
}
/**
* 给文件签名
* @param path
* @returns {Promise<*>}
*/
async createFileEncryption(path){
let hash = this.createFileHash256Sync(path);
let params = {
hash,
path
};
let signId = await this.createEncryption(params);
await this.fileSignModelIns.where({path}).delete();
let result = await this.fileSignModelIns.add({signId, path});
return signId;
}
/**
* 批量给文件签名
* @param pathArr
* @returns {Promise<*>}
*/
async batchCreateFileEncryption(pathArr){
let arr = pathArr.map(async (path) => {
let hash = this.createFileHash256Sync(path);
let params = {
hash,
path
};
let signId = await this.createEncryption(params);
return {signId, path}
});
Promise.all(arr).then(async result=>{
await this.fileSignModelIns.where({path: ['IN', pathArr]}).delete();
await this.fileSignModelIns.addMany(result);
});
}
/**
* 批量验证文件签名
* @param pathArr
* @returns {Promise<*>}
*/
async batchVerifyFileEncryption(pathArr){
let result = await this.fileSignModelIns.where({path: ['IN', pathArr]}).select();
let promiseArr = result.map(async (item) => {
let hash = this.createFileHash256Sync(item.path);
let params = {
hash,
path: item.path
};
return await this.verifyEncryption(params, item.signId);
});
let flags = await Promise.all(promiseArr);
let idx = flags.indexOf(false);
if(idx > -1){
return new Error(`文件 ${pathArr[idx]} 签名确认失败`)
}else{
return true;
}
}
/**
* 确认文件签名
* @param path
* @returns {Promise<*>}
*/
async verifyFileEncryption(path){
let hash = this.createFileHash256Sync(path);
let params = {
hash,
path
};
let signObj = await this.fileSignModelIns.where({path}).find();
if(signObj.signId != ''){
return await this.verifyEncryption(params, signObj.signId);
}else{
return new Error("文件签名确认失败")
}
}
/**
* 创建文件hash
* @param path
* @returns {string}
*/
createFileHash256Sync(path) {
const buffer = fs.readFileSync(path);
const fsHash = crypto.createHash('sha256');
fsHash.update(buffer);
const md5 = fsHash.digest('hex');
return md5
}
}
网友评论