var system=require("../system")
var settings=require("../../config/settings");
var crypto = require('crypto');
const XMLParser = require('xml2js');
const Promise = require('bluebird');
const parseXML = Promise.promisify(XMLParser.parseString);
const buildXML = new XMLParser.Builder({ rootName: 'xml', cdata: true, headless: true, renderOpts: { indent: ' ', pretty: 'true' } });

class WxopBase{
    constructor(){
        this.options = settings.wxopenplatformconfig;
        this.appId = this.options.appid;
        this.encodingAESKey = this.options.encodingaeskey;
        this.token = this.options.checktoken;
        this.aesKey = this.getAesKey(this.encodingAESKey);
        this.iv = this.getIv(this.aesKey);
        this.db=system.getObject("db.connection").getCon();
        this.cacheManager=system.getObject("db.cacheManager");
        this.rc=system.getObject("util.execClient");
    }
    async getUidInfo(len, radix) {
      var chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');//长度62，到yz长度为长36
      var uuid = [], i;
      radix = radix || chars.length;
      if (len) {
        for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix];
      } else {
        var r;
        uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
        uuid[14] = '4';
        for (i = 0; i < 36; i++) {
          if (!uuid[i]) {
            r = 0 | Math.random() * 16;
            uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
          }
        }
      }
      return uuid.join('');
    }
    getAesKey(encodingAESKey){
        return Buffer.from(encodingAESKey + '=', 'base64');
    }
    getIv(aesKey) {
        return aesKey.slice(0, 16);
    }
    //如何加密xml文本 传入xml文本，返回加密后的base64字符串。
    async encode(xmlMsg) {
        if (typeof xmlMsg != 'string') {
         return null;
        }
        var random = crypto.randomFillSync(Buffer.alloc(16));
        var buf = Buffer.from(xmlMsg);
        var msgLength = Buffer.alloc(4);
        msgLength.writeUInt32BE(buf.length, 0);
        var idBuf = Buffer.from(this.appId);
        var xmlBuf = Buffer.from(xmlMsg);
        var totalBuf = Buffer.concat([random, msgLength, xmlBuf, idBuf]);
        totalBuf = await this.PKCS7Encode(totalBuf);
        var cipher = crypto.createCipheriv('aes-256-cbc', this.aesKey, this.iv);
        cipher.setAutoPadding(false);
        var encryptBuf = Buffer.concat([cipher.update(totalBuf), cipher.final()]);
        return encryptBuf.toString('base64');
    }
    //解密微信传过来的请求body中的Encrypt  传入微信请求body中的Encrypt字段值，返回解密后的xml字符串。
    async decode(encryptMsg) {
        if (typeof encryptMsg != 'string') {
            return null;
        };
        var decipher = crypto.createDecipheriv('aes-256-cbc', this.aesKey, this.iv);
        decipher.setAutoPadding(false);
        var decipherBuffer = Buffer.concat([decipher.update(encryptMsg, 'base64'), decipher.final()]);
        decipherBuffer = await this.PKCS7Decode(decipherBuffer);
        var msgLength = decipherBuffer.slice(16, 20).readUInt32BE(0);
        var result = decipherBuffer.slice(20, msgLength + 20).toString();
        return result;
    }
    //生成`msg_signature`。传入微信请求`query`中的`timestamp`, `nonce`和请求`body`中的`Encrypt` ，返回生成的`signature`
    async getSignature(data) {
        var str = ([
          data.nonce,
          data.timestamp,
          data.msg_encrypt,
          this.token
        ]).sort().join('');

        return crypto.createHash('sha1').update(str).digest('hex');
    }
    // 检验消息的完整性。传入微信请求`query`中的`timestamp`, `nonce`, `msg_signature`和请求`body`中的`Encrypt` 返回检验结果`true`或`false`。
    async verify(data) {
        var msg_signature = data.msg_signature;
        var result = await this.getSignature(data);
        return result == msg_signature;
    }
    async PKCS7Decode(buf) {
        var len = buf[buf.length - 1];
        if (len < 1 || len > 32) {
          len = 0;
        }
        return buf.slice(0, buf.length - len);
    }
    async PKCS7Encode(buf) {
        var blockSize = 32;
        var len = buf.length;
        var paddingLength = blockSize - (len % blockSize);
        var paddingBuffer = Buffer.alloc(paddingLength, paddingLength);
        return Buffer.concat([buf, paddingBuffer]);
    }
     /**检验消息的真实性，并且获取解密后的明文
     * @param sMsgSignature: 签名串，对应URL参数的msg_signature
     * @param sTimeStamp: 时间戳，对应URL参数的timestamp
     * @param sNonce: 随机串，对应URL参数的nonce
     * @param sPostData: 密文，对应POST请求的数据
     * xml_content: 解密后的原文，当return返回0时有效
     * @return: 成功0，失败返回对应的错误码
     * 验证安全签名
     */
    async decryptMsg(sPostData, sMsgSignature, sTimeStamp, sNonce){
        const msg_encrypt = sPostData.Encrypt[0];
        var isverify = await this.verify({ nonce:sNonce,timestamp:sTimeStamp,msg_encrypt:msg_encrypt,msg_signature:sMsgSignature});
        if (!isverify) throw new Error('msgSignature is not invalid');
        const decryptedMessage = await this.decode(msg_encrypt);
        return parseXML(decryptedMessage, { explicitArray: false });
    }

    async encryptMsg(replyMsg,nonce) {
        const result = {};
        result.Encrypt = await this.encode(replyMsg);
        console.log(result);
        result.Nonce = nonce || parseInt((Math.random() * 100000000000), 10);
        result.TimeStamp = Date.parse(new Date())/1000;
        console.log(result);
        result.MsgSignature = await this.getSignature({timestamp:result.TimeStamp,nonce:result.Nonce,msg_encrypt:result.Encrypt});
        return buildXML.buildObject(result);
    };

}
module.exports=WxopBase;
// var task = new WxopBase();
// var sPostData = {Encrypt:["jF2XmFx/dJDfCORJmCOD5kjj39BAOmTb4Lp+EHZxz8QMO1yljibhLwSA0NPpqmemdn4dhSFtmjWOWF1WauLVOXkFhsH/E1P5Yo9Qj5gPL8F5CyQN52JKX8Q6xyBg5REqkcPAPvIX9BhH7GV0VeR3GZBGf7tLTZD1XiNZAB3NKZxLvfG3BkLR9fEojpjJFE8PL+VYm+LcTzr1lPQpa8pN0UvOax+RLwYu0wzFLr2TwVgZMI628PDweZ2JrO9XNN8fRbKhUXWro37mo2crIsvxNmTjuTQ1hcIzDbTtFyaD3xkuE6M6TEjygTyyDnV6VtJgNCCIZY7C/yQleSsio5CBEuRS1Bdq3txf7FLGG/tiffF9jtHdlIuDBkfOCvGfGIA/6jNinHbyM8WccIDdUFAcHOG/ZRX1J/Q/FIRqjyXCOsKKVIgFQAuKF0jRe6EgS0ev4FnHpgj50DPwIfhMCRau9ht5zTx1GCSBTI3SLwZ6J0aTFa6C02kFnGAa2HaqcE3MJhU5NrWxYzdSJE7K/P/L1ih6/O1dZ6/u2LyfwUH4kpwLop4DB6guNjTgrw4TnoLWLnw+5cf3WHq8llRCvPlwtMEm+3CMfWaLCwklxr9xpgg4Eozodb5T/erQ8+/pixUFxq9JDHp/eYimY9vlOT7bSty2YmXODII/q/ozc0s1QbHiTNAzHZSyzA0DMnVVd8jUR+KSSdbBW6n3bf3Kudxq9KYhcShbm56YeeMPRi9ewPhozO4l4RtovV+tEfzSOg9Qe2/+8q5UfU//F+7nfm2YcwdTU3yrdu2mXb3svIbiIo9BWPYTjlLfK5T/8vLeH/YcuLFlsms3CTH7yZC1IpmXNTQ5eMz2dfNlG3i/GbxiHqKbHbS14wRUUG2Luk9LUzSs7IE2i5/NhLnMKLqSixpidXIKTDqbO4HYTmHQbvIJE/nwpkAfxogJeLxtkeyuLoIEv4bGCTDr3NQ1egQeQ+YmtA=="]};
// var sMsgSignature = "3c51adde10c58f895cd11b477e452b5d6a92cc86";
// var sTimeStamp = 1564716510;
// var sNonce = "19336012712";
// task.decryptMsg(sPostData,sMsgSignature,sTimeStamp,sNonce).then(d=>{
//     console.log("dddddddddfffffffffffff");
//     console.log(d.toString());
// })
