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.cacheManager = system.getObject("db.common.cacheManager");
        this.logCtl = system.getObject("web.common.oplogCtl");
        this.oplogSve = system.getObject("service.common.oplogSve");
    }
    getUUID() {
        var uuid = uuidv4();
        var u = uuid.replace(/\-/g, "");
        return u;
    }
    /**
     * 验证签名
     * @param {*} params 要验证的参数 
     * @param {*} app_key 应用的校验key
     */
    async verifySign(params, app_key) {
        if (!params) {
            return system.getResult(null, "请求参数为空");
        }
        if (!params.sign) {
            return system.getResult(null, "请求参数sign为空");
        }
        if (!params.times_tamp) {
            return system.getResult(null, "请求参数times_tamp为空");
        }
        var signArr = [];
        var keys = Object.keys(params).sort();
        if (keys.length == 0) {
            return system.getResult(null, "请求参数信息为空");
        }
        for (let k = 0; k < keys.length; k++) {
            const tKey = keys[k];
            if (tKey != "sign" && params[tKey] && !(params[tKey] instanceof Array)) {
                signArr.push(tKey + "=" + params[tKey]);
            }
        }
        if (signArr.length == 0) {
            return system.getResult(null, "请求参数组装签名参数信息为空");
        }
        var resultSignStr = signArr.join("&") + "&key=" + app_key;
        var resultTmpSign = md5(resultSignStr).toUpperCase();
        if (params.sign != resultTmpSign) {
            return system.getResult(null, "签名验证失败");
        }
        return system.getResultSuccess();
    }
    /**
 * 白名单验证
 * @param {*} gname 组名
 * @param {*} methodname 方法名
 */
    async isCheckWhiteList(gname, methodname) {
        var fullname = gname + "." + methodname;
        var lst = [
            "test.testApi"
        ];
        var x = lst.indexOf(fullname);
        return x >= 0;
    }
    async checkAcck(gname, methodname, pobj, query, req) {
        var appInfo = null;
        var result = system.getResultSuccess();
        var ispass = await this.isCheckWhiteList(gname, methodname);
        var appkey = req.headers["accesskey"];
        var app_id = req.headers["app_id"];
        if (ispass) {
            return result;
        }//在白名单里面
        if (app_id) {
            appInfo = await this.cacheManager["ApiAppIdCheckCache"].cache(app_id, null, 3000);
            if (!appInfo) {
                result.status = system.appidFail;
                result.msg = "请求头app_id值失效，请重新获取";
            }

            var signResult = await this.verifySign(pobj.action_body, appInfo.appSecret);
            if (signResult.status != 0) {
                result.status = system.signFail;
                result.msg = signResult.msg;
            }
        }//验签
        else if (appkey) {
            appInfo = await this.cacheManager["ApiAccessKeyCheckCache"].cache(appkey, { status: true }, 3000);
            if (!appInfo || !appInfo.app) {
                result.status = system.tokenFail;
                result.msg = "请求头accesskey失效，请重新获取";
            }
        }//验证accesskey
        else {
            result.status = -1;
            result.msg = "请求头没有相关访问参数，请验证后在进行请求";
        }
        return result;
    }
    async doexec(gname, methodname, pobj, query, req) {
        var requestid = this.getUUID();
        try {
            //验证accesskey或验签
            var isPassResult = await this.checkAcck(gname, methodname, pobj, query, req);
            if (isPassResult.status != 0) {
                isPassResult.requestid = "";
                return isPassResult;
            }
            if (pobj && pobj.action_body) {
                pobj.action_body.merchant_id = pobj.action_body.merchant_id || req.headers["app_id"];
            }
            if (query) {
                query.merchant_id = req.headers["app_id"];
            }
            var rtn = await this[methodname](pobj, query, req);
            rtn.requestid = requestid;

            this.oplogSve.createDb({
                appid: req.headers["app_id"] || "",
                appkey: req.headers["accesskey"] || "",
                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,
            });
            return rtn;
        } catch (e) {
            console.log(e.stack, "api调用出现异常，请联系管理员..........")
            this.logCtl.error({
                appid: req.headers["app_id"] || "",
                appkey: req.headers["accesskey"] || "",
                requestId: requestid,
                op: pobj.classname + "/" + methodname,
                content: e.stack,
                clientIp: pobj.clientIp,
                agent: req.uagent,
                optitle: "api调用出现异常，请联系管理员",
            });
            var rtnerror = system.getResultFail(-200, "出现异常，请联系管理员");
            rtnerror.requestid = requestid;
            return rtnerror;
        }
    }
}
module.exports = APIBase;

