:art: Mini Login

huangqimin001 4 年之前
父節點
當前提交
93ab757a68
共有 10 個文件被更改,包括 276 次插入1 次删除
  1. 0 0
      account/__init__.py
  2. 4 0
      account/admin.py
  3. 5 0
      account/apps.py
  4. 0 0
      account/migrations/__init__.py
  5. 74 0
      account/models.py
  6. 4 0
      account/tests.py
  7. 4 0
      account/views.py
  8. 175 0
      api/mini_views.py
  9. 9 1
      api/urls.py
  10. 1 0
      hanyuan/settings.py

+ 0 - 0
account/__init__.py


+ 4 - 0
account/admin.py

@@ -0,0 +1,4 @@
1
+from django.contrib import admin
2
+
3
+
4
+# Register your models here.

+ 5 - 0
account/apps.py

@@ -0,0 +1,5 @@
1
+from django.apps import AppConfig
2
+
3
+
4
+class AccountConfig(AppConfig):
5
+    name = 'account'

+ 0 - 0
account/migrations/__init__.py


+ 74 - 0
account/models.py

@@ -0,0 +1,74 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+from django.db import models
4
+from django.utils.translation import ugettext_lazy as _
5
+from django_models_ext import BaseModelMixin, SexModelMixin
6
+from shortuuidfield import ShortUUIDField
7
+
8
+
9
+class UserInfo(BaseModelMixin):
10
+    UNVERIFIED = 0
11
+    ACTIVATED = 1
12
+    DISABLED = 2
13
+    DELETED = 3
14
+    ASSIGN = 10
15
+
16
+    USER_STATUS = (
17
+        (UNVERIFIED, u'未验证'),
18
+        (ACTIVATED, u'已激活'),
19
+        (DISABLED, u'已禁用'),
20
+        (DELETED, u'已删除'),
21
+        (ASSIGN, u'已分配'),
22
+    )
23
+
24
+    MALE = 1
25
+    FEMALE = 0
26
+
27
+    SEX_TYPE = (
28
+        (MALE, u'男'),
29
+        (FEMALE, u'女'),
30
+    )
31
+
32
+    user_id = ShortUUIDField(_('user_id'), max_length=32, blank=True, null=True, help_text='用户唯一标识', db_index=True, unique=True)
33
+
34
+    # 微信授权用户
35
+    unionid = models.CharField(_(u'unionid'), max_length=32, blank=True, null=True, help_text=u'微信 Unionid', db_index=True, unique=True)
36
+    openid = models.CharField(_(u'openid'), max_length=32, blank=True, null=True, help_text=u'微信公众号 Openid', db_index=True, unique=True)
37
+    openid_miniapp = models.CharField(_(u'openid_miniapp'), max_length=32, blank=True, null=True, help_text=u'微信小程序 Openid', db_index=True, unique=True)
38
+
39
+    # 用户基本信息
40
+    name = models.CharField(_(u'name'), max_length=255, blank=True, null=True, help_text=u'用户姓名')
41
+    sex = models.IntegerField(_(u'sex'), choices=SexModelMixin.SEX_TUPLE, default=SexModelMixin.UNKNOWN, help_text=u'用户性别')
42
+    nickname = models.CharField(_(u'nickname'), max_length=255, blank=True, null=True, help_text=u'用户昵称')
43
+    avatar = models.CharField(_(u'avatar'), max_length=255, blank=True, null=True, help_text=u'用户头像')
44
+    phone = models.CharField(_(u'phone'), max_length=11, blank=True, null=True, help_text=u'用户电话', db_index=True)
45
+    country = models.CharField(_(u'country'), max_length=255, blank=True, null=True, help_text=u'用户国家')
46
+    province = models.CharField(_(u'province'), max_length=255, blank=True, null=True, help_text=u'用户省份')
47
+    city = models.CharField(_(u'city'), max_length=255, blank=True, null=True, help_text=u'用户城市')
48
+
49
+    user_status = models.IntegerField(_(u'user_status'), choices=USER_STATUS, default=UNVERIFIED, help_text=u'用户状态')
50
+
51
+    class Meta:
52
+        verbose_name = _(u'用户信息')
53
+        verbose_name_plural = _(u'用户信息')
54
+
55
+    def __unicode__(self):
56
+        return '%d' % self.pk
57
+
58
+    @property
59
+    def data(self):
60
+        return {
61
+            'user_id': self.user_id,
62
+            'unionid': self.unionid,
63
+            'openid': self.openid,
64
+            'openid_miniapp': self.openid_miniapp,
65
+            'name': self.name,
66
+            'sex': self.sex,
67
+            'nickname': self.nickname,
68
+            'avatar': self.avatar,
69
+            'phone': self.phone,
70
+            'country': self.country,
71
+            'province': self.province,
72
+            'city': self.city,
73
+            'user_status': self.user_status,
74
+        }

+ 4 - 0
account/tests.py

@@ -0,0 +1,4 @@
1
+from django.test import TestCase
2
+
3
+
4
+# Create your tests here.

+ 4 - 0
account/views.py

@@ -0,0 +1,4 @@
1
+from django.shortcuts import render
2
+
3
+
4
+# Create your views here.

+ 175 - 0
api/mini_views.py

@@ -0,0 +1,175 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+import logging
4
+
5
+from django.conf import settings
6
+from django.db import transaction
7
+from django_logit import logit
8
+from django_response import response
9
+from ipaddr import client_ip
10
+from pywe_miniapp import get_session_info, get_session_key, get_userinfo, store_session_key
11
+from pywe_storage import RedisStorage
12
+from TimeConvert import TimeConvert as tc
13
+
14
+from account.models import UserInfo
15
+from utils.redis.connect import r
16
+
17
+
18
+WECHAT = settings.WECHAT
19
+logger = logging.getLogger('logit')
20
+
21
+
22
+@logit
23
+@transaction.atomic
24
+def get_userinfo_api(request):
25
+    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
26
+    appId = request.POST.get('appId', 'MINIAPP')
27
+
28
+    wxcfg = WECHAT.get(appId, {})
29
+
30
+    appid = wxcfg.get('appID')
31
+    secret = wxcfg.get('appsecret')
32
+
33
+    code = request.POST.get('code', '')
34
+    encryptedData = request.POST.get('encryptedData', '')
35
+    iv = request.POST.get('iv', '')
36
+
37
+    # {u'avatarUrl': u'http://wx.qlogo.cn/mmopen/vi_32/aSKcBBPpibyKNicHNTMM0qJVh8Kjgiak2AHWr8MHM4WgMEm7GFhsf8OYrySdbvAMvTsw3mo8ibKicsnfN5pRjl1p8HQ/0',
38
+    #  u'city': u'Guangzhou',
39
+    #  u'country': u'CN',
40
+    #  u'gender': 1,
41
+    #  u'language': u'zh_CN',
42
+    #  u'nickName': u'Band',
43
+    #  u'openId': u'oGZUI0egBJY1zhBYw2KhdUfwVJJE',
44
+    #  u'province': u'Guangdong',
45
+    #  u'unionId': u'ocMvos6NjeKLIBqg5Mr9QjxrP1FA',
46
+    #  u'watermark': {u'appid': u'wx4f4bc4dec97d474b', u'timestamp': 1477314187}}
47
+    session_key = get_session_key(appid=appid, secret=secret, code=code)
48
+    # Get Userinfo
49
+    userinfo = get_userinfo(appid=appid, secret=secret, code=code, session_key=session_key, encryptedData=encryptedData, iv=iv)
50
+
51
+    # Get or Create User
52
+    user, created = UserInfo.objects.select_for_update().get_or_create(unionid=userinfo.get('unionId', ''))
53
+
54
+    # Set User Key's Value
55
+    user.unionid = userinfo.get('unionId', '')
56
+    user.openid_miniapp = userinfo.get('openId', '')
57
+    user.sex = userinfo.get('gender', '')
58
+    user.nickname = userinfo.get('nickName', '')
59
+    user.avatar = userinfo.get('avatarUrl', '')
60
+    user.country = userinfo.get('country', '')
61
+    user.province = userinfo.get('province', '')
62
+    user.city = userinfo.get('city', '')
63
+    user.user_status = UserInfo.ACTIVATED
64
+    user.signup_ip = client_ip(request)
65
+    user.signup_at = tc.utc_datetime()
66
+    user.save()
67
+
68
+    # Store SessionKey
69
+    store_session_key(appid=appid, secret=secret, session_key=session_key, unid=user.user_id, storage=RedisStorage(r))
70
+    # Just for compatible because of store session_key has changed
71
+    store_session_key(appid=appid, secret=secret, session_key=session_key, unid='', storage=RedisStorage(r))
72
+
73
+    return response(200, 'Mini App Login Success', u'微信小程序登录成功', user.brandata(brand_id=brand_id))
74
+
75
+
76
+@logit(res=True)
77
+@transaction.atomic
78
+def mini_login_api(request):
79
+    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
80
+    appId = request.POST.get('appId', 'MINIAPP')
81
+
82
+    wxcfg = WECHAT.get(appId, {})
83
+
84
+    appid = wxcfg.get('appID')
85
+    secret = wxcfg.get('appsecret')
86
+
87
+    code = request.POST.get('code', '')
88
+
89
+    # // 正常返回的JSON数据包
90
+    # {
91
+    #     "openid": "OPENID",
92
+    #     "session_key": "SESSIONKEY",
93
+    # }
94
+    #
95
+    # // 满足UnionID返回条件时,返回的JSON数据包
96
+    # {
97
+    #     "openid": "OPENID",
98
+    #     "session_key": "SESSIONKEY",
99
+    #     "unionid": "UNIONID"
100
+    # }
101
+    # // 错误时返回JSON数据包(示例为Code无效)
102
+    # {
103
+    #     "errcode": 40029,
104
+    #     "errmsg": "invalid code"
105
+    # }
106
+    session_info = get_session_info(appid=appid, secret=secret, code=code)
107
+    logger.debug(session_info)
108
+    session_key = session_info.get('session_key', '')
109
+    unionid = session_info.get('unionid', '')
110
+    openid = session_info.get('openid', '')
111
+
112
+    # Get or Create User
113
+    user, created = UserInfo.objects.select_for_update().get_or_create(openid_miniapp=openid)
114
+
115
+    # Set User Key's Value
116
+    if unionid:
117
+        user.unionid = unionid
118
+
119
+    user.user_status = UserInfo.ACTIVATED
120
+    user.save()
121
+
122
+    # Store SessionKey
123
+    store_session_key(appid=appid, secret=secret, session_key=session_key, unid=user.user_id, storage=RedisStorage(r))
124
+    # Just for compatible because of store session_key has changed
125
+    store_session_key(appid=appid, secret=secret, session_key=session_key, unid='', storage=RedisStorage(r))
126
+
127
+    return response(200, 'Mini App Login Success', u'微信小程序登录成功', user.brandata(brand_id=brand_id))
128
+
129
+
130
+@logit
131
+@transaction.atomic
132
+def get_userinfo_api2(request):
133
+    brand_id = request.POST.get('brand_id', settings.KODO_DEFAULT_BRAND_ID)
134
+    user_id = request.POST.get('user_id', '')
135
+    appId = request.POST.get('appId', 'MINIAPP')
136
+
137
+    wxcfg = WECHAT.get(appId, {})
138
+
139
+    appid = wxcfg.get('appID')
140
+    secret = wxcfg.get('appsecret')
141
+
142
+    encryptedData = request.POST.get('encryptedData', '')
143
+    iv = request.POST.get('iv', '')
144
+
145
+    try:
146
+        user = UserInfo.objects.select_for_update().get(user_id=user_id, status=True)
147
+    except UserInfo.DoesNotExist:
148
+        return response()
149
+
150
+    # {u'avatarUrl': u'http://wx.qlogo.cn/mmopen/vi_32/aSKcBBPpibyKNicHNTMM0qJVh8Kjgiak2AHWr8MHM4WgMEm7GFhsf8OYrySdbvAMvTsw3mo8ibKicsnfN5pRjl1p8HQ/0',
151
+    #  u'city': u'Guangzhou',
152
+    #  u'country': u'CN',
153
+    #  u'gender': 1,
154
+    #  u'language': u'zh_CN',
155
+    #  u'nickName': u'Band',
156
+    #  u'openId': u'oGZUI0egBJY1zhBYw2KhdUfwVJJE',
157
+    #  u'province': u'Guangdong',
158
+    #  u'unionId': u'ocMvos6NjeKLIBqg5Mr9QjxrP1FA',
159
+    #  u'watermark': {u'appid': u'wx4f4bc4dec97d474b', u'timestamp': 1477314187}}
160
+    session_key = get_session_key(appid=appid, secret=secret, unid=user_id, storage=RedisStorage(r))
161
+    # Get Userinfo
162
+    userinfo = get_userinfo(appid=appid, secret=secret, session_key=session_key, encryptedData=encryptedData, iv=iv)
163
+
164
+    # Set User Key's Value
165
+    user.unionid = userinfo.get('unionId', '')
166
+    user.openid_miniapp = userinfo.get('openId', '')
167
+    user.sex = userinfo.get('gender', '')
168
+    user.nickname = userinfo.get('nickName', '')
169
+    user.avatar = userinfo.get('avatarUrl', '')
170
+    user.country = userinfo.get('country', '')
171
+    user.province = userinfo.get('province', '')
172
+    user.city = userinfo.get('city', '')
173
+    user.save()
174
+
175
+    return response(200, 'Mini App Get Userinfo Success', u'微信小程序获取用户信息成功', user.brandata(brand_id=brand_id))

+ 9 - 1
api/urls.py

@@ -2,7 +2,8 @@
2 2
 
3 3
 from django.conf.urls import url
4 4
 
5
-from api import branch_campus_admin_views, branch_campus_views, course_field_views, course_views, oauth_views, wx_views
5
+from api import (branch_campus_admin_views, branch_campus_views, course_field_views, course_views, mini_views,
6
+                 oauth_views, wx_views)
6 7
 
7 8
 
8 9
 urlpatterns = [
@@ -42,3 +43,10 @@ urlpatterns += [
42 43
     url(r'^course/field/list$', course_field_views.get_course_field_list, name='get_course_field_list'),
43 44
     url(r'^course/field/delete$', course_field_views.delete_course_field, name='delete_course_field'),
44 45
 ]
46
+
47
+# Mini App
48
+urlpatterns = [
49
+    url(r'^mini/userinfo$', mini_views.get_userinfo_api, name='get_userinfo_api'),  # 获取用户信息
50
+    url(r'^mini/login$', mini_views.mini_login_api, name='mini_login_api'),  # 小程序登录
51
+    url(r'^mini/userinfo2$', mini_views.get_userinfo_api2, name='get_userinfo_api2'),  # 获取用户信息
52
+]

+ 1 - 0
hanyuan/settings.py

@@ -56,6 +56,7 @@ INSTALLED_APPS = [
56 56
     'django_we',
57 57
     'commands',
58 58
     'api',
59
+    'account',
59 60
     'registration',
60 61
 ]
61 62