tlog 增加errors

This commit is contained in:
曹前明 2022-07-26 12:21:53 +08:00
parent 28f2daca2b
commit d8b2ac28a3
24 changed files with 428 additions and 95 deletions

View File

@ -1,5 +1,5 @@
from __future__ import absolute_import, unicode_literals from __future__ import absolute_import, unicode_literals
from apps.utils.task import CustomTask from apps.utils.tasks import CustomTask
from apps.am.models import Area from apps.am.models import Area
from celery import shared_task from celery import shared_task
from django.core.cache import cache from django.core.cache import cache

View File

@ -13,3 +13,7 @@ class SendCodeSerializer(serializers.Serializer):
class CodeLoginSerializer(serializers.Serializer): class CodeLoginSerializer(serializers.Serializer):
phone = serializers.CharField(label="手机号") phone = serializers.CharField(label="手机号")
code = serializers.CharField(label="验证码") code = serializers.CharField(label="验证码")
class WxCodeSerializer(serializers.Serializer):
code = serializers.CharField(label="code")

View File

@ -15,9 +15,11 @@ from rest_framework_simplejwt.tokens import RefreshToken
from django.core.cache import cache from django.core.cache import cache
from apps.utils.sms import send_sms from apps.utils.sms import send_sms
from apps.utils.tools import rannum from apps.utils.tools import rannum
from apps.utils.wxmp import wxmpClient
from apps.utils.wx import wxClient
from apps.auth1.serializers import LoginSerializer, SendCodeSerializer from apps.auth1.serializers import CodeLoginSerializer, LoginSerializer, SendCodeSerializer, WxCodeSerializer
from apps.system.models import User from apps.system.models import User
from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet from apps.utils.viewsets import CustomGenericViewSet, CustomModelViewSet
@ -90,12 +92,11 @@ class WxmpLogin(CreateAPIView):
""" """
authentication_classes = [] authentication_classes = []
permission_classes = [] permission_classes = []
serializer_class = WxCodeSerializer
def post(self, request): def post(self, request):
code = request.data['code'] code = request.data['code']
info = requests.get('https://api.weixin.qq.com/sns/jscode2session?appid='+settings.WXMP_APPID+'&secret='+settings.WXMP_APPSECRET+'&js_code=' + info = wxmpClient.get_basic_info(code=code)
code+'&grant_type=authorization_code').content.decode('utf-8')
info = json.loads(info)
openid = info['openid'] openid = info['openid']
session_key = info['session_key'] session_key = info['session_key']
try: try:
@ -116,23 +117,22 @@ class WxLogin(CreateAPIView):
""" """
authentication_classes = [] authentication_classes = []
permission_classes = [] permission_classes = []
serializer_class = WxCodeSerializer
def post(self, request): def post(self, request):
code = request.data['code'] code = request.data['code']
info = requests.get('https://api.weixin.qq.com/sns/jscode2session?appid='+settings.WXMP_APPID+'&secret='+settings.WXMP_APPSECRET+'&js_code=' + info = wxClient.get_basic_info(code=code)
code+'&grant_type=authorization_code').content.decode('utf-8')
info = json.loads(info)
openid = info['openid'] openid = info['openid']
session_key = info['session_key'] access = info['access_token']
try: try:
user = User.objects.get(wx_openid=openid, is_active=True) user = User.objects.get(wx_openid=openid, is_active=True)
ret = get_tokens_for_user(user) ret = get_tokens_for_user(user)
ret['wx_session_key'] = session_key ret['wx_token'] = access
ret['wx_openid'] = openid ret['wx_openid'] = openid
cache.set(code, ret, 60*5) cache.set(code, ret, 60*5)
return Response(ret) return Response(ret)
except Exception: except Exception:
return Response({'wx_openid': openid, 'wx_session_key': session_key}, status=400) return Response({'wx_openid': openid, 'wx_token': access}, status=400)
class GetTokenFromCache(CreateAPIView): class GetTokenFromCache(CreateAPIView):
@ -142,6 +142,7 @@ class GetTokenFromCache(CreateAPIView):
""" """
authentication_classes = [] authentication_classes = []
permission_classes = [] permission_classes = []
serializer_class = WxCodeSerializer
def post(self, request): def post(self, request):
code = request.data['code'] code = request.data['code']
@ -175,6 +176,7 @@ class CodeLogin(CreateAPIView):
""" """
authentication_classes = [] authentication_classes = []
permission_classes = [] permission_classes = []
serializer_class = CodeLoginSerializer
def post(self, request): def post(self, request):
phone = request.data['phone'] phone = request.data['phone']

View File

@ -0,0 +1,16 @@
from rest_framework import serializers
class SendSmsSerializer(serializers.Serializer):
phone = serializers.CharField(label='手机号')
template_code = serializers.CharField(label='模板标识')
template_param = serializers.JSONField(label='模板参数')
class GenerateVoiceSerializer(serializers.Serializer):
msg = serializers.CharField(label='文本')
class TestTaskSerializer(serializers.Serializer):
args = serializers.ListField(child=serializers.CharField(), label='列表参数', required=False, allow_null=True)
kwargs = serializers.JSONField(label="字典参数", required=False, allow_null=True)

View File

@ -1,7 +1,12 @@
from __future__ import absolute_import, unicode_literals from __future__ import absolute_import, unicode_literals
from celery import shared_task from celery import shared_task
import subprocess import subprocess
from apps.utils.tasks import CustomTask
from server.settings import DATABASES, BACKUP_PATH, SH_PATH, SD_PWD from server.settings import DATABASES, BACKUP_PATH, SH_PATH, SD_PWD
import requests
import json
from django.conf import settings
from django.core.cache import cache
@shared_task @shared_task
@ -37,6 +42,7 @@ def reload_web_git():
if completed.returncode != 0: if completed.returncode != 0:
return completed.stderr return completed.stderr
@shared_task @shared_task
def reload_server_only(): def reload_server_only():
command = 'echo "{}" | sudo -S supervisorctl reload'.format(SD_PWD) command = 'echo "{}" | sudo -S supervisorctl reload'.format(SD_PWD)
@ -49,3 +55,12 @@ def backup_media():
command = 'bash {}/backup_media.sh'.format(SH_PATH) command = 'bash {}/backup_media.sh'.format(SH_PATH)
completed = subprocess.run(command, shell=True, capture_output=True, text=True) completed = subprocess.run(command, shell=True, capture_output=True, text=True)
return completed return completed
@shared_task(base=CustomTask)
def get_wx_token():
r = requests.get('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}'.format(
settings.WX_APPID, settings.WX_APPSECRET)).text
token = json.loads(r)['access_token']
cache.set('wx_token', token)
return token

View File

@ -1,13 +1,17 @@
from django.urls import path from django.urls import path, include
from apps.develop.views import BackupDatabase, BackupMedia, ReloadClientGit, ReloadServerGit, ReloadServerOnly from apps.develop.views import BackupDatabase, BackupMedia, ReloadClientGit, ReloadServerGit, ReloadServerOnly, TestViewSet
from rest_framework.routers import DefaultRouter
API_BASE_URL = 'api/develop/' API_BASE_URL = 'api/develop/'
HTML_BASE_URL = 'develop/' HTML_BASE_URL = 'develop/'
router = DefaultRouter()
router.register('test', TestViewSet, basename='api_test')
urlpatterns = [ urlpatterns = [
path(API_BASE_URL + 'reload_server_git/', ReloadServerGit.as_view()), path(API_BASE_URL + 'reload_server_git/', ReloadServerGit.as_view()),
path(API_BASE_URL + 'reload_web_git/', ReloadClientGit.as_view()), path(API_BASE_URL + 'reload_web_git/', ReloadClientGit.as_view()),
path(API_BASE_URL + 'reload_server_only/', ReloadServerOnly.as_view()), path(API_BASE_URL + 'reload_server_only/', ReloadServerOnly.as_view()),
path(API_BASE_URL + 'backup_database/', BackupDatabase.as_view()), path(API_BASE_URL + 'backup_database/', BackupDatabase.as_view()),
path(API_BASE_URL + 'backup_media/', BackupMedia.as_view()) path(API_BASE_URL + 'backup_media/', BackupMedia.as_view()),
path(API_BASE_URL, include(router.urls)),
] ]

View File

@ -1,8 +1,20 @@
import json
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework.permissions import IsAdminUser from rest_framework.permissions import IsAdminUser
from rest_framework.response import Response from rest_framework.response import Response
from apps.develop.tasks import backup_database, backup_media, reload_web_git, reload_server_git, reload_server_only from rest_framework.serializers import Serializer
from rest_framework.decorators import action
from apps.develop.serializers import GenerateVoiceSerializer, SendSmsSerializer, TestTaskSerializer
from apps.develop.tasks import backup_database, backup_media, get_wx_token, reload_web_git, reload_server_git, reload_server_only
from rest_framework.exceptions import APIException, ParseError from rest_framework.exceptions import APIException, ParseError
from apps.system.models import User
from apps.system.tasks import show
from apps.utils.sms import send_sms
from apps.utils.speech import generate_voice
from django.core.cache import cache
import requests
from apps.utils.viewsets import CustomGenericViewSet
# Create your views here. # Create your views here.
@ -91,3 +103,74 @@ class BackupMedia(APIView):
return Response() return Response()
else: else:
raise APIException(completed.stdout) raise APIException(completed.stdout)
class TestViewSet(CustomGenericViewSet):
authentication_classes = ()
permission_classes = ()
@action(methods=['post'], detail=False, serializer_class=SendSmsSerializer)
def send_sms(self, request, pk=None):
"""发送短信测试
发送短信测试
"""
serializer = SendSmsSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
vdata = serializer.validated_data
res = send_sms(**vdata)
return Response(res)
@action(methods=['post'], detail=False, serializer_class=GenerateVoiceSerializer)
def generate_voice(self, request, pk=None):
"""文字转语音测试
文字转语音测试
"""
serializer = GenerateVoiceSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
vdata = serializer.validated_data
res = generate_voice(**vdata)
return Response(res)
@action(methods=['post'], detail=False, serializer_class=TestTaskSerializer)
def task(self, request, pk=None):
"""任务派发测试
任务派发测试
"""
serializer = TestTaskSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
vdata = serializer.validated_data
ret = {}
task = show.delay(*vdata.get('args', []), **vdata.get('kwargs', {}))
ret['task_id'] = task.task_id
return Response(ret)
@action(methods=['post'], detail=False, serializer_class=Serializer)
def send_wx_msg(self, request, pk=None):
"""微信模板消息发送测试
微信模板消息发送测试
"""
wx_token = cache.get('wx_token', None)
if not wx_token:
wx_token = get_wx_token()
data = {
"touser": 'ocAnm5vab6QGOnf2dqpuUZGJ0xyw',
"template_id": "wczl-hB_bs8CpxwO8_KZuogSTPFXqhBxf8C5HjKl2M4",
"url": "http://weixin.qq.com/download",
# "miniprogram":{
# "appid":"xiaochengxuappid12345",
# "pagepath":"index?foo=bar"
# },
"client_msg_id": "MSG_000001",
"data": {
"first": {
"value": "恭喜你购买成功!",
"color": "#173177"
},
}
}
requests.post(url='https://api.weixin.qq.com/cgi-bin/message/template/send?access_token='+wx_token, json=data)
return Response({'wx_token': wx_token, 'wx_openid': 'ocAnm5vab6QGOnf2dqpuUZGJ0xyw'})

View File

@ -49,4 +49,6 @@ def check_event_timeout():
cate = i.cates.all().order_by('priority', 'create_time').first() cate = i.cates.all().order_by('priority', 'create_time').first()
if cate.hanle_minute > 0 and (timezone.now()-i.create_time).seconds > cate.hanle_minute * 60: if cate.hanle_minute > 0 and (timezone.now()-i.create_time).seconds > cate.hanle_minute * 60:
i.is_timeout = True i.is_timeout = True
i.save() i.save()

View File

@ -1,7 +1,7 @@
# Create your tasks here # Create your tasks here
from __future__ import absolute_import, unicode_literals from __future__ import absolute_import, unicode_literals
from apps.opm.models import Operation, Opl from apps.opm.models import Operation, Opl
from apps.utils.task import CustomTask from apps.utils.tasks import CustomTask
from celery import shared_task from celery import shared_task
from apps.wf.models import State, Ticket from apps.wf.models import State, Ticket

View File

@ -2,5 +2,5 @@
from __future__ import absolute_import, unicode_literals from __future__ import absolute_import, unicode_literals
from apps.hrm.models import Certificate, Employee from apps.hrm.models import Certificate, Employee
from apps.rpm.models import Rcertificate, Remployee, Rpj, Rpjcertificate, Rpjmember from apps.rpm.models import Rcertificate, Remployee, Rpj, Rpjcertificate, Rpjmember
from apps.utils.task import CustomTask from apps.utils.tasks import CustomTask
from celery import shared_task from celery import shared_task

View File

@ -1,7 +1,7 @@
# Create your tasks here # Create your tasks here
from __future__ import absolute_import, unicode_literals from __future__ import absolute_import, unicode_literals
from random import random, randint from random import random, randint
from apps.utils.task import CustomTask from apps.utils.tasks import CustomTask
from celery import shared_task from celery import shared_task
from django.core.mail import send_mail from django.core.mail import send_mail

View File

@ -476,11 +476,12 @@ class UserViewSet(CustomModelViewSet):
绑定微信小程序 绑定微信小程序
""" """
openid = request.data['openid'] openid = request.data['openid']
user = request.user if openid:
if user.wxmp_openid != openid: user = request.user
User.objects.filter(wxmp_openid=openid).update(wxmp_openid=None) if user.wxmp_openid != openid:
user.wxmp_openid = openid User.objects.filter(wxmp_openid=openid).update(wxmp_openid=None)
user.save() user.wxmp_openid = openid
user.save()
return Response({'wxmp_openid': openid}) return Response({'wxmp_openid': openid})
@action(methods=['post'], detail=False, permission_classes=[IsAuthenticated]) @action(methods=['post'], detail=False, permission_classes=[IsAuthenticated])
@ -502,11 +503,12 @@ class UserViewSet(CustomModelViewSet):
绑定微信公众号, 用于发送通知 绑定微信公众号, 用于发送通知
""" """
openid = request.data['openid'] openid = request.data['openid']
user = request.user if openid:
if user.wx_openid != openid: user = request.user
User.objects.filter(wx_openid=openid).update(wx_openid=None) if user.wx_openid != openid:
user.wx_openid = openid User.objects.filter(wx_openid=openid).update(wx_openid=None)
user.save() user.wx_openid = openid
user.save()
return Response({'wx_openid': openid}) return Response({'wx_openid': openid})

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.12 on 2022-07-26 04:20
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('third', '0008_auto_20220713_1408'),
]
operations = [
migrations.AddField(
model_name='tlog',
name='errors',
field=models.TextField(blank=True, null=True),
),
]

View File

@ -76,5 +76,6 @@ class Tlog(BaseModel):
response = models.JSONField(null=True, blank=True) response = models.JSONField(null=True, blank=True)
method = models.CharField(max_length=10) method = models.CharField(max_length=10)
url = models.TextField(null=True, blank=True) url = models.TextField(null=True, blank=True)
errors = models.TextField(null=True, blank=True)
params = models.JSONField(null=True, blank=True) params = models.JSONField(null=True, blank=True)
body = models.JSONField(null=True, blank=True) body = models.JSONField(null=True, blank=True)

View File

@ -1,2 +1,3 @@
SIGN_MAKE_FAIL = {"code": "sign_make_fail", "detail": "签名照生成失败,请重新上传"} SIGN_MAKE_FAIL = {"code": "sign_make_fail", "detail": "签名照生成失败,请重新上传"}
PKS_ERROR = {"code": "pks_error", "detail": "未获取到主键列表"} PKS_ERROR = {"code": "pks_error", "detail": "未获取到主键列表"}
WX_REQUEST_ERROR = {"code": "wx_request_error", "detail": "微信接口访问异常"}

View File

@ -39,18 +39,3 @@ class CustomModelSerializer(DynamicFieldsMixin, serializers.ModelSerializer):
if hasattr(instance, 'update_by'): if hasattr(instance, 'update_by'):
validated_data['update_by'] = getattr(self.request, 'user', None) validated_data['update_by'] = getattr(self.request, 'user', None)
return super().update(instance, validated_data) return super().update(instance, validated_data)
class SendSmsSerializer(serializers.Serializer):
phone = serializers.CharField(label='手机号')
template_code = serializers.CharField(label='模板标识')
template_param = serializers.JSONField(label='模板参数')
class GenerateVoiceSerializer(serializers.Serializer):
msg = serializers.CharField(label='文本')
class TestTaskSerializer(serializers.Serializer):
args = serializers.ListField(child=serializers.CharField(), label='列表参数', required=False, allow_null=True)
kwargs = serializers.JSONField(label="字典参数", required=False, allow_null=True)

View File

@ -1,3 +1,4 @@
# from __future__ import absolute_import, unicode_literals
from celery import Task from celery import Task
import logging import logging

View File

@ -1,11 +1,10 @@
from django.urls import path, include from django.urls import path, include
from rest_framework import routers from rest_framework import routers
from apps.utils.views import SignatureViewSet, TestViewSet from apps.utils.views import SignatureViewSet
API_BASE_URL = 'api/utils/' API_BASE_URL = 'api/utils/'
router = routers.DefaultRouter() router = routers.DefaultRouter()
router.register('signature', SignatureViewSet, basename='signature') router.register('signature', SignatureViewSet, basename='signature')
router.register('test', TestViewSet, basename='util_test')
urlpatterns = [ urlpatterns = [
path(API_BASE_URL, include(router.urls)), path(API_BASE_URL, include(router.urls)),

View File

@ -4,18 +4,19 @@ import cv2
from django.http import HttpResponse from django.http import HttpResponse
from apps.system.tasks import show from apps.system.tasks import show
from apps.utils.errors import SIGN_MAKE_FAIL from apps.utils.errors import SIGN_MAKE_FAIL
from apps.utils.sms import send_sms
from apps.utils.speech import generate_voice
from server.settings import BASE_DIR from server.settings import BASE_DIR
import numpy as np import numpy as np
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.exceptions import ParseError from rest_framework.exceptions import ParseError
from apps.utils.viewsets import CustomGenericViewSet from apps.utils.viewsets import CustomGenericViewSet
from apps.utils.mixins import CustomCreateModelMixin from apps.utils.mixins import CustomCreateModelMixin
from apps.utils.serializers import GenSignatureSerializer, GenerateVoiceSerializer, SendSmsSerializer, TestTaskSerializer from apps.utils.serializers import GenSignatureSerializer
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.serializers import Serializer from rest_framework.serializers import Serializer
from django.core.cache import cache
import json
import requests
class SignatureViewSet(CustomCreateModelMixin, CustomGenericViewSet): class SignatureViewSet(CustomCreateModelMixin, CustomGenericViewSet):
@ -54,47 +55,4 @@ class SignatureViewSet(CustomCreateModelMixin, CustomGenericViewSet):
cv2.imwrite(new_path, image) cv2.imwrite(new_path, image)
return Response({'path': new_path.replace(BASE_DIR, '')}) return Response({'path': new_path.replace(BASE_DIR, '')})
except Exception: except Exception:
raise ParseError(**SIGN_MAKE_FAIL) raise ParseError(**SIGN_MAKE_FAIL)
class TestViewSet(CustomGenericViewSet):
authentication_classes = ()
permission_classes = ()
@action(methods=['post'], detail=False, serializer_class=SendSmsSerializer)
def send_sms(self, request, pk=None):
"""发送短信测试
发送短信测试
"""
serializer = SendSmsSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
vdata = serializer.validated_data
res = send_sms(**vdata)
return Response(res)
@action(methods=['post'], detail=False, serializer_class=GenerateVoiceSerializer)
def generate_voice(self, request, pk=None):
"""文字转语音测试
文字转语音测试
"""
serializer = GenerateVoiceSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
vdata = serializer.validated_data
res = generate_voice(**vdata)
return Response(res)
@action(methods=['post'], detail=False, serializer_class=TestTaskSerializer)
def task(self, request, pk=None):
"""任务派发测试
任务派发测试
"""
serializer = TestTaskSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
vdata = serializer.validated_data
ret = {}
task = show.delay(*vdata.get('args', []), **vdata.get('kwargs', {}))
ret['task_id'] = task.task_id
return Response(ret)

131
apps/utils/wx.py Normal file
View File

@ -0,0 +1,131 @@
import json
import time
from threading import Thread
import uuid
import requests
from django.conf import settings
from rest_framework.exceptions import APIException, ParseError
import logging
from apps.third.models import Tlog
from apps.utils.errors import WX_REQUEST_ERROR
from apps.utils.tools import print_roundtrip
from django.utils.timezone import now
import traceback
requests.packages.urllib3.disable_warnings()
# 实例化myLogger
myLogger = logging.getLogger('log')
class WxClient:
"""
微信公众号相关
"""
def __init__(self, app_id=settings.WX_APPID,
app_secret=settings.WX_APPSECRET) -> None:
if settings.WX_ENABLED:
self.app_id = app_id
self.app_secret = app_secret
self.isRuning = True
self.token = None
self.t = None # 线程
self.log = {}
self.setup()
def _get_token_loop(self):
while self.isRuning:
parmas = {
'grant_type': 'client_credential',
'appid': self.app_id,
'secret': self.app_secret
}
_, ret = self.request(url='/cgi-bin/token', params=parmas, method='get')
self.token = ret['access_token']
time.sleep(3600)
def setup(self):
t = Thread(target=self._get_token_loop, args=(), daemon=True)
t.start()
def __del__(self):
"""
自定义销毁
"""
self.isRuning = False
# self.t.join()
def request(self, url: str, method: str, params=dict(), json=dict(), timeout=10,
file_path_rela=None, raise_exception=True):
if not settings.WX_ENABLED:
raise ParseError('微信公众号未启用')
self.log = {"requested_at": now(), "id": uuid.uuid4(), "path": url, "method": method,
"params": params, "body": json, "target": "wx", "result": 10}
files = None
if file_path_rela: # 相对路径
files = {'file': open(settings.BASE_DIR + file_path_rela, 'rb')}
try:
if params:
url = url.format(**params)
self.log.update({"path": url})
r = getattr(requests, method)('{}{}'.format('https://api.weixin.qq.com', url),
params=params, json=json,
timeout=timeout, files=files, verify=False)
except Exception:
errors = traceback.format_exc()
myLogger.error(errors)
self.handle_log(result='error', errors=errors)
if raise_exception:
raise APIException(**WX_REQUEST_ERROR)
return 'error', WX_REQUEST_ERROR
# if settings.DEBUG:
# print_roundtrip(r)
if r.status_code == 200:
ret = r.json()
if 'errcode' in ret and ret['errcode'] not in [0, '0']:
detail = '微信错误:' + \
'{}|{}'.format(str(ret['errcode']), ret.get('errmsg', ''))
err_detail = dict(detail=detail, code='wx_'+str(ret['errcode']))
self.handle_log(result='fail', response=ret)
if raise_exception:
raise ParseError(**err_detail)
return 'fail', dict(detail=detail, code='wx_'+str(ret['errcode']))
# self.handle_log(result='success', response=ret) # 成功的日志就不记录了
return 'success', ret
self.handle_log(result='error', response=None)
if raise_exception:
raise APIException(**WX_REQUEST_ERROR)
return 'error', WX_REQUEST_ERROR
def _get_response_ms(self):
"""
Get the duration of the request response cycle is milliseconds.
In case of negative duration 0 is returned.
"""
response_timedelta = now() - self.log["requested_at"]
response_ms = int(response_timedelta.total_seconds() * 1000)
return max(response_ms, 0)
def handle_log(self, result, response=None, errors=None):
self.log.update({
"result": result,
"response": response,
"response_ms": self._get_response_ms(),
"errors": errors
})
Tlog(**self.log).save()
def get_basic_info(self, code):
params = {
'appid': self.app_id,
'secret': self.app_secret,
'code': code,
'grant_type': 'authorization_code'
}
_, res = self.request('/sns/oauth2/access_token', params=params, method='get')
return res
wxClient = WxClient()

106
apps/utils/wxmp.py Normal file
View File

@ -0,0 +1,106 @@
from distutils import errors
import json
import time
from threading import Thread
import uuid
import requests
from django.conf import settings
from rest_framework.exceptions import APIException, ParseError
import logging
from apps.third.models import Tlog
from apps.utils.errors import WX_REQUEST_ERROR
from apps.utils.tools import print_roundtrip
from django.utils.timezone import now
import traceback
requests.packages.urllib3.disable_warnings()
# 实例化myLogger
myLogger = logging.getLogger('log')
class WxmpClient:
"""
微信小程序相关
"""
def __init__(self, app_id=settings.WXMP_APPID,
app_secret=settings.WXMP_APPSECRET) -> None:
if settings.WXMP_ENABLED:
self.app_id = app_id
self.app_secret = app_secret
self.log = {}
def request(self, url: str, method: str, params=dict(), json=dict(), timeout=10,
file_path_rela=None, raise_exception=True):
if not settings.WX_ENABLED:
raise ParseError('微信小程序未启用')
self.log = {"requested_at": now(), "id": uuid.uuid4(), "path": url, "method": method,
"params": params, "body": json, "target": "wx", "result": 10}
files = None
if file_path_rela: # 相对路径
files = {'file': open(settings.BASE_DIR + file_path_rela, 'rb')}
try:
if params:
url = url.format(**params)
self.log.update({"path": url})
r = getattr(requests, method)('{}{}'.format('https://api.weixin.qq.com', url),
params=params, json=json,
timeout=timeout, files=files, verify=False)
except Exception:
errors = traceback.format_exc()
myLogger.error(errors)
self.handle_log(result='error', errors=errors)
if raise_exception:
raise APIException(**WX_REQUEST_ERROR)
return 'error', WX_REQUEST_ERROR
# if settings.DEBUG:
# print_roundtrip(r)
if r.status_code == 200:
ret = r.json()
if 'errcode' in ret and ret['errcode'] not in [0, '0']:
detail = '微信错误:' + \
'{}|{}'.format(str(ret['errcode']), ret.get('errmsg', ''))
err_detail = dict(detail=detail, code='wx_'+str(ret['errcode']))
self.handle_log(result='fail', response=ret)
if raise_exception:
raise ParseError(**err_detail)
return 'fail', dict(detail=detail, code='wx_'+str(ret['errcode']))
# self.handle_log(result='success', response=ret) # 成功的日志就不记录了
return 'success', ret
self.handle_log(result='error', response=None)
if raise_exception:
raise APIException(**WX_REQUEST_ERROR)
return 'error', WX_REQUEST_ERROR
def _get_response_ms(self):
"""
Get the duration of the request response cycle is milliseconds.
In case of negative duration 0 is returned.
"""
response_timedelta = now() - self.log["requested_at"]
response_ms = int(response_timedelta.total_seconds() * 1000)
return max(response_ms, 0)
def handle_log(self, result, response=None, errors=None):
self.log.update({
"result": result,
"response": response,
"response_ms": self._get_response_ms(),
"errors": errors
})
Tlog(**self.log).save()
def get_basic_info(self, code):
params = {
'appid': self.app_id,
'secret': self.app_secret,
'js_code': code,
'grant_type': 'authorization_code'
}
_, res = self.request('/sns/jscode2session', params=params, method='get')
return res
wxmpClient = WxmpClient()

View File

@ -1,7 +1,7 @@
# Create your tasks here # Create your tasks here
from __future__ import absolute_import, unicode_literals from __future__ import absolute_import, unicode_literals
from apps.hrm.models import Employee from apps.hrm.models import Employee
from apps.utils.task import CustomTask from apps.utils.tasks import CustomTask
from apps.vm.models import Visit, Vpeople from apps.vm.models import Visit, Vpeople
from apps.wf.models import Ticket from apps.wf.models import Ticket
from celery import shared_task from celery import shared_task

View File

@ -5,7 +5,7 @@ import logging
import traceback import traceback
from apps.system.models import User from apps.system.models import User
from apps.utils.sms import send_sms from apps.utils.sms import send_sms
from apps.utils.task import CustomTask from apps.utils.tasks import CustomTask
from celery import shared_task from celery import shared_task
from apps.wf.models import State, Ticket, TicketFlow, Transition from apps.wf.models import State, Ticket, TicketFlow, Transition

View File

@ -397,5 +397,10 @@ AI_IP = conf.AI_IP
# 微信有关 # 微信有关
WXMP_ENABLED = conf.WXMP_ENABLED
WXMP_APPID = conf.WXMP_APPID WXMP_APPID = conf.WXMP_APPID
WXMP_APPSECRET = conf.WXMP_APPSECRET WXMP_APPSECRET = conf.WXMP_APPSECRET
WX_ENABLED = conf.WX_ENABLED
WX_APPID = conf.WX_APPID
WX_APPSECRET = conf.WX_APPSECRET