login.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. var utils = require('./utils');
  2. var constants = require('./constants');
  3. var Session = require('./session');
  4. /***
  5. * @class
  6. * 表示登录过程中发生的异常
  7. */
  8. var LoginError = (function () {
  9. function LoginError(type, message) {
  10. Error.call(this, message);
  11. this.type = type;
  12. this.message = message;
  13. }
  14. LoginError.prototype = new Error();
  15. LoginError.prototype.constructor = LoginError;
  16. return LoginError;
  17. })();
  18. /**
  19. * 微信登录,获取 code 和 encryptData
  20. */
  21. var getWxLoginResult = function getLoginCode(callback) {
  22. wx.login({
  23. success: function (loginResult) {
  24. wx.getUserInfo({
  25. success: function (userResult) {
  26. callback(null, {
  27. code: loginResult.code,
  28. encryptedData: userResult.encryptedData,
  29. iv: userResult.iv,
  30. userInfo: userResult.userInfo,
  31. });
  32. },
  33. fail: function (userError) {
  34. var error = new LoginError(constants.ERR_WX_GET_USER_INFO, '获取微信用户信息失败,请检查网络状态');
  35. error.detail = userError;
  36. callback(error, null);
  37. },
  38. });
  39. },
  40. fail: function (loginError) {
  41. var error = new LoginError(constants.ERR_WX_LOGIN_FAILED, '微信登录失败,请检查网络状态');
  42. error.detail = loginError;
  43. callback(error, null);
  44. },
  45. });
  46. };
  47. var noop = function noop() {};
  48. var defaultOptions = {
  49. method: 'GET',
  50. success: noop,
  51. fail: noop,
  52. loginUrl: null,
  53. };
  54. /**
  55. * @method
  56. * 进行服务器登录,以获得登录会话
  57. *
  58. * @param {Object} options 登录配置
  59. * @param {string} options.loginUrl 登录使用的 URL,服务器应该在这个 URL 上处理登录请求
  60. * @param {string} [options.method] 请求使用的 HTTP 方法,默认为 "GET"
  61. * @param {Function} options.success(userInfo) 登录成功后的回调函数,参数 userInfo 微信用户信息
  62. * @param {Function} options.fail(error) 登录失败后的回调函数,参数 error 错误信息
  63. */
  64. var login = function login(options) {
  65. options = utils.extend({}, defaultOptions, options);
  66. if (!defaultOptions.loginUrl) {
  67. options.fail(new LoginError(constants.ERR_INVALID_PARAMS, '登录错误:缺少登录地址,请通过 setLoginUrl() 方法设置登录地址'));
  68. return;
  69. }
  70. var doLogin = () => getWxLoginResult(function (wxLoginError, wxLoginResult) {
  71. if (wxLoginError) {
  72. options.fail(wxLoginError);
  73. return;
  74. }
  75. var userInfo = wxLoginResult.userInfo;
  76. // 构造请求头,包含 code、encryptedData 和 iv
  77. var code = wxLoginResult.code;
  78. var encryptedData = wxLoginResult.encryptedData;
  79. var iv = wxLoginResult.iv;
  80. var header = {};
  81. header[constants.WX_HEADER_CODE] = code;
  82. header[constants.WX_HEADER_ENCRYPTED_DATA] = encryptedData;
  83. header[constants.WX_HEADER_IV] = iv;
  84. // 请求服务器登录地址,获得会话信息
  85. wx.request({
  86. url: options.loginUrl,
  87. header: header,
  88. method: options.method,
  89. data: options.data,
  90. success: function (result) {
  91. var data = result.data;
  92. // 成功地响应会话信息
  93. if (data && data[constants.WX_SESSION_MAGIC_ID]) {
  94. if (data.session) {
  95. data.session.userInfo = userInfo;
  96. Session.set(data.session);
  97. options.success(userInfo);
  98. } else {
  99. var errorMessage = '登录失败(' + data.error + '):' + (data.message || '未知错误');
  100. var noSessionError = new LoginError(constants.ERR_LOGIN_SESSION_NOT_RECEIVED, errorMessage);
  101. options.fail(noSessionError);
  102. }
  103. // 没有正确响应会话信息
  104. } else {
  105. var errorMessage = '登录请求没有包含会话响应,请确保服务器处理 `' + options.loginUrl + '` 的时候正确使用了 SDK 输出登录结果';
  106. var noSessionError = new LoginError(constants.ERR_LOGIN_SESSION_NOT_RECEIVED, errorMessage);
  107. options.fail(noSessionError);
  108. }
  109. },
  110. // 响应错误
  111. fail: function (loginResponseError) {
  112. var error = new LoginError(constants.ERR_LOGIN_FAILED, '登录失败,可能是网络错误或者服务器发生异常');
  113. options.fail(error);
  114. },
  115. });
  116. });
  117. var session = Session.get();
  118. if (session) {
  119. wx.checkSession({
  120. success: function () {
  121. options.success(session.userInfo);
  122. },
  123. fail: function () {
  124. Session.clear();
  125. doLogin();
  126. },
  127. });
  128. } else {
  129. doLogin();
  130. }
  131. };
  132. var setLoginUrl = function (loginUrl) {
  133. defaultOptions.loginUrl = loginUrl;
  134. };
  135. module.exports = {
  136. LoginError: LoginError,
  137. login: login,
  138. setLoginUrl: setLoginUrl,
  139. };