login.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. # -*- coding: utf-8 -*-
  2. from __future__ import unicode_literals
  3. import json
  4. import requests
  5. from .base import Map, WeixinError
  6. __all__ = ("WeixinLoginError", "WeixinLogin")
  7. class WeixinLoginError(WeixinError):
  8. def __init__(self, msg):
  9. super(WeixinLoginError, self).__init__(msg)
  10. class WeixinLogin(object):
  11. def __init__(self, app_id, app_secret):
  12. self.sess = requests.Session()
  13. self.app_id = app_id
  14. self.app_secret = app_secret
  15. def _get(self, url, params):
  16. resp = self.sess.get(url, params=params)
  17. data = Map(json.loads(resp.content.decode("utf-8")))
  18. if data.errcode:
  19. msg = "%(errcode)d %(errmsg)s" % data
  20. raise WeixinLoginError(msg)
  21. return data
  22. def authorize(self, redirect_uri, scope="snsapi_base", state=None):
  23. """
  24. 生成微信认证地址并且跳转
  25. :param redirect_uri: 跳转地址
  26. :param scope: 微信认证方式,有`snsapi_base`跟`snsapi_userinfo`两种
  27. :param state: 认证成功后会原样带上此字段
  28. """
  29. url = "https://open.weixin.qq.com/connect/oauth2/authorize"
  30. assert scope in ["snsapi_base", "snsapi_userinfo"]
  31. data = dict()
  32. data.setdefault("appid", self.app_id)
  33. data.setdefault("redirect_uri", redirect_uri)
  34. data.setdefault("response_type", "code")
  35. data.setdefault("scope", scope)
  36. if state:
  37. data.setdefault("state", state)
  38. data = [(k, data[k]) for k in sorted(data.keys()) if data[k]]
  39. s = "&".join("=".join(kv) for kv in data if kv[1])
  40. return "{0}?{1}#wechat_redirect".format(url, s)
  41. def access_token(self, code):
  42. """
  43. 获取令牌
  44. """
  45. url = "https://api.weixin.qq.com/sns/oauth2/access_token"
  46. args = dict()
  47. args.setdefault("appid", self.app_id)
  48. args.setdefault("secret", self.app_secret)
  49. args.setdefault("code", code)
  50. args.setdefault("grant_type", "authorization_code")
  51. return self._get(url, args)
  52. def auth(self, access_token, openid):
  53. """
  54. 检验授权凭证
  55. :param access_token: 授权凭证
  56. :param openid: 唯一id
  57. """
  58. url = "https://api.weixin.qq.com/sns/auth"
  59. args = dict()
  60. args.setdefault("access_token", access_token)
  61. args.setdefault("openid", openid)
  62. return self._get(url, args)
  63. def refresh_token(self, refresh_token):
  64. """
  65. 重新获取access_token
  66. :param refresh_token: 刷新令牌
  67. """
  68. url = "https://api.weixin.qq.com/sns/oauth2/refresh_token"
  69. args = dict()
  70. args.setdefault("appid", self.app_id)
  71. args.setdefault("grant_type", "refresh_token")
  72. args.setdefault("refresh_token", refresh_token)
  73. return self._get(url, args)
  74. def userinfo(self, access_token, openid):
  75. """
  76. 获取用户信息
  77. :param access_token: 令牌
  78. :param openid: 用户id,每个应用内唯一
  79. """
  80. url = "https://api.weixin.qq.com/sns/userinfo"
  81. args = dict()
  82. args.setdefault("access_token", access_token)
  83. args.setdefault("openid", openid)
  84. args.setdefault("lang", "zh_CN")
  85. return self._get(url, args)
  86. def user_info(self, access_token, openid):
  87. """
  88. 获取用户信息
  89. 兼容老版本0.3.0,与WeixinMP的user_info冲突
  90. """
  91. return self.userinfo(access_token, openid)