docs: record redesign review artifacts
This commit is contained in:
85
tasks/evidence/2026-09-24/replay-local-payment.py
Normal file
85
tasks/evidence/2026-09-24/replay-local-payment.py
Normal file
@@ -0,0 +1,85 @@
|
||||
"""Replay paid-event outcomes in the isolated Bundle 0 Django test database.
|
||||
|
||||
External gateway calls, notifications, and SMS are mocked. This script is baseline
|
||||
evidence, not a production payment test or a browser gateway substitute.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
from django.conf import settings
|
||||
from django.test import Client, override_settings
|
||||
|
||||
from apps.events.models import Event, Registration
|
||||
from apps.payments.models import Payment
|
||||
from apps.users.models import User
|
||||
from core.authentication import create_jwt_token
|
||||
|
||||
|
||||
assert os.environ.get("DJANGO_SETTINGS_MODULE") == "config.settings.test"
|
||||
assert settings.DATABASES["default"]["ENGINE"] == "django.db.backends.sqlite3"
|
||||
|
||||
student = User.objects.get(username="bundle0_student")
|
||||
event = Event.objects.get(slug="bundle0-paid")
|
||||
client = Client()
|
||||
headers = {"HTTP_AUTHORIZATION": f"Bearer {create_jwt_token(student)}"}
|
||||
body = json.dumps({"event_id": event.pk, "description": "Local mocked payment replay"})
|
||||
|
||||
|
||||
def create_payment():
|
||||
return client.post(
|
||||
"/api/payments/create",
|
||||
data=body,
|
||||
content_type="application/json",
|
||||
**headers,
|
||||
)
|
||||
|
||||
|
||||
with (
|
||||
override_settings(ALLOWED_HOSTS=["testserver", "localhost"]),
|
||||
patch("apps.payments.api.views.notify_user"),
|
||||
patch("apps.payments.api.views.send_critical_sms.delay"),
|
||||
patch("apps.payments.api.views.requests.post") as gateway,
|
||||
):
|
||||
gateway.side_effect = RuntimeError("simulated gateway outage")
|
||||
failed_request = create_payment()
|
||||
assert failed_request.status_code == 502, failed_request.content
|
||||
assert not Payment.objects.filter(user=student, event=event).exists()
|
||||
|
||||
gateway.side_effect = None
|
||||
gateway.return_value = Mock()
|
||||
gateway.return_value.json.return_value = {
|
||||
"data": {"code": 100, "authority": "BUNDLE0-CANCEL"}
|
||||
}
|
||||
pending = create_payment()
|
||||
assert pending.status_code == 200, pending.content
|
||||
assert pending.json()["start_pay_url"]
|
||||
canceled = client.get(
|
||||
"/api/payments/callback",
|
||||
{"Authority": "BUNDLE0-CANCEL", "Status": "NOK"},
|
||||
)
|
||||
assert canceled.status_code == 302
|
||||
assert "status=failed" in canceled.url
|
||||
assert Payment.objects.get(authority="BUNDLE0-CANCEL").status == Payment.OrderStatusChoices.CANCELED
|
||||
|
||||
gateway.return_value.json.return_value = {
|
||||
"data": {"code": 100, "authority": "BUNDLE0-SUCCESS"}
|
||||
}
|
||||
pending = create_payment()
|
||||
assert pending.status_code == 200, pending.content
|
||||
gateway.return_value.json.return_value = {
|
||||
"data": {"code": 100, "ref_id": "BUNDLE0-REF"}
|
||||
}
|
||||
paid = client.get(
|
||||
"/api/payments/callback",
|
||||
{"Authority": "BUNDLE0-SUCCESS", "Status": "OK"},
|
||||
)
|
||||
assert paid.status_code == 302
|
||||
assert "status=success" in paid.url
|
||||
assert Payment.objects.get(authority="BUNDLE0-SUCCESS").status == Payment.OrderStatusChoices.PAID
|
||||
assert Registration.objects.get(user=student, event=event).status == Registration.StatusChoices.CONFIRMED
|
||||
duplicate = create_payment()
|
||||
assert duplicate.status_code == 400
|
||||
|
||||
print("Paid replay: gateway outage 502; cancellation redirect; mocked success and confirmed registration; duplicate blocked.")
|
||||
Reference in New Issue
Block a user