import json import requests from urllib.parse import urljoin from django.db.models import Q from django_filters.rest_framework import DjangoFilterBackend from django_redis import get_redis_connection from rest_framework import filters from rest_framework import viewsets from django.views.decorators.csrf import csrf_exempt from dspt_api.models import EcChannel, EcEnv, EcApi, EcApiParams, EcCinemaIds, EcRequestLog, EcApiGroup from dspt_api.serializers import EcChannelSerializer, EcEnvSerializer, EcApiSerializer, EcApiParamsSerializer, \ EcCinemaIdsSerializer, EcRequestLogSerializer, EcApiGroupSerializer from dspt_api.util.sign import Sign # Create your views here. class EcChannelViewSet(viewsets.ModelViewSet): queryset = EcChannel.objects.all() serializer_class = EcChannelSerializer class EcEnvViewSet(viewsets.ModelViewSet): queryset = EcEnv.objects.all() serializer_class = EcEnvSerializer class EcApiViewSet(viewsets.ModelViewSet): queryset = EcApi.objects.all() serializer_class = EcApiSerializer class EcApiParamsViewSet(viewsets.ModelViewSet): queryset = EcApiParams.objects.all() serializer_class = EcApiParamsSerializer filter_backends = (filters.SearchFilter, DjangoFilterBackend) # http://172.16.1.114:8000/ec/get_api_params?api_id=1 filterset_fields = ('api_id',) class EcCinemaIdsViewSet(viewsets.ModelViewSet): queryset = EcCinemaIds.objects.all() serializer_class = EcCinemaIdsSerializer class EcRequestLogViewSet(viewsets.ModelViewSet): queryset = EcRequestLog.objects.all() serializer_class = EcRequestLogSerializer class EcApiGroupViewSet(viewsets.ModelViewSet): queryset = EcApiGroup.objects.all() serializer_class = EcApiGroupSerializer # 内部方法,用于生成requests请求对象 def handle_request(_request): """ POST请求参数 env dspt或zyds member_type member或nonmember api api地址 params 请求参数 """ req = _request.POST env = req.get('env') member_type = req.get('member_type') base_url = EcEnv.objects.filter(Q(code=env) & Q(type=member_type)).first().get('host') api = req.get('api') params = json.loads(req.get('params')) pid = params.get('pid') key = EcChannel.objects.filter(Q(pid=pid) & Q(env=env)).first().get('channel_key') sign = Sign(key) req_params = sign.add_sig(params) req_obj = prepare_request(base_url, api, req_params) return req_obj # 内部方法,用于拼接请求 def prepare_request(_url, _api, _params): req = requests.PreparedRequest() req.prepare_method('GET') req.prepare_url(url=urljoin(_url, _api), params=_params) req.prepare_headers({'host': _url[7:]}) return req # 外部接口, 用于实时生成url并返回前端 @csrf_exempt def general_api_url(request): """ 此接口为POST接口 request 包含 env dspt或zyds member_type member或nonmember api api地址 params 请求参数 """ req_obj = handle_request(request) return req_obj.url # 对外接口,用于收集用户提交内容后发送请求 @csrf_exempt def send_request(request): """ request 包含 1. 请求链接 request_url 2. 返回数据 response_data 3. 接口 api 4. 环境 env """ # 初始化redis redis_conn = get_redis_connection() user_ip = request.META.get('REMOTE_ADDR') api = request.get('api') redis_key_api = f'dspt_api_{user_ip}_{api}' redis_key_user_data = f'dspt_api_{user_ip}_{api}_data' # 发送请求 req = handle_request(request) response = requests.Session().send(req) # 记录Redis if redis_conn.exists(redis_key_api): redis_conn.delete(redis_key_api) else: data = { 'request_url': request.get('request_url'), 'response_data': response.json() } redis_conn.set(redis_key_api, json.dumps(data), 10 * 60 * 60) redis_conn.delete(redis_key_user_data) # 插入数据 db_data = { 'ip': user_ip, 'env': request.get('env'), 'request': request.get('request_url'), 'response': response.json() } EcRequestLog.objects.create(db_data) return response.json() # 对外接口,用于收集用户选择的数据,例如场次,卖品等,以便后续接口直接调用 @csrf_exempt def user_select_data(request): # 初始化redis redis_conn = get_redis_connection() user_ip = request.META.get('REMOTE_ADDR') api = request.get('api') redis_key_user_data = f'dspt_api_{user_ip}_{api}_data' # 记录用户选择 data = { 'user_data': request.get('user_data') } if redis_conn.exists(redis_key_user_data): redis_conn.delete(redis_key_user_data) result = redis_conn.set(redis_key_user_data, json.dumps(data), 10 * 60 * 60) return result # 对外接口,用于给前端提供上次请求的数据,如果没有则返回数据库中的默认值 # 若果有些字段是依赖于其他接口返回值生成的则单独处理此接口, 单独处理逻辑在util目录下 @csrf_exempt def get_last_request_data(request): redis_conn = get_redis_connection() user_ip = request.META.get('REMOTE_ADDR') api = request.get('api') match api: case '': pass case _: pass