oauth.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. # -*- coding: utf-8 -*-
  2. """
  3. unionpay.oauth
  4. ~~~~~~~~~~~~~~~
  5. This module provides OAuth2 library for unionpay
  6. :copyright: (c) 2014 by messense.
  7. :license: MIT, see LICENSE for more details.
  8. """
  9. from __future__ import absolute_import, unicode_literals
  10. import requests
  11. import six
  12. from apilib.systypes import StrEnum
  13. from apilib.utils_string import get_random_string
  14. import time
  15. from Crypto.Hash import SHA256
  16. from library import to_binary, to_text
  17. try:
  18. import simplejson as json
  19. except ImportError:
  20. import json # NOQA
  21. class UnionPayOAuth(object):
  22. """ 云闪付平台 OAuth 网页授权
  23. """
  24. class Scope(StrEnum):
  25. SNSAPI_BASE = 'snsapi_base'
  26. SNSAPI_UNION_LOGIN = 'snsapi_union_login'
  27. API_BASE_URL = 'https://open.95516.com/'
  28. OAUTH_BASE_URL = 'https://open.95516.com/s/open/html/oauth.html'
  29. def __str__(self):
  30. _repr = '{kclass}(appid: {appid})'.format(
  31. kclass = self.__class__.__name__,
  32. appid = self.app_id)
  33. if six.PY2:
  34. return to_binary(_repr)
  35. else:
  36. return to_text(_repr)
  37. def __repr__(self):
  38. return str(self)
  39. def __init__(self, app_id, secret):
  40. self.app_id = app_id
  41. self.secret = secret
  42. def _request(self, method, url_or_endpoint, **kwargs):
  43. if not url_or_endpoint.startswith(('http://', 'https://')):
  44. url = '{base}{endpoint}'.format(
  45. base = self.API_BASE_URL,
  46. endpoint = url_or_endpoint
  47. )
  48. else:
  49. url = url_or_endpoint
  50. if isinstance(kwargs.get('data', ''), dict):
  51. body = json.dumps(kwargs['data'], ensure_ascii = False)
  52. body = body.encode('utf-8')
  53. kwargs['data'] = body
  54. kwargs['timeout'] = kwargs.get('timeout', 15)
  55. with requests.sessions.Session() as session:
  56. res = session.request(
  57. method = method,
  58. url = url,
  59. **kwargs
  60. )
  61. try:
  62. res.raise_for_status()
  63. except requests.RequestException as reqe:
  64. return {'errmsg':u'网络异常'}
  65. result = json.loads(res.content.decode('utf-8', 'ignore'), strict = False)
  66. if 'msg' in result and result['errcode'] != 0:
  67. return result
  68. def _get(self, url, **kwargs):
  69. return self._request(
  70. method = 'get',
  71. url_or_endpoint = url,
  72. **kwargs
  73. )
  74. def get_oauth_token(self, auth_code):
  75. """获取 access_token
  76. :param auth_code: 授权完成跳转回来后 URL 中的 code 参数
  77. :return: JSON 数据包
  78. """
  79. #先计算出随机字符串
  80. nonceStr = get_random_string(16)
  81. timestamp = time.time()
  82. rawStr = 'appId=%s&secret=%s&nonceStr=%s&timestamp=%s'(self.app_id,self.secret,nonceStr,timestamp)
  83. digest = SHA256.new()
  84. signature = digest.update(rawStr)
  85. res = self._get(
  86. 'open/access/1.0/backendToken',
  87. params = {
  88. 'appId': self.app_id,
  89. 'nonceStr': nonceStr,
  90. 'timestamp': timestamp,
  91. 'signature': signature
  92. }
  93. )
  94. return res
  95. def get_user_info(self, token = None, code = None, lang = 'zh_CN'):
  96. res = self._get(
  97. 'open/access/1.0/backendToken',
  98. params = {
  99. 'appId': self.app_id,
  100. 'backendToken': token,
  101. 'code': code,
  102. 'grantType': 'authorization_code'
  103. }
  104. )
  105. return res
  106. def authorize_url(self, redirect_uri, scope):
  107. pass