api.js 3.93 KB
import Taro from '@tarojs/taro';
import config from '../config';
import udid from './udid';
import { HmacSHA256, MD5 } from './crypto';
import { stringify } from 'querystringify';
import user from './user';

export const verify = {
	verifyMethod: 'ufo.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) {
				Taro.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 = Taro.getStorageSync('verifyKey');

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

		return verifyKey || '';
	},
	sortData(data) {
		let newData = {};

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

		return newData;
	},
	stringify(data) {
		let str = '';

		Object.keys(data).forEach((key, index) => {
			str += index !== 0 ? `&${key}=${data[key]}` : `${key}=${data[key]}`;
		});

		return str;
	},
	sign(data) {
		const verifyKey = this.get();

		if (!verifyKey) {
			return '';
		}

		data = this.stringify(data);
		return HmacSHA256(data, verifyKey).toString();
	},
	computeSecret(data, encode = false) {
		let newData = {};

		data.private_key = config.apiParams.private_key;

		newData = this.sortData(data);
		newData.client_secret = MD5(stringify(newData, encode)).toString();
		delete newData.private_key;

		newData = this.sortData(newData)

		return newData;
	}
};

const api = {
	request(params) {
		// 公有参数
		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 Taro.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 {
			return result && result.data || {};
		}
		}).catch(err => {
			return {};
		});
	},
	addSessionKey(params) {
		params = Object.assign({}, params);

		let sessionKey = user.getYHStorageSync('session_key', 'app');
		let userInfo = user.getYHStorageSync('userInfo', 'app') || {};

		if (sessionKey && params.data.method != "ufo.resource.get") {
			params.data.session_key = sessionKey;

			if (!params.data.uid) {
				params.data.uid = userInfo.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,
			udid: udid.get(),
			business_line: config.business_line,
			source_type: 'wechat',
			user_source: 'wechat'
		}, 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;