UserController.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. # @Author : Rocky
  2. # @File : UserController.py
  3. # @Time : 2024/11/27 16:35
  4. import hashlib
  5. import os
  6. import time
  7. import requests
  8. from Ansjer.config import LOGGER
  9. from django.views.generic.base import View
  10. from Model.models import WeChatMiniProgram
  11. from Object.Enums.WeChatEnum import WeChatMiniProgramAPIEnum, WeChatMiniProgramConfigEnum
  12. from Object.RedisObject import RedisObject
  13. from Object.ResponseObject import ResponseObject
  14. class EquipmentFamilyView(View):
  15. def get(self, request, *args, **kwargs):
  16. request.encoding = 'utf-8'
  17. operation = kwargs.get('operation')
  18. return self.validation(request.GET, request, operation)
  19. def post(self, request, *args, **kwargs):
  20. request.encoding = 'utf-8'
  21. operation = kwargs.get('operation')
  22. return self.validation(request.POST, request, operation)
  23. def validation(self, request_dict, request, operation):
  24. lang = request_dict.get('lang', 'cn')
  25. response = ResponseObject(lang)
  26. if operation == 'getPhoneNumber':
  27. return self.get_phone_number(request_dict, response)
  28. elif operation == 'login':
  29. return self.login(request_dict, response)
  30. else:
  31. return response.json(414)
  32. @staticmethod
  33. def get_access_token():
  34. """
  35. 获取小程序全局唯一后台接口调用凭据,token有效期为7200s
  36. https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/mp-access-token/getAccessToken.html
  37. @return: access_token
  38. """
  39. try:
  40. redis_obj = RedisObject()
  41. access_token_key = WeChatMiniProgramConfigEnum.AccessTokenKey.value
  42. expires_time = redis_obj.get_ttl(access_token_key)
  43. # 如果有效时间大于十分钟,返回token,否则刷新token
  44. if expires_time > 10 * 60:
  45. access_token = redis_obj.get_data(access_token_key)
  46. return access_token
  47. else:
  48. params = {
  49. 'grant_type': 'client_credential',
  50. 'appid': WeChatMiniProgramConfigEnum.AppID.value,
  51. 'secret': WeChatMiniProgramConfigEnum.AppSecret.value
  52. }
  53. r = requests.get(url=WeChatMiniProgramAPIEnum.getAccessTokenAPI.value, params=params, timeout=5)
  54. result = eval(r.content)
  55. access_token = result.get('access_token')
  56. assert access_token
  57. expires_in = result.get('expires_in')
  58. # 保存到Redis
  59. redis_obj.set_ex_data(key=access_token_key, val=access_token, expire=expires_in)
  60. return access_token
  61. except Exception as e:
  62. LOGGER.info('微信小程序获取token异常:error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  63. return None
  64. @classmethod
  65. def get_phone_number(cls, request_dict, response):
  66. """
  67. 获取手机号码
  68. @param request_dict:
  69. @param response:
  70. @return: res
  71. """
  72. code = request_dict.get('code', None)
  73. if not code:
  74. return response.json(444)
  75. try:
  76. access_token = cls.get_access_token()
  77. url = WeChatMiniProgramAPIEnum.getPhoneNumberAPI.value.format(access_token)
  78. data = {
  79. 'code': code
  80. }
  81. r = requests.post(url=url, data=data, timeout=5)
  82. result = eval(r.content)
  83. errcode = result.get('errcode')
  84. assert errcode == 0
  85. pure_phone_number = result['phone_info']['purePhoneNumber']
  86. res = {
  87. 'pure_phone_number': pure_phone_number
  88. }
  89. return response.json(0, res)
  90. except Exception as e:
  91. LOGGER.info('微信小程序获取手机号码异常:error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  92. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  93. @classmethod
  94. def login(cls, request_dict, response):
  95. """
  96. 小程序登录
  97. https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-login/code2Session.html
  98. https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html
  99. @param request_dict:
  100. @param response:
  101. @return:
  102. """
  103. js_code = request_dict.get('js_code', None)
  104. if not js_code:
  105. return response.json(444)
  106. try:
  107. params = {
  108. 'js_code': js_code,
  109. 'grant_type': 'authorization_code',
  110. 'appid': WeChatMiniProgramConfigEnum.AppID.value,
  111. 'secret': WeChatMiniProgramConfigEnum.AppSecret.value
  112. }
  113. r = requests.get(url=WeChatMiniProgramAPIEnum.code2SessionAPI.value, params=params, timeout=5)
  114. result = eval(r.content)
  115. errcode = result.get('errcode')
  116. assert errcode == 0
  117. openid = result['openid']
  118. unionid = result['unionid']
  119. session_key = result['session_key']
  120. # 生成登录态
  121. login_status = cls.generate_login_status(openid, session_key)
  122. now_time = int(time.time())
  123. WeChatMiniProgram.objects.create(
  124. login_status=login_status, openid=openid, unionid=unionid, session_key=session_key,
  125. created_time=now_time, updated_time=now_time
  126. )
  127. res = {
  128. 'login_status': login_status
  129. }
  130. return response.json(0, res)
  131. except Exception as e:
  132. LOGGER.info('微信小程序登录异常:error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  133. return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
  134. @staticmethod
  135. def generate_login_status(openid, session_key):
  136. """
  137. 生成登录态
  138. @param openid:
  139. @param session_key:
  140. @return: login_status
  141. """
  142. salt = os.urandom(16).hex()
  143. # 将openid, session_key和salt拼接成一个字符串
  144. to_hash = openid + session_key + salt
  145. # 使用hashlib生成SHA256哈希值
  146. hash_object = hashlib.sha256(to_hash.encode())
  147. # 获取十六进制格式的哈希值
  148. login_status = hash_object.hexdigest()
  149. return login_status