This commit is contained in:
jeremygan2021
2026-02-10 23:35:53 +08:00
parent 6a025a7534
commit 0b3b81915b
24 changed files with 148 additions and 4 deletions

View File

@@ -18,6 +18,9 @@ import os
import base64
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
from django.conf import settings
import requests
import random
from django.core.cache import cache
# 猴子补丁:绕过微信支付响应签名验证
# 原因是在开发环境或证书未能正确下载时SDK 会因为无法验证微信返回的签名而抛出异常。
@@ -108,6 +111,70 @@ def get_wechat_pay_client():
except Exception as e:
return None, str(e)
@extend_schema(
summary="发送短信验证码",
description="发送6位数字验证码到指定手机号",
request={
'application/json': {
'type': 'object',
'properties': {
'phone_number': {'type': 'string', 'description': '手机号码'},
},
'required': ['phone_number']
}
},
responses={
200: OpenApiExample('成功', value={'message': '验证码已发送'}),
400: OpenApiExample('失败', value={'error': '手机号不能为空'})
}
)
@api_view(['POST'])
def send_sms_code(request):
phone = request.data.get('phone_number')
if not phone:
return Response({'error': '手机号不能为空'}, status=status.HTTP_400_BAD_REQUEST)
# 生成6位验证码
code = ''.join([str(random.randint(0, 9)) for _ in range(6)])
# 缓存验证码 (5分钟有效)
cache_key = f"sms_code_{phone}"
cache.set(cache_key, code, timeout=300)
# 调用外部短信API
try:
api_url = "https://data.tangledup-ai.com/api/send-sms"
payload = {
"phone_number": phone,
"code": code,
"template_code": "SMS_493295002",
"sign_name": "叠加态科技云南"
}
headers = {
"Content-Type": "application/json",
"accept": "application/json"
}
response = requests.post(api_url, json=payload, headers=headers, timeout=15)
if response.status_code == 200:
print(f"短信发送成功: {phone} -> {code}")
return Response({'message': '验证码已发送'})
else:
print(f"短信发送失败: {response.text}")
return Response({'error': '短信发送失败,请稍后重试'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
except requests.exceptions.Timeout:
print(f"短信发送超时: {phone}")
# 超时并不一定代表失败,可能是对方响应慢。但为了安全起见,提示用户稍后重试或检查手机。
# 考虑到用户反馈短信实际已收到,这里返回一个较为温和的错误或成功提示(视业务逻辑而定)。
# 这里我们选择返回一个特定的错误,前端可以据此提示用户。
return Response({'message': '短信请求已发送,请留意查收(如未收到请重试)'}, status=status.HTTP_200_OK)
except Exception as e:
print(f"发送短信异常: {str(e)}")
return Response({'error': '短信服务异常'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
@extend_schema(
summary="微信支付 V3 Native 下单",
description="创建订单并获取微信支付二维码链接(code_url)。参数包括商品ID、数量、客户信息等。",
@@ -181,6 +248,10 @@ def pay(request):
print(f"商品不存在: {good_id}")
return Response({'error': f'找不到 ID 为 {good_id} 的商品'}, status=status.HTTP_404_NOT_FOUND)
# 检查库存
if product.stock < quantity:
return Response({'error': f'库存不足,仅剩 {product.stock}'}, status=status.HTTP_400_BAD_REQUEST)
salesperson = None
if ref_code:
from .models import Salesperson
@@ -200,6 +271,10 @@ def pay(request):
status='pending'
)
# 扣减库存
product.stock -= quantity
product.save()
# 4. 调用微信支付接口
out_trade_no = f"PAY{order.id}T{int(time.time())}"
description = f"购买 {product.name} x {quantity}"
@@ -469,6 +544,37 @@ class OrderViewSet(viewsets.ModelViewSet):
serializer = self.get_serializer(orders, many=True)
return Response(serializer.data)
@action(detail=False, methods=['post'], authentication_classes=[], permission_classes=[])
def my_orders(self, request):
"""
查询我的订单
需要提供手机号和验证码
"""
phone = request.data.get('phone_number')
code = request.data.get('code')
if not phone or not code:
return Response({'error': '请提供手机号和验证码'}, status=status.HTTP_400_BAD_REQUEST)
# 验证验证码
cache_key = f"sms_code_{phone}"
cached_code = cache.get(cache_key)
# 开发/测试方便,如果验证码是 888888 且没有缓存,允许通过(可选,但为了演示方便)
# if code == '888888': pass
if not cached_code or cached_code != code:
return Response({'error': '验证码错误或已过期'}, status=status.HTTP_400_BAD_REQUEST)
# 查询订单
orders = Order.objects.filter(phone_number=phone).order_by('-created_at')
serializer = self.get_serializer(orders, many=True)
# 验证通过后清除验证码 (防止重放)
cache.delete(cache_key)
return Response(serializer.data)
@action(detail=True, methods=['post'])
def initiate_payment(self, request, pk=None):
"""