var utils = require('./utils'); var constants = require('./constants'); var Session = require('./session'); /*** * @class * 表示登录过程中发生的异常 */ var LoginError = (function () { function LoginError(type, message) { Error.call(this, message); this.type = type; this.message = message; } LoginError.prototype = new Error(); LoginError.prototype.constructor = LoginError; return LoginError; })(); /** * 微信登录,获取 code 和 encryptData */ var getWxLoginResult = function getLoginCode(callback) { wx.login({ success: function (loginResult) { wx.getUserInfo({ success: function (userResult) { console.log('[userResult]', userResult); callback(null, { code: loginResult.code, encryptedData: userResult.encryptedData, iv: userResult.iv, userInfo: userResult.userInfo, }); }, fail: function (userError) { console.log('[userError]', userError); var error = new LoginError(constants.ERR_WX_GET_USER_INFO, '获取微信用户信息失败,请检查网络状态'); error.detail = userError; callback(error, null); }, }); }, fail: function (loginError) { console.log('[loginError]', loginError); var error = new LoginError(constants.ERR_WX_LOGIN_FAILED, '微信登录失败,请检查网络状态'); error.detail = loginError; callback(error, null); }, }); }; var noop = function noop() {}; var defaultOptions = { method: 'GET', success: noop, fail: noop, loginUrl: null, }; /** * @method * 进行服务器登录,以获得登录会话 * * @param {Object} options 登录配置 * @param {string} options.loginUrl 登录使用的 URL,服务器应该在这个 URL 上处理登录请求 * @param {string} [options.method] 请求使用的 HTTP 方法,默认为 "GET" * @param {Function} options.success(userInfo) 登录成功后的回调函数,参数 userInfo 微信用户信息 * @param {Function} options.fail(error) 登录失败后的回调函数,参数 error 错误信息 */ var login = function login(options) { options = utils.extend({}, defaultOptions, options); if (!defaultOptions.loginUrl) { options.fail(new LoginError(constants.ERR_INVALID_PARAMS, '登录错误:缺少登录地址,请通过 setLoginUrl() 方法设置登录地址')); return; } var doLogin = () => getWxLoginResult(function (wxLoginError, wxLoginResult) { if (wxLoginError) { options.fail(wxLoginError); return; } var userInfo = wxLoginResult.userInfo; // 构造请求头,包含 code、encryptedData 和 iv var code = wxLoginResult.code; var encryptedData = wxLoginResult.encryptedData; var iv = wxLoginResult.iv; var header = {}; header[constants.WX_HEADER_CODE] = code; header[constants.WX_HEADER_ENCRYPTED_DATA] = encryptedData; header[constants.WX_HEADER_IV] = iv; // 请求服务器登录地址,获得会话信息 wx.request({ url: options.loginUrl, header: header, method: options.method, data: options.data, success: function (result) { var data = result.data; // 成功地响应会话信息 if (data && data.code === 0 && data.data.skey) { var res = data.data if (res.userinfo) { Session.set(res.skey); options.success(res.iminfo); } else { var errorMessage = '登录失败(' + data.error + '):' + (data.message || '未知错误'); var noSessionError = new LoginError(constants.ERR_LOGIN_SESSION_NOT_RECEIVED, errorMessage); options.fail(noSessionError); } // 没有正确响应会话信息 } else { var noSessionError = new LoginError(constants.ERR_LOGIN_SESSION_NOT_RECEIVED, JSON.stringify(data)); options.fail(noSessionError); } }, // 响应错误 fail: function (loginResponseError) { var error = new LoginError(constants.ERR_LOGIN_FAILED, '登录失败,可能是网络错误或者服务器发生异常'); options.fail(error); }, }); }); var session = Session.get(); if (session) { wx.checkSession({ success: function () { options.success(session.userinfo); }, fail: function () { Session.clear(); doLogin(); }, }); } else { doLogin(); } }; var setLoginUrl = function (loginUrl) { defaultOptions.loginUrl = loginUrl; }; module.exports = { LoginError: LoginError, login: login, setLoginUrl: setLoginUrl, };