const system = require("../system");
const settings = require("../../config/settings");
const DocBase = require("./doc.base");
const uuidv4 = require('uuid/v4');
const md5 = require("MD5");
class APIBase extends DocBase {
    constructor() {
        super();
        this.merchantSve = system.getObject("service.merchant.merchantSve");
        this.oplogSve = system.getObject("service.common.oplogSve");
        this.SIGN_GNAME = ['sign'];
        this.EXCEPT_KEYS = ['sign', 'requestid'];
    }
    getUUID() {
        var uuid = uuidv4();
        var u = uuid.replace(/\-/g, "");
        return u;
    }
    trim(o) {
        if (!o) {
            return "";
        }
        return o.toString().trim();
    }
    async validSign(params) {

        let appId = this.trim(params.appId);
        let timestamp = Number(params.timestamp);
        let nonceStr = this.trim(params.nonceStr);
        let now = new Date().getTime();
        if (now - timestamp > 60 * 60 * 60 * 1000) {
            return system.getResultFail(1000000, "请求超时");
        }
        if (!appId) {
            return system.getResultFail(1000000, "请填写appId");
        }
        if (!nonceStr) {
            return system.getResultFail(1000000, "随机码为空");
        }

        // TODO redis通过sign幂等验证
        // 幂等验证代码xxxx
        let app = await this.merchantSve.apiWidthCache({id: appId})
        if (!app || !app.id) {
            return system.getResultFail(1000000, "appId不存在");
        }
        if (!app.is_enabled) {
            return system.getResultFail(1000000, "该应用已失效");
        }
        if (!app.merchant_id) {
            return system.getResultFail(1000000, "该应用未绑定商户");
        }

        let keys = Object.keys(params).sort();
        let signArr = [];
        for (let k = 0; k < keys.length; k++) {
            let tKey = keys[k];
            if (this.EXCEPT_KEYS.indexOf(tKey) == -1 && params[tKey]) {
                signArr.push(tKey + "=" + params[tKey]);
            }
        }

        let signStr = signArr.join("&") + "&key=" + app.secret;
        let sign = md5(signStr).toUpperCase();
        console.log(params.sign, signStr, sign);
        if (params.sign != sign) {
            return system.getResultFail(1001001, this.getSignErrorMsg(sign));
        }
        params.app = app;
        return system.getResultSuccess();
    }

    getSignErrorMsg(sign) {
        let signErrorMsg = "签名验证失败";
        if (settings.env == "dev") {
            signErrorMsg = signErrorMsg + "---" + sign;
        }
        return signErrorMsg;
    }

    async checkSign(gname, params) {
        if (this.SIGN_GNAME.indexOf(gname) != -1) {
            return await this.validSign(params);
        }
        return system.getResultSuccess();
    }

    async doexec(gname, methodname, pobj, query, req) {
        var requestid = this.getUUID();
        pobj.requestid = requestid;
        let rtn;
        try {
            let signRes = await this.checkSign(gname, pobj);
            if (signRes.status !== 0) {
                return signRes;
            }
            rtn = await this[methodname](pobj, query, req) || {};
            rtn.requestid = requestid;
            return rtn;
        } catch (e) {
            console.log(e.stack, "api调用出现异常，请联系管理员..........")
            rtn = system.getResultFail(-200, "出现异常，请联系管理员");
            rtn.requestid = requestid;
            return rtn;
        } finally {
            this.oplogSve.createDb({
                appid: "",
                appkey: "",
                requestId: requestid,
                op: req.classname + "/" + methodname,
                content: JSON.stringify(pobj),
                resultInfo: JSON.stringify(rtn),
                clientIp: req.clientIp,
                agent: req.uagent,
                opTitle: "api服务提供方appKey:" + settings.appKey,
            });
        }
    }
}
module.exports = APIBase;

