feat: add recharge callback processing

This commit is contained in:
QiuSW
2026-07-03 09:07:21 +08:00
parent 8931960b35
commit c15a07a5c2
20 changed files with 1073 additions and 25 deletions
+80 -1
View File
@@ -1,3 +1,8 @@
import logging
from django.http import HttpResponse
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from rest_framework.exceptions import AuthenticationFailed
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
@@ -15,7 +20,22 @@ from apps.api.serializers import (
GenerateImageRequestSerializer,
GenerateTitleRequestSerializer,
)
from apps.billing.services import get_balance_snapshot
from apps.billing.payment_gateways import (
PaymentVerificationError,
verify_alipay_callback,
verify_wechat_callback,
)
from apps.billing.services import (
InvalidRechargeOrderStateError,
RechargeAmountMismatchError,
RechargeCallbackError,
RechargeOrderNotFoundError,
RechargePayMethodMismatchError,
apply_recharge_payment,
get_balance_snapshot,
)
logger = logging.getLogger(__name__)
class ExternalApiView(APIView):
@@ -77,3 +97,62 @@ class BalanceView(ExternalApiView):
},
status=status.HTTP_200_OK,
)
class RechargeCallbackView(APIView):
authentication_classes = ()
permission_classes = ()
@staticmethod
def _error_response(exc: Exception):
if isinstance(exc, PaymentVerificationError):
return (
api_error("signature_invalid", "支付回调验签失败"),
status.HTTP_400_BAD_REQUEST,
)
if isinstance(exc, RechargeAmountMismatchError):
return (
api_error("amount_mismatch", "支付回调金额与本地订单金额不一致"),
status.HTTP_400_BAD_REQUEST,
)
if isinstance(exc, RechargeCallbackError):
return api_error(exc.code, "支付回调处理失败"), status.HTTP_400_BAD_REQUEST
return api_error("bad_request", "支付回调处理失败"), status.HTTP_400_BAD_REQUEST
@method_decorator(csrf_exempt, name="dispatch")
class WechatRechargeCallbackView(RechargeCallbackView):
def post(self, request):
try:
payment = verify_wechat_callback(request.headers, request.body)
apply_recharge_payment(payment)
except (
PaymentVerificationError,
RechargeAmountMismatchError,
InvalidRechargeOrderStateError,
RechargeOrderNotFoundError,
RechargePayMethodMismatchError,
) as exc:
logger.warning("Rejected WeChat recharge callback: %s", exc.__class__.__name__)
data, http_status = self._error_response(exc)
return Response(data, status=http_status)
return Response({"code": "SUCCESS", "message": "成功"}, status=status.HTTP_200_OK)
@method_decorator(csrf_exempt, name="dispatch")
class AlipayRechargeCallbackView(RechargeCallbackView):
def post(self, request):
try:
payload = request.data.dict() if hasattr(request.data, "dict") else dict(request.data)
payment = verify_alipay_callback(payload)
apply_recharge_payment(payment)
except (
PaymentVerificationError,
RechargeAmountMismatchError,
InvalidRechargeOrderStateError,
RechargeOrderNotFoundError,
RechargePayMethodMismatchError,
) as exc:
logger.warning("Rejected Alipay recharge callback: %s", exc.__class__.__name__)
return HttpResponse("fail", status=status.HTTP_400_BAD_REQUEST)
return HttpResponse("success", content_type="text/plain", status=status.HTTP_200_OK)