an> - 0 jdjos/django_we_callback_settings.py
@@ -0,0 +1,81 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+ |
|
3 |
+ |
|
4 |
+def DJANGO_WE_CFG_FUNC(request, state=None): |
|
5 |
+ """ WeChat CFG Callback Func """ |
|
6 |
+ |
|
7 |
+ |
|
8 |
+def DJANGO_WE_QUOTE_STATE_FUNC(request, state): |
|
9 |
+ """ WeChat Quote Callback Func """ |
|
10 |
+ from utils.redis.connect import r |
|
11 |
+ return r.quote(state, short_uuid=True) |
|
12 |
+ |
|
13 |
+ |
|
14 |
+def DJANGO_WE_UNQUOTE_STATE_FUNC(request, state): |
|
15 |
+ """ WeChat UnQuote Callback Func """ |
|
16 |
+ from utils.redis.connect import r |
|
17 |
+ # If Not Buf, When Wechat Multi Request, Unquote Will Get None |
|
18 |
+ # Then Once Should ReOAuth, Will Raise Error |
|
19 |
+ return r.unquote(state, buf=True) or state |
|
20 |
+ |
|
21 |
+ |
|
22 |
+def DJANGO_WE_BASE_FUNC(code, state, access_info=None): |
|
23 |
+ """ WeChat Base Redirect Callback Func """ |
|
24 |
+ |
|
25 |
+ |
|
26 |
+def DJANGO_WE_BASE_COOKIE_FUNC(code, state, access_info=None): |
|
27 |
+ """ WeChat Base Set Cookie Redirect Callback Func """ |
|
28 |
+ |
|
29 |
+ |
|
30 |
+def DJANGO_WE_USERINFO_FUNC(code, state, access_info=None, userinfo=None): |
|
31 |
+ """ WeChat Userinfo Redirect Callback Func """ |
|
32 |
+ from django.conf import settings |
|
33 |
+ from utils.redis.connect import r |
|
34 |
+ from utils.user.userinfo_save import userinfo_save |
|
35 |
+ |
|
36 |
+ # Save profile or something else |
|
37 |
+ user = userinfo_save(userinfo) |
|
38 |
+ |
|
39 |
+ token_check_key = getattr(user, settings.TOKEN_CHECK_KEY) |
|
40 |
+ |
|
41 |
+ return { |
|
42 |
+ settings.TOKEN_CHECK_KEY: token_check_key, |
|
43 |
+ 'vtoken': r.token(token_check_key, ex=True, time=r.REDIS_EXPIRED_ONE_DAY, buf=False, short_uuid=True), |
|
44 |
+ } |
|
45 |
+ |
|
46 |
+ |
|
47 |
+def DJANGO_WE_USERINFO_COOKIE_FUNC(code, state, access_info=None, userinfo=None): |
|
48 |
+ """ WeChat Userinfo Set Cookie Redirect Callback Func """ |
|
49 |
+ from django.conf import settings |
|
50 |
+ from utils.user.userinfo_save import userinfo_save |
|
51 |
+ |
|
52 |
+ # Save profile or something else |
|
53 |
+ user = userinfo_save(userinfo) |
|
54 |
+ |
|
55 |
+ token_check_key = getattr(user, settings.TOKEN_CHECK_KEY) |
|
56 |
+ |
|
57 |
+ return {}, settings.TOKEN_CHECK_KEY, token_check_key |
|
58 |
+ |
|
59 |
+ |
|
60 |
+def DJANGO_WE_SHARE_FUNC(request, state=None): |
|
61 |
+ """ WeChat Share Callback Func """ |
|
62 |
+ # from django.conf import settings |
|
63 |
+ # return settings.WECHAT_OAUTH2_REDIRECT_URL |
|
64 |
+ |
|
65 |
+ |
|
66 |
+def DJANGO_WE_MESSAGE_CALLBACK_FUNC(request, xmldict, decrypted): |
|
67 |
+ """ WeChat Message Callback Func """ |
|
68 |
+ |
|
69 |
+ |
|
70 |
+def DJANGO_WE_COMPONENT_AUTH_FUNC(request, xmldict, decrypted): |
|
71 |
+ """ WeChat COMPONENT Auth Func """ |
|
72 |
+ |
|
73 |
+ |
|
74 |
+def DJANGO_WE_COMPONENT_CALLBACK_FUNC(request, appid, xmldict, decrypted): |
|
75 |
+ """ WeChat COMPONENT Callback Func """ |
|
76 |
+ |
|
77 |
+ |
|
78 |
+def DJANGO_WE_REDIS_OBJ_FUNC(request): |
|
79 |
+ """ WeChat Redis Object Callback Func """ |
|
80 |
+ from utils.redis.connect import r |
|
81 |
+ return r |
@@ -0,0 +1,16 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+ |
|
3 |
+import redis_extensions as redis |
|
4 |
+ |
|
5 |
+ |
|
6 |
+def redis_conf(conf): |
|
7 |
+ return { |
|
8 |
+ 'host': conf.get('HOST', 'localhost'), |
|
9 |
+ 'port': conf.get('PORT', 6379), |
|
10 |
+ 'password': '{0}:{1}'.format(conf.get('USER', ''), conf.get('PASSWORD', '')) if conf.get('USER') else '', |
|
11 |
+ 'db': conf.get('db', 0), |
|
12 |
+ } |
|
13 |
+ |
|
14 |
+ |
|
15 |
+def redis_connect(conf): |
|
16 |
+ return redis.StrictRedisExtensions(connection_pool=redis.ConnectionPool(**redis_conf(conf))) |
@@ -0,0 +1,17 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+ |
|
3 |
+# DEBUG = False |
|
4 |
+ |
|
5 |
+ALLOWED_HOSTS = ['127.0.0.1', 'localhost', 'jdjos'] |
|
6 |
+ |
|
7 |
+# DOMAIN |
|
8 |
+DOMAIN = 'http://a.com' |
|
9 |
+ |
|
10 |
+# 邮件设置 |
|
11 |
+# 只有当 DEBUG = False 的时候,才会邮件发送报错信息 |
|
12 |
+SERVER_EMAIL = 'error.notify@exmail.com' |
|
13 |
+EMAIL_HOST_USER = 'error.notify@exmail.com' |
|
14 |
+EMAIL_HOST_PASSWORD = '<^_^>pwd<^_^>' |
|
15 |
+DEFAULT_FROM_EMAIL = 'error.notify <error.notify@exmail.com>' |
|
16 |
+ADMINS = [('Zhang San', 'san.zhang@exmail.com'), ('Li Si', 'si.li@exmail.com')] |
|
17 |
+EMAIL_SUBJECT_PREFIX = u'[Templet] ' |
@@ -0,0 +1,27 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+ |
|
3 |
+import os |
|
4 |
+ |
|
5 |
+ |
|
6 |
+BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
|
7 |
+PROJ_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__))) |
|
8 |
+ |
|
9 |
+TEMPLATES = [ |
|
10 |
+ { |
|
11 |
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates', |
|
12 |
+ 'DIRS': [os.path.join(BASE_DIR, 'templates')], |
|
13 |
+ # 'APP_DIRS': True, |
|
14 |
+ 'OPTIONS': { |
|
15 |
+ 'context_processors': [ |
|
16 |
+ 'django.template.context_processors.debug', |
|
17 |
+ 'django.template.context_processors.request', |
|
18 |
+ 'django.contrib.auth.context_processors.auth', |
|
19 |
+ 'django.contrib.messages.context_processors.messages', |
|
20 |
+ ], |
|
21 |
+ 'loaders': [ |
|
22 |
+ 'django.template.loaders.filesystem.Loader', |
|
23 |
+ 'django.template.loaders.app_directories.Loader', |
|
24 |
+ ], |
|
25 |
+ }, |
|
26 |
+ }, |
|
27 |
+] |
@@ -0,0 +1,396 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+ |
|
3 |
+""" |
|
4 |
+Django settings for jdjos project. |
|
5 |
+ |
|
6 |
+Generated by 'django-admin startproject' using Django 1.11.3. |
|
7 |
+ |
|
8 |
+For more information on this file, see |
|
9 |
+https://docs.djangoproject.com/en/1.11/topics/settings/ |
|
10 |
+ |
|
11 |
+For the full list of settings and their values, see |
|
12 |
+https://docs.djangoproject.com/en/1.11/ref/settings/ |
|
13 |
+""" |
|
14 |
+ |
|
15 |
+import os |
|
16 |
+ |
|
17 |
+# try: |
|
18 |
+# from func_settings import redis_connect |
|
19 |
+# REDIS_CACHE = redis_connect(REDIS.get('default', {})) |
|
20 |
+# except ImportError: |
|
21 |
+# REDIS_CACHE = None |
|
22 |
+from django_redis_connector import connector |
|
23 |
+ |
|
24 |
+ |
|
25 |
+# Build paths inside the project like this: os.path.join(BASE_DIR, ...) |
|
26 |
+BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
|
27 |
+PROJ_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__))) |
|
28 |
+ |
|
29 |
+ |
|
30 |
+# Quick-start development settings - unsuitable for production |
|
31 |
+# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ |
|
32 |
+ |
|
33 |
+# SECURITY WARNING: keep the secret key used in production secret! |
|
34 |
+SECRET_KEY = '0=hpv21&am(7(k5ab!^zjvvl=ntj)^i@7)87t47uzumt_5rq$+' |
|
35 |
+ |
|
36 |
+# SECURITY WARNING: don't run with debug turned on in production! |
|
37 |
+DEBUG = True |
|
38 |
+ |
|
39 |
+ALLOWED_HOSTS = [] |
|
40 |
+ |
|
41 |
+ |
|
42 |
+# Application definition |
|
43 |
+ |
|
44 |
+INSTALLED_APPS = [ |
|
45 |
+ 'django.contrib.admin', |
|
46 |
+ 'django.contrib.auth', |
|
47 |
+ 'django.contrib.contenttypes', |
|
48 |
+ 'django.contrib.sessions', |
|
49 |
+ 'django.contrib.messages', |
|
50 |
+ 'django.contrib.staticfiles', |
|
51 |
+ # 'django_file_upload', |
|
52 |
+ # 'django_short_url', |
|
53 |
+ 'django_uniapi', |
|
54 |
+ 'django_admin', |
|
55 |
+ 'django_we', |
|
56 |
+ 'commands', |
|
57 |
+ 'api', |
|
58 |
+] |
|
59 |
+ |
|
60 |
+MIDDLEWARE = [ |
|
61 |
+ 'django.middleware.security.SecurityMiddleware', |
|
62 |
+ 'django.contrib.sessions.middleware.SessionMiddleware', |
|
63 |
+ 'django.middleware.common.CommonMiddleware', |
|
64 |
+ # 'django.middleware.csrf.CsrfViewMiddleware', |
|
65 |
+ 'django.contrib.auth.middleware.AuthenticationMiddleware', |
|
66 |
+ 'django.contrib.messages.middleware.MessageMiddleware', |
|
67 |
+ 'django.middleware.clickjacking.XFrameOptionsMiddleware', |
|
68 |
+ 'detect.middleware.UserAgentDetectionMiddleware', |
|
69 |
+] |
|
70 |
+ |
|
71 |
+ROOT_URLCONF = 'jdjos.urls' |
|
72 |
+ |
|
73 |
+TEMPLATES = [ |
|
74 |
+ { |
|
75 |
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates', |
|
76 |
+ 'DIRS': [os.path.join(BASE_DIR, 'templates')], |
|
77 |
+ # 'APP_DIRS': True, |
|
78 |
+ 'OPTIONS': { |
|
79 |
+ 'context_processors': [ |
|
80 |
+ 'django.template.context_processors.debug', |
|
81 |
+ 'django.template.context_processors.request', |
|
82 |
+ 'django.contrib.auth.context_processors.auth', |
|
83 |
+ 'django.contrib.messages.context_processors.messages', |
|
84 |
+ ], |
|
85 |
+ 'loaders': [ |
|
86 |
+ ('django.template.loaders.cached.Loader', [ |
|
87 |
+ 'django.template.loaders.filesystem.Loader', |
|
88 |
+ 'django.template.loaders.app_directories.Loader', |
|
89 |
+ ]), |
|
90 |
+ ], |
|
91 |
+ }, |
|
92 |
+ }, |
|
93 |
+] |
|
94 |
+ |
|
95 |
+WSGI_APPLICATION = 'jdjos.wsgi.application' |
|
96 |
+ |
|
97 |
+ |
|
98 |
+# Database9 |
|
99 |
+# https://docs.djangoproject.com/en/1.11/ref/settings/#databases |
|
100 |
+ |
|
101 |
+DATABASES = { |
|
102 |
+ # Create Database |
|
103 |
+ # CREATE DATABASE jdjos DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; |
|
104 |
+ 'default': { |
|
105 |
+ 'ENGINE': 'django.db.backends.mysql', |
|
106 |
+ 'NAME': 'jdjos', |
|
107 |
+ 'USER': 'root', |
|
108 |
+ 'PASSWORD': '', |
|
109 |
+ 'HOST': '127.0.0.1', |
|
110 |
+ 'PORT': 3306, |
|
111 |
+ 'CONN_MAX_AGE': 600, |
|
112 |
+ 'OPTIONS': { |
|
113 |
+ # Utf8mb4 for Emoji |
|
114 |
+ # |
|
115 |
+ # Nickname |
|
116 |
+ # |
|
117 |
+ # account.WechatInfo ==> nickname |
|
118 |
+ # ALTER TABLE account_wechatinfo MODIFY COLUMN nickname VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; |
|
119 |
+ 'charset': 'utf8mb4', |
|
120 |
+ }, |
|
121 |
+ } |
|
122 |
+} |
|
123 |
+ |
|
124 |
+ |
|
125 |
+# Password validation |
|
126 |
+# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators |
|
127 |
+ |
|
128 |
+AUTH_PASSWORD_VALIDATORS = [ |
|
129 |
+ { |
|
130 |
+ 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', |
|
131 |
+ }, |
|
132 |
+ { |
|
133 |
+ 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', |
|
134 |
+ }, |
|
135 |
+ { |
|
136 |
+ 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', |
|
137 |
+ }, |
|
138 |
+ { |
|
139 |
+ 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', |
|
140 |
+ }, |
|
141 |
+] |
|
142 |
+ |
|
143 |
+ |
|
144 |
+# Internationalization |
|
145 |
+# https://docs.djangoproject.com/en/1.11/topics/i18n/ |
|
146 |
+ |
|
147 |
+LANGUAGE_CODE = 'zh-Hans' |
|
148 |
+ |
|
149 |
+TIME_ZONE = 'Asia/Shanghai' |
|
150 |
+ |
|
151 |
+USE_I18N = True |
|
152 |
+ |
|
153 |
+USE_L10N = True |
|
154 |
+ |
|
155 |
+USE_TZ = True |
|
156 |
+ |
|
157 |
+ |
|
158 |
+# Static files (CSS, JavaScript, Images) |
|
159 |
+# https://docs.djangoproject.com/en/1.11/howto/static-files/ |
|
160 |
+ |
|
161 |
+STATICFILES_DIRS = ( |
|
162 |
+ os.path.join(PROJ_DIR, 'static').replace('\\', '/'), |
|
163 |
+) |
|
164 |
+ |
|
165 |
+STATIC_ROOT = os.path.join(BASE_DIR, 'collect_static').replace('\\', '/') |
|
166 |
+ |
|
167 |
+STATIC_URL = '/static/' |
|
168 |
+ |
|
169 |
+STATICFILES_FINDERS = ( |
|
170 |
+ 'django.contrib.staticfiles.finders.FileSystemFinder', |
|
171 |
+ 'django.contrib.staticfiles.finders.AppDirectoriesFinder', |
|
172 |
+ # 'django.contrib.staticfiles.finders.DefaultStorageFinder', |
|
173 |
+) |
|
174 |
+ |
|
175 |
+MEDIA_ROOT = os.path.join(BASE_DIR, 'media').replace('\\', '/') |
|
176 |
+ |
|
177 |
+MEDIA_URL = '/media/' |
|
178 |
+ |
|
179 |
+# File 设置 |
|
180 |
+FILE_UPLOAD_MAX_MEMORY_SIZE = 5242880 # InMemoryUploadedFile 文件最大值,设置为 5 MB |
|
181 |
+FILE_UPLOAD_PERMISSIONS = 0o644 # TemporaryUploadedFile 文件权限设置 |
|
182 |
+ |
|
183 |
+# DOMAIN |
|
184 |
+DOMAIN = 'http://a.com' |
|
185 |
+ |
|
186 |
+# Redis 设置 |
|
187 |
+REDIS = { |
|
188 |
+ 'default': { |
|
189 |
+ 'HOST': '127.0.0.1', |
|
190 |
+ 'PORT': 6379, |
|
191 |
+ 'USER': '', |
|
192 |
+ 'PASSWORD': '', |
|
193 |
+ 'db': 0, |
|
194 |
+ } |
|
195 |
+} |
|
196 |
+ |
|
197 |
+# 微信设置 |
|
198 |
+WECHAT = { |
|
199 |
+ 'JSAPI': { |
|
200 |
+ 'trade_type': 'JSAPI', # JSAPI-网页支付、Native-原生支付、APP-APP支付、MICROPAY-刷卡支付 |
|
201 |
+ 'token': '5201314', |
|
202 |
+ 'appID': '', |
|
203 |
+ 'appsecret': '', |
|
204 |
+ 'encodingaeskey': '', |
|
205 |
+ 'mchID': '', |
|
206 |
+ 'apiKey': '', |
|
207 |
+ 'mch_cert': '', |
|
208 |
+ 'mch_key': '', |
|
209 |
+ 'redpack': { |
|
210 |
+ |
|
211 |
+ } |
|
212 |
+ }, |
|
213 |
+} |
|
214 |
+ |
|
215 |
+WECHAT_DEFAULT_CFG = 'JSAPI' |
|
216 |
+ |
|
217 |
+# 微信唯一标识 |
|
218 |
+# Choices: 'unionid' or 'openid' |
|
219 |
+# |
|
220 |
+# models.py |
|
221 |
+# 'unique_identifier': self.unionid if settings.WECHAT_UNIQUE_IDENTIFICATION == 'unionid' else self.openid, |
|
222 |
+# views.py |
|
223 |
+# unique_identifier = request.POST.get(settings.WECHAT_UNIQUE_IDENTIFICATION, '') |
|
224 |
+# profile = Profile.objects.get(**{settings.WECHAT_UNIQUE_IDENTIFICATION: unique_identifier}) |
|
225 |
+# |
|
226 |
+# If not bind to OpenPlat, change `WECHAT_UNIQUE_IDENTIFICATION` as `openid` |
|
227 |
+WECHAT_UNIQUE_IDENTIFICATION = 'unionid' |
|
228 |
+ |
|
229 |
+# Token 错误重授权设置 |
|
230 |
+TOKEN_CHECK_KEY = '' |
|
231 |
+# TOKEN_CHECK_KEY = 'user_id' |
|
232 |
+WECHAT_OAUTH2_REDIRECT_ENTRY = '' |
|
233 |
+WECHAT_OAUTH2_REDIRECT_URL = '' |
|
234 |
+ |
|
235 |
+# Cookie 设置 |
|
236 |
+DJANGO_WE_COOKIE_MAX_AGE = COOKIE_MAX_AGE = 31536000 # 单位:秒,1年:365 * 24 * 60 * 60 = 31536000 |
|
237 |
+DJANGO_WE_COOKIE_SALT = COOKIE_SALT = 'djwe' # Salt for ``set_signed_cookie`` |
|
238 |
+# Cookie 校验设置 |
|
239 |
+COOKIE_USER_CHECK_KEY = '' |
|
240 |
+# COOKIE_USER_CHECK_KEY = 'user_id' |
|
241 |
+ |
|
242 |
+# 邮件设置 |
|
243 |
+# https://docs.djangoproject.com/en/1.11/howto/error-reporting/#email-reports |
|
244 |
+# When DEBUG is False, Django will email the users listed in the ADMINS setting |
|
245 |
+# whenever your code raises an unhandled exception and results in an internal server error (HTTP status code 500). |
|
246 |
+# 只有当 DEBUG = False 的时候,才会邮件发送报错信息 |
|
247 |
+# Email address that error messages come from. |
|
248 |
+SERVER_EMAIL = 'error.notify@exmail.com' |
|
249 |
+# The email backend to use. For possible shortcuts see django.core.mail. |
|
250 |
+# The default is to use the SMTP backend. |
|
251 |
+# Third-party backends can be specified by providing a Python path |
|
252 |
+# to a module that defines an EmailBackend class. |
|
253 |
+EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' |
|
254 |
+# Host for sending email. |
|
255 |
+EMAIL_HOST = 'smtp.exmail.qq.com' |
|
256 |
+# Port for sending email. |
|
257 |
+EMAIL_PORT = 25 |
|
258 |
+# Optional SMTP authentication information for EMAIL_HOST. |
|
259 |
+EMAIL_HOST_USER = 'error.notify@exmail.com' |
|
260 |
+EMAIL_HOST_PASSWORD = '<^_^>pwd<^_^>' |
|
261 |
+EMAIL_USE_TLS = False |
|
262 |
+EMAIL_USE_SSL = False |
|
263 |
+EMAIL_SSL_CERTFILE = None |
|
264 |
+EMAIL_SSL_KEYFILE = None |
|
265 |
+EMAIL_TIMEOUT = None |
|
266 |
+# Default email address to use for various automated correspondence from |
|
267 |
+# the site managers. |
|
268 |
+DEFAULT_FROM_EMAIL = 'error.notify <error.notify@exmail.com>' |
|
269 |
+# People who get code error notifications. |
|
270 |
+# In the format [('Full Name', 'email@example.com'), ('Full Name', 'anotheremail@example.com')] |
|
271 |
+ADMINS = [('Zhang San', 'san.zhang@exmail.com'), ('Li Si', 'si.li@exmail.com')] |
|
272 |
+# Not-necessarily-technical managers of the site. They get broken link |
|
273 |
+# notifications and other various emails. |
|
274 |
+MANAGERS = ADMINS |
|
275 |
+# Subject-line prefix for email messages send with django.core.mail.mail_admins |
|
276 |
+# or ...mail_managers. Make sure to include the trailing space. |
|
277 |
+EMAIL_SUBJECT_PREFIX = u'[Templet] ' |
|
278 |
+ |
|
279 |
+# Django-Admin Settings |
|
280 |
+DJANGO_ADMIN_DISABLE_DELETE_SELECTED = False |
|
281 |
+ |
|
282 |
+# Django-FILE-UPLOAD Settings |
|
283 |
+DJANGO_FILE_UPLOAD_USE_YM = True |
|
284 |
+DJANGO_FILE_UPLOAD_USE_DT = True |
|
285 |
+ |
|
286 |
+# Django-Logit Settings |
|
287 |
+DJANGO_LOGIT_ENABLED = True |
|
288 |
+DJANGO_LOGIT_BODY_FLAG = False |
|
289 |
+DJANGO_LOGIT_RES_FLAG = False |
|
290 |
+ |
|
291 |
+# Django-Onerror Settings |
|
292 |
+DJANGO_ONERROR_ACCEPT_REPORT = True |
|
293 |
+DJANGO_ONERROR_ADMIN_SITE_REGISTER = True |
|
294 |
+ |
|
295 |
+# Django-Short-URL Settings |
|
296 |
+# Redirect url when short url not exists |
|
297 |
+DJANGO_SHORT_URL_REDIRECT_URL = '' |
|
298 |
+ |
|
299 |
+# Django-We Settings |
|
300 |
+DJANGO_WE_QUOTE_OR_NOT = True |
|
301 |
+# Enable Cookie or not |
|
302 |
+# DJANGO_WE_BASE_REDIRECT_SET_COOKIE = False |
|
303 |
+# DJANGO_WE_USERINFO_REDIRECT_SET_COOKIE = True |
|
304 |
+# Cookie Config |
|
305 |
+DJANGO_WE_COOKIE_MAX_AGE = COOKIE_MAX_AGE |
|
306 |
+DJANGO_WE_COOKIE_SALT = COOKIE_SALT |
|
307 |
+ |
|
308 |
+# 开发调试相关配置 |
|
309 |
+if DEBUG: |
|
310 |
+ try: |
|
311 |
+ from local_settings_dev import * |
|
312 |
+ except ImportError: |
|
313 |
+ pass |
|
314 |
+ |
|
315 |
+try: |
|
316 |
+ from local_settings import * |
|
317 |
+except ImportError: |
|
318 |
+ pass |
|
319 |
+ |
|
320 |
+try: |
|
321 |
+ from django_file_callback_settings import * |
|
322 |
+except ImportError: |
|
323 |
+ pass |
|
324 |
+ |
|
325 |
+try: |
|
326 |
+ from django_we_callback_settings import * |
|
327 |
+except ImportError: |
|
328 |
+ pass |
|
329 |
+ |
|
330 |
+# 依赖 local_settings 中的配置 |
|
331 |
+# 微信授权设置 |
|
332 |
+# WECHAT_OAUTH2_REDIRECT_URI = '{0}/we/oauth2?scope={{0}}&redirect_url={{1}}'.format(DOMAIN) |
|
333 |
+# Shorten URL |
|
334 |
+# ``o`` is short for oauth2 |
|
335 |
+# ``r`` is short for redirect_url |
|
336 |
+WECHAT_OAUTH2_REDIRECT_URI = '{0}/we/o?scope={{0}}&r={{1}}'.format(DOMAIN) |
|
337 |
+WECHAT_OAUTH2_USERINFO_REDIRECT_URI = '{0}/we/o?r={{0}}'.format(DOMAIN) # Scope default snsapi_userinfo |
|
338 |
+WECHAT_BASE_REDIRECT_URI = '{0}/we/base_redirect'.format(DOMAIN) |
|
339 |
+WECHAT_USERINFO_REDIRECT_URI = '{0}/we/userinfo_redirect'.format(DOMAIN) |
|
340 |
+WECHAT_DIRECT_BASE_REDIRECT_URI = '{0}/we/direct_base_redirect'.format(DOMAIN) |
|
341 |
+WECHAT_DIRECT_USERINFO_REDIRECT_URI = '{0}/we/direct_userinfo_redirect'.format(DOMAIN) |
|
342 |
+ |
|
343 |
+JDJOS_OAUTH_AUTHORIZE = 'https://oauth.jd.com/oauth/authorize?response_type=code&client_id={client_id}&redirect_uri={redirect_uri}&state={state}' |
|
344 |
+JDJOS_OAUTH_TOKEN = 'https://oauth.jd.com/oauth/token?grant_type=authorization_code&client_id={client_id}&redirect_uri={redirect_uri}&code={code}&state={state}&client_secret={client_secret}' |
|
345 |
+JDJOS_REDIRECT_URI = '{0}/jos/oauth'.format(DOMAIN) |
|
346 |
+ |
|
347 |
+# Redis 连接 |
|
348 |
+WECHAT_REDIS_OBJ = REDIS_CACHE = connector(REDIS.get('default', {})) |
|
349 |
+ |
|
350 |
+# LOGGER 设置 |
|
351 |
+# python manage.py rlistlog --key=django:logit:jdjos --filename=/tmp/jdjos.logit.log |
|
352 |
+LOGGING = { |
|
353 |
+ 'version': 1, |
|
354 |
+ 'disable_existing_loggers': False, |
|
355 |
+ 'formatters': { |
|
356 |
+ 'verbose': { |
|
357 |
+ 'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s' |
|
358 |
+ }, |
|
359 |
+ 'simple': { |
|
360 |
+ 'format': '%(levelname)s %(message)s' |
|
361 |
+ }, |
|
362 |
+ }, |
|
363 |
+ 'handlers': { |
|
364 |
+ 'logit': { |
|
365 |
+ 'level': 'DEBUG', |
|
366 |
+ 'class': 'rlog.RedisListHandler', |
|
367 |
+ 'redis_client': REDIS_CACHE, |
|
368 |
+ 'key': 'django:logit:jdjos', |
|
369 |
+ 'formatter': 'verbose', |
|
370 |
+ }, |
|
371 |
+ 'console': { |
|
372 |
+ 'level': 'DEBUG', |
|
373 |
+ 'class': 'logging.StreamHandler', |
|
374 |
+ 'formatter': 'verbose' |
|
375 |
+ }, |
|
376 |
+ }, |
|
377 |
+ 'loggers': { |
|
378 |
+ 'logit': { |
|
379 |
+ 'handlers': ['logit'], |
|
380 |
+ 'level': 'DEBUG', |
|
381 |
+ 'propagate': True, |
|
382 |
+ }, |
|
383 |
+ 'console': { |
|
384 |
+ 'handlers': ['console'], |
|
385 |
+ 'level': 'DEBUG', |
|
386 |
+ 'propagate': True, |
|
387 |
+ }, |
|
388 |
+ }, |
|
389 |
+} |
|
390 |
+ |
|
391 |
+# MAX_BIGINT |
|
392 |
+# Why Not ``sys.maxint`` |
|
393 |
+# n bit platform sys.maxint = 2 ** (n - 1) - 1 |
|
394 |
+# 64 bit 9223372036854775807, 32 bit 2147483647 |
|
395 |
+from django.db.models import BigIntegerField # isort:skip |
|
396 |
+MAX_BIGINT = BigIntegerField.MAX_BIGINT |
@@ -0,0 +1,68 @@ |
||
1 |
+.text-center { |
|
2 |
+ text-align: center; |
|
3 |
+} |
|
4 |
+ |
|
5 |
+/* |
|
6 |
+ 文本溢出省略,元素需要设置定宽度 |
|
7 |
+ */ |
|
8 |
+/* 单行 */ |
|
9 |
+.text_ellipsis { |
|
10 |
+ overflow: hidden; |
|
11 |
+ white-space: nowrap; |
|
12 |
+ text-overflow: ellipsis; |
|
13 |
+} |
|
14 |
+/* 多行 */ |
|
15 |
+.a { |
|
16 |
+ overflow: hidden; |
|
17 |
+ text-overflow: ellipsis; |
|
18 |
+ display: -webkit-box; |
|
19 |
+ -webkit-line-clamp: 2; |
|
20 |
+ -webkit-box-orient: vertical; |
|
21 |
+} |
|
22 |
+ |
|
23 |
+/* |
|
24 |
+ 浮动 & 清除浮动 |
|
25 |
+ */ |
|
26 |
+.fl { |
|
27 |
+ float: left; |
|
28 |
+} |
|
29 |
+ |
|
30 |
+.fr { |
|
31 |
+ float: right; |
|
32 |
+} |
|
33 |
+ |
|
34 |
+.clearfix { |
|
35 |
+ zoom: 1; |
|
36 |
+} |
|
37 |
+ |
|
38 |
+.clearfix:after { |
|
39 |
+ content: "\200B"; |
|
40 |
+ display: block; |
|
41 |
+ height: 0; |
|
42 |
+ clear: both; |
|
43 |
+} |
|
44 |
+ |
|
45 |
+.clearfix:after {content:"."; display:block; height:0; visibility:hidden; clear:both; } |
|
46 |
+.clearfix { *zoom:1; } |
|
47 |
+ |
|
48 |
+/* |
|
49 |
+ 解决安卓微信点击图片预览问题 |
|
50 |
+ 这个会让 img 标签的点击事件失效,如果想要点击图片就要给上面再写一层 |
|
51 |
+ 需要长按识别二维码的时候,则再单独给该图片添加 |
|
52 |
+ ```css |
|
53 |
+ pointer-events: auto; |
|
54 |
+ ``` |
|
55 |
+ 来恢复对应的点击事件 |
|
56 |
+ */ |
|
57 |
+img { |
|
58 |
+ pointer-events: none; |
|
59 |
+} |
|
60 |
+ |
|
61 |
+.clickable { |
|
62 |
+ pointer-events: auto; |
|
63 |
+} |
|
64 |
+ |
|
65 |
+/* Input 自动填充后,移除 Chrome 默认黄色 */ |
|
66 |
+input:-webkit-autofill { |
|
67 |
+ box-shadow: 0 0 0 1000px white inset !important; |
|
68 |
+} |
@@ -0,0 +1,574 @@ |
||
1 |
+!(function(e, t) { |
|
2 |
+ var config = { |
|
3 |
+ wxconfig: 'http://api.tt4it.com/wx/jsapi_signature', |
|
4 |
+ callback: 'callback' |
|
5 |
+ }, wxData = { |
|
6 |
+ debug: false, |
|
7 |
+ imgUrl: '', |
|
8 |
+ link: '', |
|
9 |
+ desc: '', |
|
10 |
+ title: '', |
|
11 |
+ timeLine: '' |
|
12 |
+ }, wxConfig = { |
|
13 |
+ hide: false, |
|
14 |
+ baseFlag: false, |
|
15 |
+ baseHide: false, |
|
16 |
+ close: false, |
|
17 |
+ hideMenuItems: [], |
|
18 |
+ showMenuItems: [] |
|
19 |
+ }, jsApiList = [ |
|
20 |
+ 'checkJsApi', |
|
21 |
+ 'onMenuShareTimeline', |
|
22 |
+ 'onMenuShareAppMessage', |
|
23 |
+ 'onMenuShareQQ', |
|
24 |
+ 'onMenuShareWeibo', |
|
25 |
+ 'onMenuShareQZone', |
|
26 |
+ 'hideMenuItems', |
|
27 |
+ 'showMenuItems', |
|
28 |
+ 'hideAllNonBaseMenuItem', |
|
29 |
+ 'showAllNonBaseMenuItem', |
|
30 |
+ 'translateVoice', |
|
31 |
+ 'startRecord', |
|
32 |
+ 'stopRecord', |
|
33 |
+ 'onRecordEnd', |
|
34 |
+ 'playVoice', |
|
35 |
+ 'pauseVoice', |
|
36 |
+ 'stopVoice', |
|
37 |
+ 'uploadVoice', |
|
38 |
+ 'downloadVoice', |
|
39 |
+ 'chooseImage', |
|
40 |
+ 'previewImage', |
|
41 |
+ 'uploadImage', |
|
42 |
+ 'downloadImage', |
|
43 |
+ 'getLocalImgData', |
|
44 |
+ 'getNetworkType', |
|
45 |
+ 'openLocation', |
|
46 |
+ 'getLocation', |
|
47 |
+ 'hideOptionMenu', |
|
48 |
+ 'showOptionMenu', |
|
49 |
+ 'closeWindow', |
|
50 |
+ 'scanQRCode', |
|
51 |
+ 'chooseWXPay', |
|
52 |
+ 'openEnterpriseRedPacket', |
|
53 |
+ 'openProductSpecificView', |
|
54 |
+ 'addCard', |
|
55 |
+ 'chooseCard', |
|
56 |
+ 'openCard' |
|
57 |
+ ], wxApiFun |
|
58 |
+ |
|
59 |
+ function isEmpty(obj) { |
|
60 |
+ if (obj == null) return true |
|
61 |
+ if (obj.length > 0) return false |
|
62 |
+ if (obj.length === 0) return true |
|
63 |
+ for (var key in obj) { |
|
64 |
+ if (Object.prototype.hasOwnProperty.call(obj, key)) return false |
|
65 |
+ } |
|
66 |
+ return true |
|
67 |
+ } |
|
68 |
+ |
|
69 |
+ function isNotEmpty(obj) { |
|
70 |
+ return !isEmpty(obj) |
|
71 |
+ } |
|
72 |
+ |
|
73 |
+ function isOpenOnPC() { // 判断当前网页是否在 PC 浏览器中打开 |
|
74 |
+ var ua = navigator.userAgent |
|
75 |
+ return /windows nt/i.test(ua) || /macintosh/i.test(ua) || /linux x86_64/i.test(ua) |
|
76 |
+ } |
|
77 |
+ |
|
78 |
+ function isOpenInWeixin() { // 判断当前网页是否在微信内置浏览器中打开 |
|
79 |
+ return /micromessenger/i.test(navigator.userAgent) |
|
80 |
+ } |
|
81 |
+ |
|
82 |
+ function getWeixinVersion() { |
|
83 |
+ var ua = navigator.userAgent, |
|
84 |
+ mt = ua.match(/micromessenger\/([\d.]+)/i) |
|
85 |
+ return (mt ? mt[1] : '') |
|
86 |
+ } |
|
87 |
+ |
|
88 |
+ // This function checks whether Wechat is the appointed version or not |
|
89 |
+ // Cmp: http://jsperf.com/regexp-test-vs-indexof-ignore-upper-and-lower |
|
90 |
+ function isWeixinVersion(version) { |
|
91 |
+ // return new RegExp('micromessenger/' + version , 'i').test(navigator.userAgent) |
|
92 |
+ return navigator.userAgent.toLowerCase().indexOf('micromessenger/' + version) != -1 |
|
93 |
+ } |
|
94 |
+ |
|
95 |
+ function hideOptionMenu() { |
|
96 |
+ wxConfig.hide = true |
|
97 |
+ fixedWxData() |
|
98 |
+ } |
|
99 |
+ |
|
100 |
+ function showOptionMenu() { |
|
101 |
+ wxConfig.hide = false |
|
102 |
+ fixedWxData() |
|
103 |
+ } |
|
104 |
+ |
|
105 |
+ function hideMenuItems(items) { |
|
106 |
+ wxConfig.hideMenuItems = items |
|
107 |
+ fixedWxData() |
|
108 |
+ } |
|
109 |
+ |
|
110 |
+ function showMenuItems(items) { |
|
111 |
+ wxConfig.showMenuItems = items |
|
112 |
+ fixedWxData() |
|
113 |
+ } |
|
114 |
+ |
|
115 |
+ function hideAllNonBaseMenuItem() { |
|
116 |
+ wxConfig.baseFlag = true |
|
117 |
+ wxConfig.baseHide = true |
|
118 |
+ fixedWxData() |
|
119 |
+ } |
|
120 |
+ |
|
121 |
+ function showAllNonBaseMenuItem() { |
|
122 |
+ wxConfig.baseFlag = true |
|
123 |
+ wxConfig.baseHide = false |
|
124 |
+ fixedWxData() |
|
125 |
+ } |
|
126 |
+ |
|
127 |
+ function closeWindow() { |
|
128 |
+ wxConfig.close = true |
|
129 |
+ fixedWxData() |
|
130 |
+ } |
|
131 |
+ |
|
132 |
+ function wxReady(data) { |
|
133 |
+ data = typeof data === 'object' ? data : JSON.parse(data) |
|
134 |
+ wx.config({ |
|
135 |
+ debug: wxData.debug, |
|
136 |
+ appId: data.appId, |
|
137 |
+ timestamp: data.timestamp, |
|
138 |
+ nonceStr: data.nonceStr, |
|
139 |
+ signature: data.signature, |
|
140 |
+ jsApiList: jsApiList |
|
141 |
+ }) |
|
142 |
+ |
|
143 |
+ var callbacks = { |
|
144 |
+ trigger: function (res) { |
|
145 |
+ // alert('用户点击发送给朋友') |
|
146 |
+ if (JSWE.wxTrigger) {JSWE.wxTrigger(res)} |
|
147 |
+ }, |
|
148 |
+ success: function (res) { |
|
149 |
+ // alert('已分享') |
|
150 |
+ if (JSWE.wxSuccess) {JSWE.wxSuccess(res)} |
|
151 |
+ }, |
|
152 |
+ cancel: function (res) { |
|
153 |
+ // alert('已取消') |
|
154 |
+ if (JSWE.wxCancel) {JSWE.wxCancel(res)} |
|
155 |
+ }, |
|
156 |
+ fail: function (res) { |
|
157 |
+ // alert(JSON.stringify(res)) |
|
158 |
+ if (JSWE.wxFail) {JSWE.wxFail(res)} |
|
159 |
+ } |
|
160 |
+ }, shareInfo = function(flag) { |
|
161 |
+ var _share = { |
|
162 |
+ title: flag ? wxData.title : (wxData.timeLine || wxData.desc), |
|
163 |
+ link: wxData.link, |
|
164 |
+ imgUrl: wxData.imgUrl, |
|
165 |
+ trigger: callbacks.trigger, |
|
166 |
+ success: callbacks.success, |
|
167 |
+ cancel: callbacks.cancel, |
|
168 |
+ fail: callbacks.fail |
|
169 |
+ } |
|
170 |
+ if (flag) _share.desc = wxData.desc |
|
171 |
+ return _share |
|
172 |
+ }, wxShareApi = function() { |
|
173 |
+ // 2. 分享接口 |
|
174 |
+ // 2.1 监听“分享给朋友”,按钮点击、自定义分享内容及分享结果接口 |
|
175 |
+ wx.onMenuShareAppMessage(shareInfo(1)) |
|
176 |
+ // 2.2 监听“分享到朋友圈”按钮点击、自定义分享内容及分享结果接口 |
|
177 |
+ wx.onMenuShareTimeline(shareInfo(0)) |
|
178 |
+ // 2.3 监听“分享到QQ”按钮点击、自定义分享内容及分享结果接口 |
|
179 |
+ wx.onMenuShareQQ(shareInfo(1)) |
|
180 |
+ // 2.4 监听“分享到微博”按钮点击、自定义分享内容及分享结果接口 |
|
181 |
+ wx.onMenuShareWeibo(shareInfo(1)) |
|
182 |
+ // 2.5 监听“分享到QQ空间”按钮点击、自定义分享内容及分享结果接口 |
|
183 |
+ wx.onMenuShareQZone(shareInfo(1)) |
|
184 |
+ }, wxMenuApi = function () { |
|
185 |
+ // 8. 界面操作接口 |
|
186 |
+ // 8.1 隐藏右上角菜单 |
|
187 |
+ // 8.2 显示右上角菜单 |
|
188 |
+ if (wxConfig.hide) {wx.hideOptionMenu()} else {wx.showOptionMenu()} |
|
189 |
+ // 8.3 批量隐藏菜单项 |
|
190 |
+ if (isNotEmpty(wxConfig.hideMenuItems)) { |
|
191 |
+ wx.hideMenuItems({ |
|
192 |
+ menuList: wxConfig.hideMenuItems, |
|
193 |
+ success: function (res) { |
|
194 |
+ if (JSWE.wxHideMenuItemsSuccess) {JSWE.wxHideMenuItemsSuccess(res)} |
|
195 |
+ }, |
|
196 |
+ fail: function (res) { |
|
197 |
+ if (JSWE.wxHideMenuItemsFail) {JSWE.wxHideMenuItemsFail(res)} |
|
198 |
+ } |
|
199 |
+ }) |
|
200 |
+ } |
|
201 |
+ // 8.4 批量显示菜单项 |
|
202 |
+ if (isNotEmpty(wxConfig.showMenuItems)) { |
|
203 |
+ wx.showMenuItems({ |
|
204 |
+ menuList: wxConfig.showMenuItems, |
|
205 |
+ success: function (res) { |
|
206 |
+ if (JSWE.wxShowMenuItemsSuccess) {JSWE.wxShowMenuItemsSuccess(res)} |
|
207 |
+ }, |
|
208 |
+ fail: function (res) { |
|
209 |
+ if (JSWE.wxShowMenuItemsFail) {JSWE.wxShowMenuItemsFail(res)} |
|
210 |
+ } |
|
211 |
+ }) |
|
212 |
+ } |
|
213 |
+ // 8.5 隐藏所有非基本菜单项 |
|
214 |
+ // 8.6 显示所有被隐藏的非基本菜单项 |
|
215 |
+ if (wxConfig.baseFlag) { |
|
216 |
+ if (wxConfig.baseHide) {wx.hideAllNonBaseMenuItem()} else {wx.showAllNonBaseMenuItem()} |
|
217 |
+ } |
|
218 |
+ // 8.7 关闭当前窗口 |
|
219 |
+ if (wxConfig.close) {wx.closeWindow()} |
|
220 |
+ }, wxVoiceApi = function() { |
|
221 |
+ // 4.3 监听录音自动停止 |
|
222 |
+ wx.onVoiceRecordEnd({ |
|
223 |
+ complete: function (res) { |
|
224 |
+ voice.localId = res.localId |
|
225 |
+ if (JSWE.wxVoiceRecordEnd) {JSWE.wxVoiceRecordEnd(res)} |
|
226 |
+ } |
|
227 |
+ }) |
|
228 |
+ // 4.7 监听录音播放停止 |
|
229 |
+ wx.onVoicePlayEnd({ |
|
230 |
+ complete: function (res) { |
|
231 |
+ if (JSWE.wxVoicePlayEnd) {JSWE.wxVoicePlayEnd(res)} |
|
232 |
+ } |
|
233 |
+ }) |
|
234 |
+ }, wxApi = function () { |
|
235 |
+ wxShareApi() |
|
236 |
+ wxMenuApi() |
|
237 |
+ wxVoiceApi() |
|
238 |
+ } |
|
239 |
+ |
|
240 |
+ wx.ready(wxApi) |
|
241 |
+ |
|
242 |
+ return wxApiFun = wxApi |
|
243 |
+ } |
|
244 |
+ |
|
245 |
+ if (isOpenInWeixin() || isOpenOnPC()) { |
|
246 |
+ if ('undefined' !== typeof JSWE_CONF_UPDATE) JSWE_CONF_UPDATE(config) |
|
247 |
+ $.ajax({ |
|
248 |
+ url: config.wxconfig, |
|
249 |
+ type: 'get', |
|
250 |
+ dataType: 'jsonp', |
|
251 |
+ jsonpCallback: config.callback, |
|
252 |
+ data: { |
|
253 |
+ url: window.location.href.split('#')[0] |
|
254 |
+ }, |
|
255 |
+ success: wxReady |
|
256 |
+ }) |
|
257 |
+ } |
|
258 |
+ |
|
259 |
+ function initWxData(data, flag) { |
|
260 |
+ for(var d in data) {if (d in wxData) wxData[d] = data[d]} |
|
261 |
+ if (flag) fixedWxData() |
|
262 |
+ } |
|
263 |
+ |
|
264 |
+ function changeWxData(key, value, flag) { |
|
265 |
+ if (key in falDwxDataata) {wxData[key] = value} |
|
266 |
+ if (flag) fixedWxData() |
|
267 |
+ } |
|
268 |
+ |
|
269 |
+ function fixedWxData() { |
|
270 |
+ if ('undefined' !== typeof wxApiFun) wxApiFun() |
|
271 |
+ } |
|
272 |
+ |
|
273 |
+ // 3 智能接口 |
|
274 |
+ var voice = { |
|
275 |
+ localId: '', |
|
276 |
+ serverId: '' |
|
277 |
+ } |
|
278 |
+ // 3.1 识别音频并返回识别结果 |
|
279 |
+ function translateVoice() { |
|
280 |
+ if (voice.localId == '') { |
|
281 |
+ if (JSWE.wxTranslateVoiceEmpty) {JSWE.wxTranslateVoiceEmpty()} |
|
282 |
+ return |
|
283 |
+ } |
|
284 |
+ wx.translateVoice({ |
|
285 |
+ localId: voice.localId, |
|
286 |
+ complete: function (res) { |
|
287 |
+ if (JSWE.wxTranslateVoiceComplete) {JSWE.wxTranslateVoiceComplete(res)} |
|
288 |
+ } |
|
289 |
+ }) |
|
290 |
+ } |
|
291 |
+ |
|
292 |
+ // 4 音频接口 |
|
293 |
+ // 4.1 开始录音 |
|
294 |
+ function startRecord() { |
|
295 |
+ wx.startRecord({ |
|
296 |
+ cancel: function () { |
|
297 |
+ if (JSWE.wxStartRecordCancel) {JSWE.wxStartRecordCancel(res)} |
|
298 |
+ } |
|
299 |
+ }) |
|
300 |
+ } |
|
301 |
+ |
|
302 |
+ // 4.2 停止录音 |
|
303 |
+ function stopRecord() { |
|
304 |
+ wx.stopRecord({ |
|
305 |
+ success: function (res) { |
|
306 |
+ voice.localId = res.localId |
|
307 |
+ if (JSWE.wxStopRecordSuccess) {JSWE.wxStopRecordSuccess(res)} |
|
308 |
+ }, |
|
309 |
+ fail: function (res) { |
|
310 |
+ if (JSWE.wxStopRecordFail) {JSWE.wxStopRecordFail(res)} |
|
311 |
+ } |
|
312 |
+ }) |
|
313 |
+ } |
|
314 |
+ |
|
315 |
+ // 4.4 播放音频 |
|
316 |
+ function playVoice() { |
|
317 |
+ if (voice.localId == '') { |
|
318 |
+ if (JSWE.wxPlayVoiceEmpty) {JSWE.wxPlayVoiceEmpty()} |
|
319 |
+ return |
|
320 |
+ } |
|
321 |
+ wx.playVoice({ |
|
322 |
+ localId: voice.localId |
|
323 |
+ }) |
|
324 |
+ } |
|
325 |
+ |
|
326 |
+ // 4.5 暂停播放音频 |
|
327 |
+ function pauseVoice() { |
|
328 |
+ if (voice.localId == '') { |
|
329 |
+ if (JSWE.wxPauseVoiceEmpty) {JSWE.wxPauseVoiceEmpty()} |
|
330 |
+ return |
|
331 |
+ } |
|
332 |
+ wx.pauseVoice({ |
|
333 |
+ localId: voice.localId |
|
334 |
+ }) |
|
335 |
+ } |
|
336 |
+ |
|
337 |
+ // 4.6 停止播放音频 |
|
338 |
+ function stopVoice() { |
|
339 |
+ if (voice.localId == '') { |
|
340 |
+ if (JSWE.wxStopVoiceEmpty) {JSWE.wxStopVoiceEmpty()} |
|
341 |
+ return |
|
342 |
+ } |
|
343 |
+ wx.stopVoice({ |
|
344 |
+ localId: voice.localId |
|
345 |
+ }) |
|
346 |
+ } |
|
347 |
+ |
|
348 |
+ // 4.8 上传语音 |
|
349 |
+ function uploadVoice() { |
|
350 |
+ var localId = voice.localId |
|
351 |
+ if (localId == '') { |
|
352 |
+ if (JSWE.wxUploadVoiceEmpty) {JSWE.wxUploadVoiceEmpty()} |
|
353 |
+ return |
|
354 |
+ } |
|
355 |
+ wx.uploadVoice({ |
|
356 |
+ localId: localId, |
|
357 |
+ success: function (res) { |
|
358 |
+ voice.serverId = res.serverId |
|
359 |
+ if (JSWE.wxUploadVoiceSuccess) {JSWE.wxUploadVoiceSuccess(res, localId)} |
|
360 |
+ } |
|
361 |
+ }) |
|
362 |
+ } |
|
363 |
+ |
|
364 |
+ // 4.9 下载语音 |
|
365 |
+ function downloadVoice() { |
|
366 |
+ var serverId = voice.serverId |
|
367 |
+ if (serverId == '') { |
|
368 |
+ if (JSWE.wxDownloadVoiceEmpty) {JSWE.wxDownloadVoiceEmpty()} |
|
369 |
+ return |
|
370 |
+ } |
|
371 |
+ wx.downloadVoice({ |
|
372 |
+ serverId: serverId, |
|
373 |
+ success: function (res) { |
|
374 |
+ voice.localId = res.localId |
|
375 |
+ if (JSWE.wxDownloadVoiceSuccess) {JSWE.wxDownloadVoiceSuccess(res, serverId)} |
|
376 |
+ } |
|
377 |
+ }) |
|
378 |
+ } |
|
379 |
+ |
|
380 |
+ // 5 图片接口 |
|
381 |
+ var images = { |
|
382 |
+ localIds: [], |
|
383 |
+ serverIds: [] |
|
384 |
+ } |
|
385 |
+ // 5.1 拍照、本地选图 |
|
386 |
+ function chooseImage(choose_params) { |
|
387 |
+ if ('undefined' === typeof choose_params) choose_params = {} |
|
388 |
+ wx.chooseImage({ |
|
389 |
+ count: choose_params.count || 9, // 默认9 |
|
390 |
+ sizeType: choose_params.sizeType || ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有 |
|
391 |
+ sourceType: choose_params.sourceType || ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有 |
|
392 |
+ success: function (res) { |
|
393 |
+ images.localIds = res.localIds // 返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片 |
|
394 |
+ // 判断是否直接上传 |
|
395 |
+ if (choose_params.directUpload) {setTimeout(uploadImages({localIds: images.localIds, isShowProgressTips: choose_params.isShowProgressTips || 1}), 100)} |
|
396 |
+ // 拍照、本地选图成功后的回调函数 |
|
397 |
+ if (JSWE.wxChooseImageSuccess) {JSWE.wxChooseImageSuccess(res, choose_params.extras || {})} |
|
398 |
+ } |
|
399 |
+ }) |
|
400 |
+ } |
|
401 |
+ |
|
402 |
+ // 5.2 图片预览 |
|
403 |
+ function previewImage(preview_params) { |
|
404 |
+ wx.previewImage({ |
|
405 |
+ current: preview_params.current, // 当前显示图片的链接,不填则默认为 urls 的第一张 |
|
406 |
+ urls: preview_params.urls // 需要预览的图片链接列表 |
|
407 |
+ }) |
|
408 |
+ } |
|
409 |
+ |
|
410 |
+ // 5.3 上传图片 |
|
411 |
+ function uploadImage(upload_params) { |
|
412 |
+ // 上传图片为异步处理,重复上传同一图片,返回的serverId也是不同的 |
|
413 |
+ var localId = upload_params.localId |
|
414 |
+ wx.uploadImage({ |
|
415 |
+ localId: localId, // 需要上传的图片的本地ID,由chooseImage接口获得 |
|
416 |
+ isShowProgressTips: upload_params.isShowProgressTips || 1, // 默认为1,显示进度提示 |
|
417 |
+ success: function (res) { |
|
418 |
+ images.serverIds.push(res.serverId) // 返回图片的服务器端ID |
|
419 |
+ // 上传图片成功后的回调函数 |
|
420 |
+ if (JSWE.wxUploadImageSuccess) {JSWE.wxUploadImageSuccess(res, localId)} |
|
421 |
+ } |
|
422 |
+ }) |
|
423 |
+ } |
|
424 |
+ |
|
425 |
+ function uploadImages(upload_params) { |
|
426 |
+ var localIds = upload_params.localIds, isShowProgressTips = upload_params.isShowProgressTips || 1 |
|
427 |
+ images.serverIds = [] |
|
428 |
+ for (var idx in localIds) {uploadImage({localId: localIds[idx], isShowProgressTips: isShowProgressTips})} |
|
429 |
+ } |
|
430 |
+ |
|
431 |
+ // 5.4 下载图片 |
|
432 |
+ function downloadImage(download_params) { |
|
433 |
+ var serverId = download_params.serverId |
|
434 |
+ wx.downloadImage({ |
|
435 |
+ serverId: serverId, // 需要下载的图片的服务器端ID,由uploadImage接口获得 |
|
436 |
+ isShowProgressTips: download_params.isShowProgressTips || 1, // 默认为1,显示进度提示 |
|
437 |
+ success: function (res) { |
|
438 |
+ images.localId.push(res.localId) |
|
439 |
+ if (JSWE.wxDownloadImageSuccess) {JSWE.wxDownloadImageSuccess(res, serverId)} |
|
440 |
+ } |
|
441 |
+ }) |
|
442 |
+ } |
|
443 |
+ |
|
444 |
+ function downloadImages(download_params) { |
|
445 |
+ var serverIds = download_params.serverIds, isShowProgressTips = download_params.isShowProgressTips || 1 |
|
446 |
+ images.localIds = [] |
|
447 |
+ for (var idx in serverIds) {downloadImage({serverId: serverIds[idx], isShowProgressTips: isShowProgressTips})} |
|
448 |
+ } |
|
449 |
+ |
|
450 |
+ function getLocalImgData(localId) { |
|
451 |
+ wx.getLocalImgData({ |
|
452 |
+ localId: localId, // 图片的localID |
|
453 |
+ success: function (res) { |
|
454 |
+ // var localData = res.localData; // localData是图片的base64数据,可以用img标签显示 |
|
455 |
+ if (JSWE.wxGetLocalImgDataSuccess) {JSWE.wxGetLocalImgDataSuccess(res)} |
|
456 |
+ } |
|
457 |
+ }) |
|
458 |
+ } |
|
459 |
+ |
|
460 |
+ // 9 微信原生接口 |
|
461 |
+ // 9.1.1 扫描二维码并返回结果 |
|
462 |
+ // 9.1.2 扫描二维码并返回结果 |
|
463 |
+ function scanQRCode(scan_params) { |
|
464 |
+ if ('undefined' === typeof scan_params) scan_params = {} |
|
465 |
+ wx.scanQRCode({ |
|
466 |
+ needResult: scan_params.needResult || 0, // 默认为0,0扫描结果由微信处理,1直接返回扫描结果 |
|
467 |
+ scanType: scan_params.scanType || ['qrCode', 'barCode'], // 可以指定扫二维码还是一维码,默认二者都有 |
|
468 |
+ success: function (res) { // 当 needResult 为 1 时,扫码返回的结果 |
|
469 |
+ if (JSWE.wxScanQRCodeSuccess) {JSWE.wxScanQRCodeSuccess(res)} |
|
470 |
+ } |
|
471 |
+ }) |
|
472 |
+ } |
|
473 |
+ |
|
474 |
+ // QRCode & BarCode is different |
|
475 |
+ function parseScanQRCodeResultStr(resultStr) { |
|
476 |
+ var strs = resultStr.split(',') |
|
477 |
+ return strs[strs.length - 1] |
|
478 |
+ } |
|
479 |
+ |
|
480 |
+ // 10 微信支付接口 |
|
481 |
+ // 10.1 发起一个支付请求 |
|
482 |
+ function chooseWXPay(wxpay_params) { |
|
483 |
+ wx.chooseWXPay({ |
|
484 |
+ timestamp: wxpay_params.timeStamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符 |
|
485 |
+ nonceStr: wxpay_params.nonceStr, // 支付签名随机串,不长于 32 位 |
|
486 |
+ package: wxpay_params.package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***) |
|
487 |
+ signType: wxpay_params.signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5' |
|
488 |
+ paySign: wxpay_params.paySign, // 支付签名 |
|
489 |
+ success: function (res) { |
|
490 |
+ // 支付成功后的回调函数 |
|
491 |
+ if (JSWE.wxPaySuccess) {JSWE.wxPaySuccess(res)} |
|
492 |
+ } |
|
493 |
+ }) |
|
494 |
+ } |
|
495 |
+ |
|
496 |
+ // xx 微信原生企业红包接口 |
|
497 |
+ // xx.1 发起一个发送原生企业红包请求 |
|
498 |
+ function openEnterpriseRedPacket(wxredpack_params) { |
|
499 |
+ wx.openEnterpriseRedPacket({ |
|
500 |
+ timeStamp: wxredpack_params.timeStamp, // 红包签名时间戳,注意原生企业红包接口timeStamp字段名需大写其中的S字符,而支付接口timeStamp字段名无需大写其中的S字符。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符 |
|
501 |
+ nonceStr: wxredpack_params.nonceStr, // 红包签名随机串,不长于 32 位 |
|
502 |
+ package: encodeURIComponent(wxredpack_params.package), // 发放红包接口返回的prepay_id参数值,提交格式如:prepay_id=***) |
|
503 |
+ signType: wxredpack_params.signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5' |
|
504 |
+ paySign: wxredpack_params.paySign, // 红包签名 |
|
505 |
+ success: function (res) { |
|
506 |
+ // 发送原生企业红包成功后的回调函数 |
|
507 |
+ if (JSWE.wxEnterpriseRedPacketSuccess) {JSWE.wxEnterpriseRedPacketSuccess(res)} |
|
508 |
+ } |
|
509 |
+ }) |
|
510 |
+ } |
|
511 |
+ |
|
512 |
+ var v = { |
|
513 |
+ version: '1.0.5', |
|
514 |
+ |
|
515 |
+ // Basic Vars |
|
516 |
+ config: config, |
|
517 |
+ wxData: wxData, |
|
518 |
+ jsApiList: jsApiList, |
|
519 |
+ |
|
520 |
+ isEmpty: isEmpty, |
|
521 |
+ isNotEmpty: isNotEmpty, |
|
522 |
+ |
|
523 |
+ // Weixin Function |
|
524 |
+ isOpenInWeixin: isOpenInWeixin, |
|
525 |
+ getWeixinVersion: getWeixinVersion, |
|
526 |
+ isWeixinVersion: isWeixinVersion, |
|
527 |
+ |
|
528 |
+ // Menu Function |
|
529 |
+ hideOptionMenu: hideOptionMenu, |
|
530 |
+ showOptionMenu: showOptionMenu, |
|
531 |
+ hideMenuItems: hideMenuItems, |
|
532 |
+ showMenuItems: showMenuItems, |
|
533 |
+ hideAllNonBaseMenuItem: hideAllNonBaseMenuItem, |
|
534 |
+ showAllNonBaseMenuItem: showAllNonBaseMenuItem, |
|
535 |
+ closeWindow: closeWindow, |
|
536 |
+ |
|
537 |
+ // Share Function |
|
538 |
+ initWxData: initWxData, |
|
539 |
+ changeWxData: changeWxData, |
|
540 |
+ fixedWxData: fixedWxData, |
|
541 |
+ |
|
542 |
+ // Voice Function |
|
543 |
+ voice: voice, |
|
544 |
+ translateVoice: translateVoice, |
|
545 |
+ startRecord: startRecord, |
|
546 |
+ stopRecord: stopRecord, |
|
547 |
+ playVoice: playVoice, |
|
548 |
+ pauseVoice: pauseVoice, |
|
549 |
+ stopVoice: stopVoice, |
|
550 |
+ uploadVoice: uploadVoice, |
|
551 |
+ downloadVoice: downloadVoice, |
|
552 |
+ |
|
553 |
+ // Image Function |
|
554 |
+ images: images, |
|
555 |
+ chooseImage: chooseImage, |
|
556 |
+ previewImage: previewImage, |
|
557 |
+ uploadImage: uploadImage, |
|
558 |
+ uploadImages: uploadImages, |
|
559 |
+ downloadImage: downloadImage, |
|
560 |
+ downloadImages: downloadImages, |
|
561 |
+ getLocalImgData: getLocalImgData, |
|
562 |
+ |
|
563 |
+ // Scan Function |
|
564 |
+ scanQRCode: scanQRCode, |
|
565 |
+ parseScanQRCodeResultStr: parseScanQRCodeResultStr, |
|
566 |
+ |
|
567 |
+ // Pay Function |
|
568 |
+ chooseWXPay: chooseWXPay, |
|
569 |
+ |
|
570 |
+ // EnterpriseRedPacket Function |
|
571 |
+ openEnterpriseRedPacket: openEnterpriseRedPacket |
|
572 |
+ } |
|
573 |
+ e.JSWE = e.V = v |
|
574 |
+})(window) |
@@ -0,0 +1,52 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+ |
|
3 |
+"""jdjos URL Configuration |
|
4 |
+ |
|
5 |
+The `urlpatterns` list routes URLs to views. For more information please see: |
|
6 |
+ https://docs.djangoproject.com/en/1.11/topics/http/urls/ |
|
7 |
+Examples: |
|
8 |
+Function views |
|
9 |
+ 1. Add an import: from my_app import views |
|
10 |
+ 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home') |
|
11 |
+Class-based views |
|
12 |
+ 1. Add an import: from other_app.views import Home |
|
13 |
+ 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home') |
|
14 |
+Including another URLconf |
|
15 |
+ 1. Import the include() function: from django.conf.urls import url, include |
|
16 |
+ 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) |
|
17 |
+""" |
|
18 |
+from django.conf import settings |
|
19 |
+from django.conf.urls import include, url |
|
20 |
+from django.conf.urls.static import static |
|
21 |
+from django.contrib import admin |
|
22 |
+ |
|
23 |
+ |
|
24 |
+urlpatterns = [ |
|
25 |
+ url(r'^admin/', admin.site.urls), |
|
26 |
+] |
|
27 |
+ |
|
28 |
+urlpatterns += [ |
|
29 |
+ url(r'^api/', include('api.urls', namespace='api')), |
|
30 |
+ url(r'^uniapi/', include('django_uniapi.urls', namespace='uniapi')), |
|
31 |
+] |
|
32 |
+ |
|
33 |
+urlpatterns += [ |
|
34 |
+ # url(r'^s/', include('django_short_url.urls', namespace='django_short_url')), |
|
35 |
+] |
|
36 |
+ |
|
37 |
+urlpatterns += [ |
|
38 |
+ url(r'^w/', include('django_we.urls', namespace='shortwechat')), |
|
39 |
+ url(r'^we/', include('django_we.urls', namespace='wechat')), |
|
40 |
+] |
|
41 |
+ |
|
42 |
+urlpatterns += [ |
|
43 |
+ # url(r'^p/', include('page.urls', namespace='shortpage')), |
|
44 |
+ # url(r'^page/', include('page.urls', namespace='page')), |
|
45 |
+] |
|
46 |
+ |
|
47 |
+urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) |
|
48 |
+urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) |
|
49 |
+ |
|
50 |
+# AdminSite |
|
51 |
+admin.site.site_title = '' |
|
52 |
+admin.site.site_header = 'My administration' |
@@ -0,0 +1,17 @@ |
||
1 |
+""" |
|
2 |
+WSGI config for jdjos project. |
|
3 |
+ |
|
4 |
+It exposes the WSGI callable as a module-level variable named ``application``. |
|
5 |
+ |
|
6 |
+For more information on this file, see |
|
7 |
+https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/ |
|
8 |
+""" |
|
9 |
+ |
|
10 |
+import os |
|
11 |
+ |
|
12 |
+from django.core.wsgi import get_wsgi_application |
|
13 |
+ |
|
14 |
+ |
|
15 |
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "jdjos.settings") |
|
16 |
+ |
|
17 |
+application = get_wsgi_application() |
@@ -0,0 +1,23 @@ |
||
1 |
+#!/usr/bin/env python |
|
2 |
+import os |
|
3 |
+import sys |
|
4 |
+ |
|
5 |
+ |
|
6 |
+if __name__ == "__main__": |
|
7 |
+ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "jdjos.settings") |
|
8 |
+ try: |
|
9 |
+ from django.core.management import execute_from_command_line |
|
10 |
+ except ImportError: |
|
11 |
+ # The above import may fail for some other reason. Ensure that the |
|
12 |
+ # issue is really that Django is missing to avoid masking other |
|
13 |
+ # exceptions on Python 2. |
|
14 |
+ try: |
|
15 |
+ import django |
|
16 |
+ except ImportError: |
|
17 |
+ raise ImportError( |
|
18 |
+ "Couldn't import Django. Are you sure it's installed and " |
|
19 |
+ "available on your PYTHONPATH environment variable? Did you " |
|
20 |
+ "forget to activate a virtual environment?" |
|
21 |
+ ) |
|
22 |
+ raise |
|
23 |
+ execute_from_command_line(sys.argv) |
@@ -0,0 +1,10 @@ |
||
1 |
+#!/bin/bash |
|
2 |
+ |
|
3 |
+# Ignoring autogenerated files |
|
4 |
+# -- Migration directories |
|
5 |
+# Ignoring error codes |
|
6 |
+# -- E128 continuation line under-indented for visual indent |
|
7 |
+# -- E402 module level import not at top of file |
|
8 |
+# -- E501 line too long |
|
9 |
+ |
|
10 |
+pycodestyle --exclude=build,migrations,.tox --ignore=E128,E402,E501 . |
@@ -0,0 +1,7 @@ |
||
1 |
+StatusCode==1.0.0 |
|
2 |
+furl==2.0.0 |
|
3 |
+jsonfield==2.0.2 |
|
4 |
+mysqlclient==1.3.13 |
|
5 |
+-r requirements_dj.txt |
|
6 |
+-r requirements_pywe.txt |
|
7 |
+-r requirements_redis.txt |
@@ -0,0 +1,3 @@ |
||
1 |
+ipdb==0.11 |
|
2 |
+ipython==5.6.0 |
|
3 |
+uwsgi==2.0.17 |
@@ -0,0 +1,2 @@ |
||
1 |
+isort==4.3.9 |
|
2 |
+pycodestyle==2.4.0 |
@@ -0,0 +1,15 @@ |
||
1 |
+Django==1.11.16 |
|
2 |
+django-admin==1.3.2 |
|
3 |
+django-detect==1.0.8 |
|
4 |
+django-file==1.0.3 |
|
5 |
+django-json-render==1.0.2 |
|
6 |
+django-json-response==1.1.5 |
|
7 |
+django-logit==1.1.3 |
|
8 |
+django-models-ext==1.1.8 |
|
9 |
+django-redis-connector==1.0.1 |
|
10 |
+django-response==1.1.1 |
|
11 |
+django-rlog==1.0.7 |
|
12 |
+django-short-url==1.1.3 |
|
13 |
+django-six==1.0.4 |
|
14 |
+django-uniapi==1.0.5 |
|
15 |
+django-we==1.4.2 |
@@ -0,0 +1,2 @@ |
||
1 |
+pywe-oauth==1.0.7 |
|
2 |
+pywe-pay==1.0.12 |
@@ -0,0 +1,3 @@ |
||
1 |
+hiredis==1.0.0 |
|
2 |
+redis==2.10.6 |
|
3 |
+redis-extensions==1.2.5 |
@@ -0,0 +1,4 @@ |
||
1 |
+#!/bin/bash |
|
2 |
+ |
|
3 |
+sudo sysctl -w net.core.somaxconn=4096 |
|
4 |
+sudo sysctl -w net.core.netdev_max_backlog=50000 |
@@ -0,0 +1,77 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+ |
|
3 |
+from StatusCode import BaseStatusCode, StatusCodeField |
|
4 |
+ |
|
5 |
+ |
|
6 |
+class ParamStatusCode(BaseStatusCode): |
|
7 |
+ """ 4000xx 参数相关错误码 """ |
|
8 |
+ PARAM_NOT_FOUND = StatusCodeField(400000, 'Param Not Found', description=u'参数不存在') |
|
9 |
+ |
|
10 |
+ |
|
11 |
+class ProfileStatusCode(BaseStatusCode): |
|
12 |
+ """ 4001xx 用户相关错误码 """ |
|
13 |
+ PROFILE_NOT_FOUND = StatusCodeField(400101, 'Profile Not Found', description=u'用户不存在') |
|
14 |
+ |
|
15 |
+ |
|
16 |
+class PhoneStatusCode(BaseStatusCode): |
|
17 |
+ """ 4002xx 手机相关错误码 """ |
|
18 |
+ INVALID_PHONE = StatusCodeField(400200, 'Invalid Phone', description=u'非法手机号') |
|
19 |
+ PHONE_NOT_FOUND = StatusCodeField(400201, 'Phone Not Found', description=u'手机号不存在') |
|
20 |
+ PHONE_ALREADY_EXISTS = StatusCodeField(400202, 'Phone Already Exists', description=u'手机号已存在') |
|
21 |
+ |
|
22 |
+ |
|
23 |
+class OrderStatusCode(BaseStatusCode): |
|
24 |
+ """ 4040xx 订单/支付相关错误码 """ |
|
25 |
+ UNIFIED_ORDER_FAIL = StatusCodeField(404000, 'Unified Order Fail', description=u'统一下单失败') |
|
26 |
+ ORDER_NOT_FOUND = StatusCodeField(404001, 'Order Not Found', description=u'订单不存在') |
|
27 |
+ # 订单支付状态 |
|
28 |
+ ORDER_NOT_PAY = StatusCodeField(404011, 'Order Not Pay', description=u'订单未支付') |
|
29 |
+ ORDER_PAYING = StatusCodeField(404012, 'Order Paying', description=u'订单支付中') |
|
30 |
+ ORDER_PAY_FAIL = StatusCodeField(404013, 'Order Pay Fail', description=u'微信支付失败') |
|
31 |
+ # 通知校验状态 |
|
32 |
+ SIGN_CHECK_FAIL = StatusCodeField(404090, 'Sign Check Fail', description=u'签名校验失败') |
|
33 |
+ FEE_CHECK_FAIL = StatusCodeField(404091, 'FEE Check Fail', description=u'金额校验失败') |
|
34 |
+ |
|
35 |
+ |
|
36 |
+class PayStatusCode(BaseStatusCode): |
|
37 |
+ """ 4041xx 支付相关错误码 """ |
|
38 |
+ |
|
39 |
+ |
|
40 |
+class WithdrawStatusCode(BaseStatusCode): |
|
41 |
+ """ 4042xx 提现相关错误码 """ |
|
42 |
+ BALANCE_INSUFFICIENT = StatusCodeField(404200, 'Balance Insufficient', description=u'提现金额不足') |
|
43 |
+ |
|
44 |
+ |
|
45 |
+class TokenStatusCode(BaseStatusCode): |
|
46 |
+ """ 4090xx 票据相关错误码 """ |
|
47 |
+ TOKEN_NOT_FOUND = StatusCodeField(409001, 'Token Not Found', description=u'票据不存在') |
|
48 |
+ |
|
49 |
+ |
|
50 |
+class SignatureStatusCode(BaseStatusCode): |
|
51 |
+ """ 4091xx 签名校验错误 """ |
|
52 |
+ SIGNATURE_ERROR = StatusCodeField(409101, 'Signature Error', description=u'签名错误') |
|
53 |
+ |
|
54 |
+ |
|
55 |
+class GVCodeStatusCode(BaseStatusCode): |
|
56 |
+ """ 4092xx 图形验证码相关错误码 """ |
|
57 |
+ GRAPHIC_VCODE_ERROR = StatusCodeField(409201, 'Graphic VCode Error', description=u'图形验证码错误') |
|
58 |
+ |
|
59 |
+ |
|
60 |
+class SVCodeStatusCode(BaseStatusCode): |
|
61 |
+ """ 4093xx 短信验证码相关错误码 """ |
|
62 |
+ SMS_QUOTA_LIMIT = StatusCodeField(409300, 'SMS Quota Limit', description=u'短信次数超限') |
|
63 |
+ SMS_VCODE_ERROR = StatusCodeField(409301, 'SMS VCode Error', description=u'验证码错误,请稍后重试') |
|
64 |
+ SMS_VCODE_HAS_SEND = StatusCodeField(409302, 'SMS VCode Has Send', description=u'验证码已发送,请勿重复获取') |
|
65 |
+ |
|
66 |
+ |
|
67 |
+class InsufficientStatusCode(BaseStatusCode): |
|
68 |
+ """ 4095xx 不足相关错误码 """ |
|
69 |
+ BALANCE_INSUFFICIENT = StatusCodeField(409501, 'Balance Insufficient', description=u'余额不足') |
|
70 |
+ INTEGRAL_INSUFFICIENT = StatusCodeField(409502, 'Integral Insufficient', description=u'积分不足') |
|
71 |
+ |
|
72 |
+ |
|
73 |
+class PermissionStatusCode(BaseStatusCode): |
|
74 |
+ """ 4099xx 权限相关错误码 """ |
|
75 |
+ PERMISSION_DENIED = StatusCodeField(409900, 'Permission Denied', description=u'权限不足') |
|
76 |
+ UPLOAD_PERMISSION_DENIED = StatusCodeField(409910, 'Upload Permission Denied', description=u'上传权限不足') |
|
77 |
+ UPDATE_PERMISSION_DENIED = StatusCodeField(409930, 'Update Permission Denied', description=u'更新权限不足') |
@@ -0,0 +1,24 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+ |
|
3 |
+from json_response import JsonpResponse, JsonResponse |
|
4 |
+from StatusCode import StatusCodeField |
|
5 |
+ |
|
6 |
+ |
|
7 |
+def response_data(status_code=200, message=None, description=None, data={}, **kwargs): |
|
8 |
+ return dict({ |
|
9 |
+ 'status': status_code, |
|
10 |
+ 'message': message, |
|
11 |
+ 'description': description, |
|
12 |
+ 'data': data, |
|
13 |
+ }, **kwargs) |
|
14 |
+ |
|
15 |
+ |
|
16 |
+def response(status_code=200, message=None, description=None, data={}, msg_args=[], msg_kwargs={}, desc_args=[], desc_kwargs={}, request=None, callback=None, **kwargs): |
|
17 |
+ # Final Message and Description |
|
18 |
+ message, description = (message or status_code.message, description or status_code.description) if isinstance(status_code, StatusCodeField) else (message, description) |
|
19 |
+ # Final Response Data |
|
20 |
+ resp_data = response_data(status_code, (message or '').format(*msg_args, **msg_kwargs), (description or '').format(*desc_args, **desc_kwargs), data, **kwargs) |
|
21 |
+ # Assign Callback |
|
22 |
+ callback = callback or (request and request.GET.get('callback')) |
|
23 |
+ # Call JsonResponse or JsonpResponse |
|
24 |
+ return JsonpResponse(callback, resp_data, safe=False) if callback else JsonResponse(resp_data, safe=False) |
@@ -0,0 +1,6 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+ |
|
3 |
+from django.conf import settings |
|
4 |
+ |
|
5 |
+ |
|
6 |
+r = settings.REDIS_CACHE |
@@ -0,0 +1 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
@@ -0,0 +1,18 @@ |
||
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+ |
|
3 |
+ |
|
4 |
+def userinfo_save(userinfo): |
|
5 |
+ """ Save profile or something else """ |
|
6 |
+ # from account.models import UserInfo |
|
7 |
+ # from django.conf import settings |
|
8 |
+ # |
|
9 |
+ # unique_identifier = userinfo.get(settings.WECHAT_UNIQUE_IDENTIFICATION, '') |
|
10 |
+ # |
|
11 |
+ # user, created = UserInfo.objects.select_for_update().get_or_create(**{settings.WECHAT_UNIQUE_IDENTIFICATION: unique_identifier}) |
|
12 |
+ # user.unionid = userinfo.get('unionid', '') |
|
13 |
+ # user.openid = userinfo.get('openid', '') |
|
14 |
+ # user.nickname = userinfo.get('nickname', '') |
|
15 |
+ # user.avatar = userinfo.get('headimgurl', '') |
|
16 |
+ # user.save() |
|
17 |
+ # |
|
18 |
+ # return user |