Browse Source

微信小程序接口

locky 8 months ago
parent
commit
1efdddce71
3 changed files with 83 additions and 5 deletions
  1. 67 4
      Controller/WeChatMiniProgram/UserController.py
  2. 15 0
      Model/models.py
  3. 1 1
      Object/Enums/WeChatEnum.py

+ 67 - 4
Controller/WeChatMiniProgram/UserController.py

@@ -1,10 +1,15 @@
 # @Author    : Rocky
 # @File      : UserController.py
 # @Time      : 2024/11/27 16:35
+import hashlib
+import os
+import time
+
 import requests
 from Ansjer.config import LOGGER
 from django.views.generic.base import View
 
+from Model.models import WeChatMiniProgram
 from Object.Enums.WeChatEnum import WeChatMiniProgramAPIEnum, WeChatMiniProgramConfigEnum
 from Object.RedisObject import RedisObject
 from Object.ResponseObject import ResponseObject
@@ -19,16 +24,16 @@ class EquipmentFamilyView(View):
 
     def post(self, request, *args, **kwargs):
         request.encoding = 'utf-8'
-
         operation = kwargs.get('operation')
         return self.validation(request.POST, request, operation)
 
     def validation(self, request_dict, request, operation):
         lang = request_dict.get('lang', 'cn')
         response = ResponseObject(lang)
-        access_token = self.get_access_token()
         if operation == 'getPhoneNumber':
             return self.get_phone_number(request_dict, response)
+        elif operation == 'login':
+            return self.login(request_dict, response)
         else:
             return response.json(414)
 
@@ -71,7 +76,7 @@ class EquipmentFamilyView(View):
         获取手机号码
         @param request_dict:
         @param response:
-        @return: phone_number
+        @return: res
         """
         code = request_dict.get('code', None)
         if not code:
@@ -88,10 +93,68 @@ class EquipmentFamilyView(View):
             assert errcode == 0
             pure_phone_number = result['phone_info']['purePhoneNumber']
             res = {
-                'purePhoneNumber': pure_phone_number
+                'pure_phone_number': pure_phone_number
             }
             return response.json(0, res)
         except Exception as e:
             LOGGER.info('微信小程序获取手机号码异常:error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
             return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
 
+    @classmethod
+    def login(cls, request_dict, response):
+        """
+        小程序登录
+        https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-login/code2Session.html
+        https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html
+        @param request_dict:
+        @param response:
+        @return:
+        """
+        js_code = request_dict.get('js_code', None)
+        if not js_code:
+            return response.json(444)
+        try:
+            params = {
+                'js_code': js_code,
+                'grant_type': 'authorization_code',
+                'appid': WeChatMiniProgramConfigEnum.AppID.value,
+                'secret': WeChatMiniProgramConfigEnum.AppSecret.value
+            }
+            r = requests.get(url=WeChatMiniProgramAPIEnum.code2SessionAPI.value, params=params, timeout=5)
+            result = eval(r.content)
+            errcode = result.get('errcode')
+            assert errcode == 0
+            openid = result['openid']
+            unionid = result['unionid']
+            session_key = result['session_key']
+            # 生成登录态
+            login_status = cls.generate_login_status(openid, session_key)
+            now_time = int(time.time())
+            WeChatMiniProgram.objects.create(
+                login_status=login_status, openid=openid, unionid=unionid, session_key=session_key,
+                created_time=now_time, updated_time=now_time
+            )
+            res = {
+                'login_status': login_status
+            }
+            return response.json(0, res)
+        except Exception as e:
+            LOGGER.info('微信小程序登录异常:error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+            return response.json(500, 'error_line:{}, error_msg:{}'.format(e.__traceback__.tb_lineno, repr(e)))
+
+    @staticmethod
+    def generate_login_status(openid, session_key):
+        """
+        生成登录态
+        @param openid:
+        @param session_key:
+        @return: login_status
+        """
+        salt = os.urandom(16).hex()
+        # 将openid, session_key和salt拼接成一个字符串
+        to_hash = openid + session_key + salt
+        # 使用hashlib生成SHA256哈希值
+        hash_object = hashlib.sha256(to_hash.encode())
+        # 获取十六进制格式的哈希值
+        login_status = hash_object.hexdigest()
+        return login_status

+ 15 - 0
Model/models.py

@@ -5648,3 +5648,18 @@ class VodHls40(VodHlsBase):
     class Meta:
         db_table = 'vod_hls_40'
         verbose_name = '云存回放信息表40'
+
+
+class WeChatMiniProgram(models.Model):
+    id = models.AutoField(primary_key=True, verbose_name='自增标记ID')
+    login_status = models.CharField(default='', max_length=128, verbose_name='自定义登录态')
+    openid = models.CharField(default='', max_length=32, verbose_name='用户唯一标识')
+    unionid = models.CharField(default='', max_length=32, verbose_name='用户在开放平台的唯一标识符')
+    session_key = models.CharField(default='', max_length=150, verbose_name='会话密钥')
+    created_time = models.IntegerField(default=0, verbose_name='创建时间')
+    updated_time = models.IntegerField(default=0, verbose_name='更新时间')
+
+    class Meta:
+        db_table = 'wechat_mini_program'
+        verbose_name = '微信小程序'
+

+ 1 - 1
Object/Enums/WeChatEnum.py

@@ -15,4 +15,4 @@ class WeChatMiniProgramConfigEnum(IntEnum):
 class WeChatMiniProgramAPIEnum(IntEnum):
     getAccessTokenAPI = 'https://api.weixin.qq.com/cgi-bin/token'
     getPhoneNumberAPI = 'https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token={}'
-
+    code2SessionAPI = 'https://api.weixin.qq.com/sns/jscode2session'