Payment event ledger (PaymentEvent) replicated to the backup server, plus CSV export script on 247
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -15,7 +15,7 @@ from rest_framework.response import Response
|
||||
from rest_framework.throttling import ScopedRateThrottle
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from . import bazaar, zarinpal
|
||||
from . import bazaar, events, zarinpal
|
||||
from .models import Order
|
||||
from .permissions import HasInternalServiceKey
|
||||
from .serializers import (
|
||||
@@ -103,12 +103,18 @@ class PaymentRedirectView(APIView):
|
||||
if order.status != 'pending' or order.gateway_authority:
|
||||
break
|
||||
requested_amount = order.amount
|
||||
result = zarinpal.request_payment(order)
|
||||
try:
|
||||
result = zarinpal.request_payment(order)
|
||||
except Exception as exc:
|
||||
events.record('gateway_request_failed', order=order, error=type(exc).__name__)
|
||||
raise
|
||||
Order.objects.filter(pk=order.pk, gateway_authority='', amount=requested_amount).update(
|
||||
gateway_authority=result.authority,
|
||||
)
|
||||
order.refresh_from_db(fields=['gateway_authority', 'amount', 'status'])
|
||||
|
||||
events.record('gateway_redirect', order=order, status=order.status,
|
||||
authority_set=bool(order.gateway_authority))
|
||||
if order.status != 'pending':
|
||||
# سفارش از قبل نتیجه گرفته (paid/failed، یا کدِ ۱۰۰٪ همین الان)؛ چیزی برای پرداختِ تازه نیست.
|
||||
# کاربر به اپ برمیگردد با همان نتیجه، نه به ریشهی دامنهی API.
|
||||
@@ -159,7 +165,10 @@ class ZarinpalCallbackView(APIView):
|
||||
if order is None:
|
||||
# کالبکِ بیسفارش: یا Authorityِ جعلی یا سفارشی که از دیتابیس رفته؛ در دیتابیس ردی ندارد.
|
||||
logger.warning('zarinpal callback: no order for authority=%s status=%s', authority[:64], status_param[:10])
|
||||
events.record('callback_unknown_authority', provider='gateway',
|
||||
authority=authority[:64], status_param=status_param[:10])
|
||||
raise Http404
|
||||
events.record('callback_received', order=order, authority=authority[:64], status_param=status_param[:10])
|
||||
if status_param != 'OK':
|
||||
new_status, gateway_ref_id = 'failed', ''
|
||||
else:
|
||||
@@ -168,6 +177,7 @@ class ZarinpalCallbackView(APIView):
|
||||
)
|
||||
new_status = 'paid' if result.is_valid else 'failed'
|
||||
gateway_ref_id = result.ref_id
|
||||
events.record('verify_result', order=order, valid=bool(result.is_valid), ref_id=gateway_ref_id)
|
||||
|
||||
with transaction.atomic():
|
||||
locked_order = get_object_or_404(Order.objects.select_for_update(), pk=order.pk)
|
||||
@@ -306,6 +316,7 @@ class BazaarVerifyPurchaseView(APIView):
|
||||
# apply_order_payment_result سفارش را از نو میخواند و همان را عوض میکند؛ این نمونه هنوز
|
||||
# وضعیتِ پیش از پرداخت را دارد. بدونِ این، پاسخ «pending» بود درحالیکه سفارش «paid» شده بود.
|
||||
order.refresh_from_db(fields=['status'])
|
||||
events.record('bazaar_verify', order=order, valid=bool(result.is_valid), status=order.status)
|
||||
|
||||
data = {'orderId': str(order.id), 'status': order.status, 'valid': result.is_valid}
|
||||
return Response(BazaarVerifyResponseSerializer(data).data)
|
||||
@@ -366,6 +377,7 @@ class BazaarStartPurchaseView(APIView):
|
||||
# علامتِ «خرید شروع شد» تا کدِ تخفیفِ بعدی نیاید؛ قیمت همان قیمتِ کامل است.
|
||||
order.bazaar_price_rial = _to_rial(order.amount, order.currency)
|
||||
order.save(update_fields=['bazaar_price_rial'])
|
||||
events.record('bazaar_start', order=order, amount=order.amount, discounted=token is not None)
|
||||
data = {
|
||||
'orderId': str(order.id),
|
||||
'sku': order.bazaar_product_sku,
|
||||
|
||||
Reference in New Issue
Block a user