api.js 4.84 KB
import wx from '../utils/wx';
import config from './config';
import udid from './udid';
import {HmacSHA256, MD5} from '../vendors/crypto';
import {stringify} from '../vendors/query-stringify';

export const verify = {
    verifyMethod: 'resources.simple.pice',
    update() {
        return api.get({ // eslint-disable-line
            data: {
                method: this.verifyMethod
            }
        }).then(result => {
            if (result && result.code === 200 && result.data && result.data.sk) {
                wx.setStorageSync('verifyKey', result.data.sk);
            }

            return result;
        });
    },
    gen() {
        const self = this;
        let maxTryTimes = 3;

        function update() {
            return self.update().then(result => {
                if (result && result.code === 200 && result.data && result.data.sk) {
                    return result.data.sk;
                } else if (maxTryTimes) {
                    maxTryTimes--;

                    return update();
                } else {
                    return '';
                }
            });
        }

        return update();
    },
    get() {
        const verifyKey = wx.getStorageSync('verifyKey');

        if (!verifyKey) {
            this.gen(); // 异步更新
        }

        return verifyKey || '';
    },
    sign(data, encode = false) {
        const verifyKey = this.get();

        if (!verifyKey) {
            return '';
        }

        data = stringify(data, {
            encode: encode
        });

        return HmacSHA256(data, verifyKey).toString();
    },
    computeSecret(data, encode = false) {
        const newData = {
            private_key: config.apiParams.private_key
        };

        Object.keys(data).sort().forEach(key => {
            newData[key] = String(data[key]).trim();
        });

        newData.client_secret = MD5(stringify(newData, {
            encode: encode
        })).toString();
        delete newData.private_key;

        return newData;
    }
};

const api = {
    request(params) {
        const app = getApp();

        // 公有参数
        params.data = this.addParams(params.data);
        params = this.addSessionKey(params);

        // client_secret
        params.data = verify.computeSecret(params.data);

        // 接口验签
        if (!params.header['x-yoho-verify'] && params.data.method !== verify.verifyMethod) {
            params.header['x-yoho-verify'] = verify.sign(params.data);
        }

        return wx.request(params).then(result => {
            if (result.statusCode === 200) {
                const resultData = result && result.data || {};

                delete result.data;
                resultData.result = result;

                if (resultData.code === 508) {
                    verify.gen();
                }

                if (resultData.code === params.code) {
                    return resultData.data || {};
                }

                return resultData;
            } else if (result.statusCode === 401) {
                app.clearUserSession();
            } else {
                console.error('api statusCode:', result.statusCode);
                return result && result.data || {};
            }
        }).catch(err => {
            console.error(err);
            return {};
        });
    },
    addSessionKey(params) {
        let app = getApp();
        let uid = app && app.getUid();
        let sessionKey = app && app.getSessionKey();

        params = Object.assign({}, params);

        if (uid && sessionKey) {
            params.data.session_key = sessionKey;
            params.data.uid = uid;
            params.header.Cookies = `JSESSIONID=${sessionKey}`;
        }

        return params;
    },
    addParams(params) {
        return Object.assign({
            client_type: config.apiParams.client_type,
            app_version: config.apiParams.app_version,
            miniapp_version: config.apiParams.miniapp_version,
            storeId: config.storeId,
            udid: udid.get(),
            business_line: config.business_line
        }, params);
    },
    get(params) {
        // 默认值
        params = Object.assign({
            data: {},
            header: {},
            dataType: 'json'
        }, params, {
            url: config.domains[params.api || 'api'] + (params.url || ''),
        });

        // 构造好参数再请求
        return this.request(params);
    },
    post(params) {
        // 默认值
        params = Object.assign({
            method: 'post',
            data: {},
            header: {
                'content-type': 'application/x-www-form-urlencoded'
            },
            dataType: 'json'
        }, params, {
            url: config.domains[params.api || 'api'] + (params.url || ''),
        });

        // 构造好参数再请求
        return this.request(params);
    }
};

export default api;