request.js 8.7 KB
import getPrivateKey from './getPrivateKey'
import config from '../../config.js'
import trimObject from './utils/trimObject.js'
import queryString from './utils/query-string/query-string.js'
const crypto = require('./utils/cryptojs/cryptojs.js');
import MD5 from './utils/md5/md5.js'
import udid from './utils/udid.js'

const request = (methods = 'GET') => {
  return async (options = {}) => {
    try {
      let pk = await getPrivateKey();
      options.pk = pk;
      options.methods = methods;
      return new Promise(function (resolve, reject) {
        sendRequest(resolve, reject, options);
      })
    } catch (e) {
      return new Promise(function (resolve, reject) {
        if (!e || !e.isPrivatekeyError) {
          reject(e);
        }
        sendRequest(resolve, reject, options);
      })
    }
  }
}

const getGlobalData = () => {
  const app = getApp();
  let globalData;
  if (app && app.globalData) {
    // 原生小程序的 globalData 获取方式
    globalData = app && app.globalData;
  } else {
    // Taro 下 globalData 获取方式
    globalData = app && app.props && app.props.globalData;
  }
  return globalData;
}

/**
 * 请求参数相关
 */
const handleParam = (params) => {
  let globalData = getGlobalData();
  getUid(params);
  getUdid(params);
  const userInfo = getStorageUserInfo();
  const session_key = userInfo && userInfo.session_key ? userInfo.session_key : '';
  const publicParams = _publicParams();
  let newParams = {
    ...params,
    ...publicParams,
  };
  if (session_key) {
    newParams.session_key = session_key;
  }
  return newParams;
}

const getUdid = (params) => {
  params.udid = udid.get();
}

const getUid = (params) => {
  const userInfo = getStorageUserInfo();
  if (params && !params.hasOwnProperty('uid')) {
    // 判断 globalData 是否包含 uid
    let uid = userInfo && userInfo.uid ? userInfo.uid : 0;
    if (uid !== 0) {
      params.uid = uid;
    }
  }
}

const _publicParams = () => {
  let screen_size;
  let os_version;
  try {
    let res = wx.getSystemInfoSync();
    screen_size = res.windowWidth + 'x' + res.windowHeight;
    os_version = res.version;
  } catch (e) {}
  let publicParams = {
    ...config.apiParams,
    v: '7',
    screen_size,
    // os_version
  }
  return publicParams;
}

const _signParam = (params, encode = false) => {
  const resultParams = _signResultParams(params, encode);
  const resultString = queryString.stringify(resultParams, { encode });
  return resultString;
}

const _signResultParams = (params, encode = false) => {
  let allParams = trimObject(params);	// 去除首尾空格
  let paramsPair = queryString.stringify(allParams, { encode: false });
  let client_secret = MD5(paramsPair);
  delete allParams.private_key;
  const resultParams = Object.assign(allParams, { client_secret });
  return resultParams;
}

/**
 * 请求头相关
 */
const handleHeader = (options, newParams) => {
  let p2SecretKey = options.pk;
  if (p2SecretKey === '') {
    p2SecretKey = getYHStorageSync("p2SecretKey", 'request')
  }
  let param = _signParam(newParams, false);
  let resultString = ''
  if (p2SecretKey) {
    resultString = crypto.HMAC(crypto.SHA256, param, p2SecretKey, "")
  }
  const session_key = newParams.session_key ? newParams.session_key : '';
  let header = {
    'x-yoho-verify': resultString,
    'Cookie': 'JSESSIONID=' + session_key,
    'Cookies': 'JSESSIONID=' + session_key,
  }
  return header;
}

/**
 * 发送请求
 */
const sendRequest = (resolve, reject, options) => {
  // 处理请求参数
  const newParams = handleParam(options.params);
  const resultParams = _signResultParams(newParams, options.encode);
  // 处理请求头
  const header = handleHeader(options, newParams);
  // path 路径
  let url = options.url;
  if (options.path) {
    url = url + options.path;
  }
  // 请求
  wx.request({
    url: url,
    data: resultParams,
    header: header,
    method: options.methods,
    success: function(res) {
      const statusCode = res.statusCode;
      const errMsg = res.errMsg;
      const data = res.data;
      if (resultParams.method === 'app.passport.verify') {
        resolve(res);
      } else {
        if (data && (data.code == 200 || data.code == 301) && data.data) {
          resolve(data.data);
        } else {
          const code = data.code ? data.code : res.statusCode;
          const message = data.message ? data.message : res.errMsg;
          reject({ code, message });
        }
      }
    },
    fail: function (err) {
      const code = err.code ? err.code : 800;
      const message = err.message ? err.message : '';
      reject({ code, message });
    },
    complete: options.complete, // 无论成功还是失败, 都会调用,可以用于取消 loading 等
  })
}

const toPromise = (platform) => {
  return (method) => {
    return (option) => {
      return new Promise ((resolve, reject) => {
        platform[method]({
          ...option,
          success: (res) => { resolve(res) },
          fail: (err) => { reject(err) }
        })
      })
    }
  }
}
const toPromiseWX = toPromise(wx);
const getNetworkType = toPromiseWX('getNetworkType');

const _reportData = async (reportType, pt, pn, param, appObject) => {
  console.log('++++++++++', appObject);
  let globalData = appObject.props.globalData;
  let sid = appObject.globalData.sid;
  let ch = appObject.globalData.ch || '0';
  let ak = 'ufo_mp';
  let systemInfo = wx.getSystemInfoSync();
  console.log('系统systemInfo: ', systemInfo);
  const udid = wx.getStorageSync('udid');

  let device = {}
  device.ak = ak;
  device.udid = udid;
  device.ch = ch;
  device.os = "weixinapp";
  device.osv = systemInfo && systemInfo.version ? systemInfo.version : '';
  device.dm = systemInfo && systemInfo.model ? systemInfo.model.replace(' ', '_') : '';

  if (systemInfo.platform == 'ios'){
    //针对ios设备,特殊处理dm,转为iphone_7这种格式
    var start_num = device.dm.indexOf('<')
    var end_num = device.dm.indexOf('>')
    var deviceModel
    if (start_num != 0 && end_num != 0) {
      deviceModel = device.dm.substring(start_num + 1, end_num)
      if (deviceModel.length > 0) {
        deviceModel = deviceModel.replace(',', '_')
        device.dm = deviceModel
      }
    }
  }
  if (!pt || !pn || !device || !device.dm) return;
  if (!param) param = {};
  if (!reportType) reportType = 'hb';
  let ts = new Date().getTime() + '000000';
  let uid = globalData.userInfo && globalData.userInfo.uid ? MD5(globalData.userInfo.uid) : '';
  if(!uid){
    const userInfoSync = wx.getStorageSync('userInfo') || {};
    uid = MD5(userInfoSync.uid);
  }
  let res = await getNetworkType();
  let networkType = res && res.networkType;
  let net = '0';
  if (networkType === 'wifi') {
    net = '1';
  } else if (networkType === '2g') {
    net = '2';
  } else if (networkType === '3g') {
    net = '3';
  } else if (networkType === '4g') {
    net = '4';
  } else {
    net = '0';
  }

  let event = {}
  event.ps = '0',
  event.av = config.apiParams.app_version,
  event.ab = config.apiParams.app_version,
  event.ca = '0',
  event.net = net,
  event.sid = sid,
  event.uid = uid ? uid : '0',
  event.ts = ts,
  event.pt = pt,
  event.pn = pn,
  event.param = param;
  let  events = [event];
  let report_params = {
    events,
    type: reportType,
    device,
    sid: sid
  }
  return report_params
};

const appReport = (method = 'POST') => {
  return async (params = {}) => {
    let { reportType, pt, pn, param, appObject } = params;
    let report = await _reportData(reportType, pt, pn, param, appObject);
    return new Promise(function (resolve, reject) {
      let url = config.domains.reportHost;
      let sid = report.sid ? report.sid : report.sid || '';
      delete report['sid'];
      let data = JSON.stringify(report)
      let header = {
        'content-type': "application/json",
        'x-yoho-sid': MD5(sid),
      }
      wx.request({
        url,
        data,
        method,
        header,
        success: function(res) {
          resolve(res);
        },
        fail: function (err) {
          reject(err);
        }
      });
    })
  }
}

const getYHStorageSync = (key, fromPage) => {
  try {
    let res = wx.getStorageSync(key);
    return res;
  } catch (e) {
    wx.reportAnalytics('ufo_get_storage_error', {
      key: key,
      error: e.message,
      error_code: e.code,
      from_page: fromPage,
    });
    return null;
  }
}

const getStorageUserInfo = () => {
  const globalData = getGlobalData();
  if (globalData.userInfo.length > 0) {
    return globalData.userInfo;
  } else {
    return getYHStorageSync('userInfo');
  }
}

export const GET = request('GET');
export const POST = request('POST');
export const PUT = request('PUT');
export const DELETE = request('DELETE');
// export const UPLOAD_LOG = uploadLogData('POST')
export const APP_REPORT = appReport('POST')