@@ -0,0 +1,4 @@ |
||
1 |
+from django.contrib import admin |
|
2 |
+ |
|
3 |
+ |
|
4 |
+# Register your models here. |
@@ -0,0 +1,5 @@ |
||
1 |
+from django.apps import AppConfig |
|
2 |
+ |
|
3 |
+ |
|
4 |
+class AccountConfig(AppConfig): |
|
5 |
+ name = 'account' |
@@ -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 |
+ } |
@@ -0,0 +1,4 @@ |
||
1 |
+from django.test import TestCase |
|
2 |
+ |
|
3 |
+ |
|
4 |
+# Create your tests here. |
@@ -0,0 +1,4 @@ |
||
1 |
+from django.shortcuts import render |
|
2 |
+ |
|
3 |
+ |
|
4 |
+# Create your views here. |
@@ -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)) |
@@ -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 |
+] |
@@ -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 |
|