from rest_framework.views import APIView from apps.lyTiktokUnion.models import DYSystemAccount from utils.jsonResponse import SuccessResponse,ErrorResponse,DetailResponse from utils.common import get_parameter_dic,formatdatetime from django.db.models import Q,F,Sum,Count from django.db import transaction from rest_framework import serializers from rest_framework_simplejwt.authentication import JWTAuthentication from utils.serializers import CustomModelSerializer from utils.viewset import CustomModelViewSet from rest_framework.permissions import IsAuthenticated from utils.pagination import CustomPagination from utils.douyin.douyin_utils import douyin from utils.douyin.douyinUnion_utils import douyinUnion from config import DOUYIN_OPENAPI_CLIENT_KEY,DOUYIN_OPENAPI_CLIENT_SECRET,DOMAIN_HOST from apps.lyTiktokUnion.tools.douyin import newdoudian_dklive_yz,newdoudian_dkfx_gj,newdoudian_tz_yz from django.http import HttpResponse import datetime import time import json import django_filters import logging logger = logging.getLogger(__name__) class DYSystemAccountFilterset(django_filters.rest_framework.FilterSet): #开始时间 beginAt = django_filters.DateTimeFilter(field_name='update_datetime', lookup_expr='gte') # 指定过滤的字段 #结束时间 endAt = django_filters.DateTimeFilter(field_name='update_datetime', lookup_expr='lte') # 模糊搜索 nickname = django_filters.CharFilter(field_name='nickname', lookup_expr='icontains') # icontains表示该字段模糊搜索 status = django_filters.CharFilter(field_name='status') class Meta: model = DYSystemAccount fields = ['beginAt', 'endAt','nickname','status'] class DYSystemAccountSerializer(CustomModelSerializer): token_status = serializers.SerializerMethodField() def get_token_status(self,obj): status = { "access_token":False, "refresh_token":False } now = datetime.datetime.now() if obj.access_token_expire >= now: status['access_token'] = True if obj.refresh_token_expire >=now: status['refresh_token'] = True return status class Meta: model = DYSystemAccount read_only_fields = ["id"] fields = '__all__' # 刷新抖店的认证,保持access_token为有效状态 def keepDouDianTokenOnline(): queryset = DYSystemAccount.objects.filter(is_delete=False) for m in queryset: if m.identity == 1: dk_accesstoken_ttl = newdoudian_dkfx_gj.get_cache_access_token_ttl() dk_refreshtoken_ttl = newdoudian_dkfx_gj.get_cache_refresh_access_token_ttl() if (dk_accesstoken_ttl < 0 or dk_accesstoken_ttl < 2*60*60) and dk_refreshtoken_ttl > 0: logger.info("开始刷新抖客token...") refresh_bool = newdoudian_dkfx_gj.refresh_token() if refresh_bool: nowtimestap = int(time.time()) access_token_expire_in = int(newdoudian_dkfx_gj.get_cache_access_token_ttl()) refresh_access_expire_in = int(newdoudian_dkfx_gj.get_cache_refresh_access_token_ttl()) new_access_token = newdoudian_dkfx_gj.get_access_token() new_refresh_token = newdoudian_dkfx_gj.get_cache_refresh_token() access_token_expire = datetime.datetime.fromtimestamp(nowtimestap + access_token_expire_in) refresh_token_expire = datetime.datetime.fromtimestamp(nowtimestap + refresh_access_expire_in) m.access_token = new_access_token m.refresh_token = new_refresh_token m.access_token_expire = access_token_expire m.refresh_token_expire = refresh_token_expire m.save() logger.info("刷新抖客token成功") else: logger.error("刷新抖客token失败") if m.identity == 2: tz_accesstoken_ttl = newdoudian_tz_yz.get_cache_access_token_ttl() tz_refreshtoken_ttl = newdoudian_tz_yz.get_cache_refresh_access_token_ttl() if (tz_accesstoken_ttl < 0 or tz_accesstoken_ttl < 2*60*60) and tz_refreshtoken_ttl > 0: logger.info("开始刷新团长token...") refresh_bool = newdoudian_tz_yz.refresh_token() if refresh_bool: nowtimestap = int(time.time()) access_token_expire_in = int(newdoudian_tz_yz.get_cache_access_token_ttl()) refresh_access_expire_in = int(newdoudian_tz_yz.get_cache_refresh_access_token_ttl()) new_access_token = newdoudian_tz_yz.get_access_token() new_refresh_token = newdoudian_tz_yz.get_cache_refresh_token() access_token_expire = datetime.datetime.fromtimestamp(nowtimestap + access_token_expire_in) refresh_token_expire = datetime.datetime.fromtimestamp(nowtimestap + refresh_access_expire_in) m.access_token = new_access_token m.refresh_token = new_refresh_token m.access_token_expire = access_token_expire m.refresh_token_expire = refresh_token_expire m.save() logger.info("刷新团长token成功") else: logger.error("刷新团长token失败") class DYSystemAccountViewSet(CustomModelViewSet): queryset = DYSystemAccount.objects.filter(is_delete=False).order_by("create_datetime") serializer_class = DYSystemAccountSerializer filterset_class = DYSystemAccountFilterset search_fields = ("nickname",) #重写delete方法,并改为逻辑删除 def destroy(self, request, *args, **kwargs): instance = self.get_object_list() for i in range(len(instance)): instance[i].is_delete = True model = self.get_serializer().Meta.model model.objects.bulk_update(instance,fields=['is_delete']) return SuccessResponse(data=[], msg="删除成功") # 工具型应用 抖客/达人 拼链接 方式 应用授权,抖客再浏览器登录自己的抖客账号,登录后访问此授权链接点击授权,会重定向授权code到 此 应用的【使用地址】(包括state) # 拼接后的地址如: https://buyin.jinritemai.com/dashboard/institution/through-power?app_id=7252637730696414757&state=state def createCodeBuyin(self,request): id = get_parameter_dic(request).get("id",None) if not id:#新增授权 url = newdoudian_dkfx_gj.build_auth_url(type=3) else:#重新授权 url = newdoudian_dkfx_gj.build_auth_url(type=3,state=id) return SuccessResponse(data=url) def getCodeBuyinUserinfo(self,request): #先触发刷新token keepDouDianTokenOnline() datas = [] data = { 'app_key':newdoudian_dkfx_gj.getCurrentAppKey(), 'buyin_id': "", 'name':"", 'status':"过期", 'identity':'抖客', 'expiretime':"" } instance = DYSystemAccount.objects.filter(identity=1,is_delete=False).first() if instance: buyin_id = instance.buyin_id data['buyin_id'] = buyin_id data['name'] = instance.nickname if newdoudian_dkfx_gj.get_cache_access_token_ttl(): data['status'] = "正常" data['expiretime'] = round((newdoudian_dkfx_gj.get_cache_access_token_ttl())/3600,1) else: data['name'] = "请使用抖客授权" datas.append(data) data2 = { 'app_key':newdoudian_tz_yz.getCurrentAppKey(), 'buyin_id':"", 'name':"", 'status':"过期", 'identity':'团长', 'expiretime':"" } instance2 = DYSystemAccount.objects.filter(identity=2, is_delete=False).first() if instance2: buyin_id = instance2.buyin_id data2['buyin_id'] = buyin_id data2['name'] = instance2.nickname if newdoudian_tz_yz.get_cache_access_token_ttl(): data2['status'] = "正常" data2['expiretime'] = round((newdoudian_tz_yz.get_cache_access_token_ttl()) / 3600, 1) else: data2['name'] = "请使用团长授权" datas.append(data2) return SuccessResponse(data=datas) # 生成抖音授权码链接 def createCode(self,request): id = get_parameter_dic(request).get("id",None) newdouyin = douyin(client_key=DOUYIN_OPENAPI_CLIENT_KEY,client_secret=DOUYIN_OPENAPI_CLIENT_SECRET) scope = "user_info,data.external.user,alliance.colonel.service,alliance.kol.buyin_id,alliance.product.skus,alliance.kol.store_manage,alliance.kol.reputation,alliance.kol.orders,alliance.kol.materials,alliance.kol.reputation,alliance.picksource.convert,alliance.kol.live_status" redirect_uri = DOMAIN_HOST+"/api/system/douyincodeCallback/" if not id:#新增授权 url = newdouyin.create_code(scope=scope,redirect_uri=redirect_uri) else:#重新授权 url = newdouyin.create_code(scope=scope,redirect_uri=redirect_uri,state=id) return SuccessResponse(data=url) # 刷新抖音授权码链接 def refreshAccessToken(self,request): id = get_parameter_dic(request)['id'] queryset = self.filter_queryset(self.get_queryset()) instance = queryset.filter(id=id,is_delete=False).first() if not instance: return ErrorResponse(msg="id error") now = datetime.datetime.now() refresh_datetime = datetime.timedelta(days=3)#提前三天刷新refresh_token if instance.refresh_token_expire < now: return ErrorResponse(msg="refresh_token已过期,请重新授权") newdouyin = douyin(client_key=DOUYIN_OPENAPI_CLIENT_KEY,client_secret=DOUYIN_OPENAPI_CLIENT_SECRET) #先检查是否要刷新refresh_token if instance.refresh_token_expire <= (now + refresh_datetime): refresh_res = newdouyin.refresh_refresh_token(instance.refresh_token) if refresh_res: if "error_code" in refresh_res["data"] and refresh_res["data"]["error_code"] == 0: refresh_res = refresh_res['data'] refresh_token = refresh_res.get("refresh_token") refresh_expires_in = refresh_res.get("refresh_expires_in") refresh_token_expire = now + datetime.timedelta(seconds=int(refresh_expires_in)) instance.refresh_token_expire = refresh_token_expire instance.refresh_token = refresh_token instance.save() #开始刷新access_token res = newdouyin.refresh_access_token(instance.refresh_token) if not res: return ErrorResponse(msg="刷新token错误") if "error_code" in res["data"] and not res["data"]["error_code"] == 0: return ErrorResponse(msg="获取刷新access_token失败,错误码:%s,描述:%s"%(res["data"]["error_code"],res["data"]["description"])) res = res['data'] instance.access_token = res.get("access_token") expires_in = res.get("expires_in") access_token_expire = now + datetime.timedelta(seconds=int(expires_in)) instance.access_token_expire = access_token_expire instance.save() return SuccessResponse(msg="刷新成功") #抖音后台达人账号code授权回调 class DouyinSytemDarenCodeCallbackView(APIView): ''' 抖音后台达人账号code授权回调 get: 抖音后台达人账号code授权回调 ''' authentication_classes = [] permission_classes = [] def get(self, request): newdouyin = douyin(client_key=DOUYIN_OPENAPI_CLIENT_KEY,client_secret=DOUYIN_OPENAPI_CLIENT_SECRET) data = get_parameter_dic(request) code,state = newdouyin.callback_code(data) if not all([code,state]): return HttpResponse("非法请求") logger.info("获取code回调信息code=%s|state=%s"%(code,state)) if state == "state":#新增 now = datetime.datetime.now() res = newdouyin.get_access_token(code=code) if not res: return HttpResponse("获取access_token失败") if "error_code" in res["data"] and not res["data"]["error_code"] == 0: return HttpResponse("获取access_token失败,错误码:%s,描述:%s"%(res["data"]["error_code"],res["data"]["description"])) logger.info("新增系统抖客/达人授权信息,获取token信息:%s"%(res)) res = res['data'] access_token = res.get("access_token") refresh_token = res.get("refresh_token") refresh_expires_in = res.get("refresh_expires_in") expires_in = res.get("expires_in") access_token_expire = now + datetime.timedelta(seconds=int(expires_in)) refresh_token_expire = now + datetime.timedelta(seconds=int(refresh_expires_in)) open_id = res.get("open_id") # newdouyinunion = douyinUnion(client_key=DOUYIN_OPENAPI_CLIENT_KEY,client_secret=DOUYIN_OPENAPI_CLIENT_SECRET) # buyin_id_res = newdouyinunion.get_buyin_id(access_token=access_token,open_id=open_id) # if not buyin_id_res: # return HttpResponse("获取百应ID失败") # logger.info("新增系统抖客/达人授权信息,获取百应ID信息:%s"%(buyin_id_res)) # buyin_id = buyin_id_res.get("buyin_id",None) userinfo = newdouyin.get_userinfo(access_token=access_token,open_id=open_id) if not userinfo: return HttpResponse("获取userinfo失败") logger.info("新增系统抖客/达人授权信息,获取用户基本信息%s"%(userinfo)) if "error_code" in userinfo["data"] and not userinfo["data"]["error_code"] == 0: return HttpResponse("获取userinfo失败,错误码:%s,描述:%s"%(userinfo["data"]["error_code"],userinfo["data"]["description"])) userinfo = userinfo['data'] avatar = userinfo.get("avatar") nickname = userinfo.get("nickname") DYSystemAccount.objects.create(refresh_token=refresh_token,access_token=access_token,open_id=open_id,avatar=avatar,nickname=nickname,access_token_expire=access_token_expire,refresh_token_expire=refresh_token_expire) return HttpResponse("获取授权成功!!!") #重新授权 instance = DYSystemAccount.objects.filter(id=state,is_delete=False).first() if not instance: return HttpResponse("非法请求2") now = datetime.datetime.now() res = newdouyin.get_access_token(code=code) if not res: return HttpResponse("获取access_token失败") if "error_code" in res["data"] and not res["data"]["error_code"] == 0: return HttpResponse("获取access_token失败,错误码:%s,描述:%s"%(res["data"]["error_code"],res["data"]["description"])) res = res['data'] access_token = res.get("access_token") refresh_token = res.get("refresh_token") refresh_expires_in = res.get("refresh_expires_in") expires_in = res.get("expires_in") access_token_expire = now + datetime.timedelta(seconds=int(expires_in)) refresh_token_expire = now + datetime.timedelta(seconds=int(refresh_expires_in)) instance.access_token = access_token instance.refresh_token = refresh_token instance.access_token_expire = access_token_expire instance.refresh_token_expire = refresh_token_expire instance.save() return HttpResponse("获取授权成功!!!")