from github pull code

This commit is contained in:
xiaoma
2026-02-06 20:17:01 +08:00
51 changed files with 1026912 additions and 33 deletions

6
backend/.dockerignore Normal file
View File

@@ -0,0 +1,6 @@
venv
__pycache__
*.pyc
.git
.env
db.sqlite3

View File

@@ -8,12 +8,6 @@ ENV PYTHONUNBUFFERED=1
# Set work directory
WORKDIR /app
# Install system dependencies (needed for psycopg2 and others)
RUN apt-get update && apt-get install -y \
gcc \
libpq-dev \
&& rm -rf /var/lib/apt/lists/*
# Install python dependencies
COPY requirements.txt /app/
RUN pip install --upgrade pip && pip install -r requirements.txt

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -82,17 +82,26 @@ WSGI_APPLICATION = 'config.wsgi.application'
# Database
# https://docs.djangoproject.com/en/6.0/ref/settings/#databases
# 优先使用 SQLite 进行本地开发,如果需要 PostgreSQL 请自行配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'market',
'USER': 'market',
'PASSWORD': '123market',
'HOST': '6.6.6.66',
'PORT': '5432',
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# 如果您坚持要使用 PostgreSQL请取消下面的注释并确保本地已启动 Postgres 服务
# DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.postgresql',
# 'NAME': 'market',
# 'USER': 'market',
# 'PASSWORD': '123market',
# 'HOST': 'localhost',
# 'PORT': '5432',
# }
# }
# Password validation
# https://docs.djangoproject.com/en/6.0/ref/settings/#auth-password-validators

BIN
backend/db.sqlite3 Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,6 +1,6 @@
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import ESP32ConfigViewSet, OrderViewSet, order_check_view, ServiceViewSet, ARServiceViewSet, ServiceOrderViewSet
from .views import ESP32ConfigViewSet, OrderViewSet, order_check_view, ServiceViewSet, ARServiceViewSet, ServiceOrderViewSet, payment_finish
router = DefaultRouter()
router.register(r'configs', ESP32ConfigViewSet)
@@ -11,5 +11,6 @@ router.register(r'service-orders', ServiceOrderViewSet)
urlpatterns = [
path('', include(router.urls)),
path('finish/', payment_finish, name='payment-finish'),
path('page/check-order/', order_check_view, name='check-order-page'),
]

View File

@@ -2,9 +2,77 @@ from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
from drf_spectacular.utils import extend_schema, extend_schema_view, OpenApiParameter, OpenApiExample
from .models import ESP32Config, Order, WeChatPayConfig, Service, ARService, ServiceOrder
from .serializers import ESP32ConfigSerializer, OrderSerializer, ServiceSerializer, ARServiceSerializer, ServiceOrderSerializer
import xml.etree.ElementTree as ET
import uuid
import time
import hashlib
@csrf_exempt
def payment_finish(request):
"""
微信支付回调接口
URL: /api/finish/
"""
if request.method != 'POST':
return HttpResponse("Method not allowed", status=405)
try:
# 解析微信发送的 XML
xml_data = request.body
if not xml_data:
return HttpResponse("Empty body", status=400)
root = ET.fromstring(xml_data)
# 将 XML 转为字典
data = {child.tag: child.text for child in root}
# 检查支付结果
# WeChat Pay V2 回调参数中 return_code 为通信标识result_code 为业务结果
if data.get('return_code') == 'SUCCESS' and data.get('result_code') == 'SUCCESS':
# out_trade_no 是我们在统一下单时传给微信的订单号
order_id = data.get('out_trade_no')
transaction_id = data.get('transaction_id') # 微信支付订单号
# 找到订单并更新状态
try:
# 兼容处理:如果是字符串 ID尝试转换
order = Order.objects.get(id=order_id)
if order.status != 'paid':
order.status = 'paid'
order.wechat_trade_no = transaction_id
order.save()
print(f"Order {order_id} marked as paid via callback.")
except Order.DoesNotExist:
print(f"Order {order_id} not found in callback.")
except Exception as e:
print(f"Error processing order {order_id} in callback: {e}")
# 返回成功响应给微信,否则微信会不断重试通知
success_response = """
<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
</xml>
"""
return HttpResponse(success_response, content_type='application/xml')
except ET.ParseError:
return HttpResponse("Invalid XML", status=400)
except Exception as e:
print(f"Payment callback error: {e}")
error_response = f"""
<xml>
<return_code><![CDATA[FAIL]]></return_code>
<return_msg><![CDATA[{str(e)}]]></return_msg>
</xml>
"""
return HttpResponse(error_response, content_type='application/xml')
@extend_schema_view(
list=extend_schema(summary="获取AR服务列表", description="获取所有可用的AR服务"),
@@ -16,9 +84,6 @@ class ARServiceViewSet(viewsets.ReadOnlyModelViewSet):
"""
queryset = ARService.objects.all().order_by('-created_at')
serializer_class = ARServiceSerializer
import uuid
import time
import hashlib
def order_check_view(request):
"""