89 lines
3.3 KiB
Python
89 lines
3.3 KiB
Python
from __future__ import annotations
|
||
|
||
from django.conf import settings
|
||
from rest_framework import serializers
|
||
|
||
|
||
class ContactSerializer(serializers.Serializer):
|
||
email = serializers.EmailField()
|
||
first_name = serializers.CharField(required=False, allow_blank=True)
|
||
last_name = serializers.CharField(required=False, allow_blank=True)
|
||
phone_number = serializers.CharField(required=False, allow_blank=True)
|
||
city = serializers.CharField(required=False, allow_blank=True)
|
||
street = serializers.CharField(required=False, allow_blank=True)
|
||
postal_code = serializers.CharField(required=False, allow_blank=True)
|
||
country_code = serializers.CharField(required=False, allow_blank=True)
|
||
|
||
|
||
class PayerSerializer(serializers.Serializer):
|
||
contact = ContactSerializer()
|
||
|
||
# Optional controls – keep everything optional, no card numbers allowed (SDK handles UI)
|
||
allowed_payment_instruments = serializers.ListField(
|
||
child=serializers.CharField(), required=False
|
||
)
|
||
default_payment_instrument = serializers.CharField(required=False)
|
||
allowed_swifts = serializers.ListField(child=serializers.CharField(), required=False)
|
||
default_swift = serializers.CharField(required=False)
|
||
|
||
|
||
class CallbackSerializer(serializers.Serializer):
|
||
return_url = serializers.URLField()
|
||
notification_url = serializers.URLField(required=False)
|
||
|
||
def validate(self, attrs):
|
||
# Default notification_url from settings if not provided
|
||
if not attrs.get("notification_url"):
|
||
attrs["notification_url"] = getattr(
|
||
settings, "GOPAY_NOTIFICATION_URL", "http://localhost:8000/api/payments/gopay/webhook"
|
||
)
|
||
return attrs
|
||
|
||
|
||
class ItemSerializer(serializers.Serializer):
|
||
name = serializers.CharField()
|
||
amount = serializers.IntegerField(min_value=1, help_text="Minor units")
|
||
type = serializers.CharField(required=False, default="ITEM")
|
||
count = serializers.IntegerField(required=False, min_value=1, default=1)
|
||
|
||
|
||
class AdditionalParamSerializer(serializers.Serializer):
|
||
name = serializers.CharField()
|
||
value = serializers.CharField()
|
||
|
||
|
||
class PaymentBodySerializer(serializers.Serializer):
|
||
# Minimal required
|
||
amount = serializers.IntegerField(min_value=1, help_text="Minor units (e.g. 100 CZK = 10000)")
|
||
currency = serializers.CharField()
|
||
order_number = serializers.CharField()
|
||
|
||
# Optional
|
||
order_description = serializers.CharField(required=False, allow_blank=True)
|
||
payer = PayerSerializer()
|
||
callback = CallbackSerializer()
|
||
items = ItemSerializer(many=True, required=False)
|
||
additional_params = AdditionalParamSerializer(many=True, required=False)
|
||
lang = serializers.CharField(required=False)
|
||
preauthorize = serializers.BooleanField(required=False)
|
||
|
||
def validate(self, attrs):
|
||
# Explicitly reject any card details if someone tries to sneak them in
|
||
forbidden_keys = {"card", "card_data", "pan", "cvv", "expiry", "card_number"}
|
||
for key in list(attrs.keys()):
|
||
if key in forbidden_keys:
|
||
raise serializers.ValidationError({key: "Card details must not be sent to the server."})
|
||
return attrs
|
||
|
||
|
||
class PaymentCreateSerializer(serializers.Serializer):
|
||
# Frontend posts { payment: { ... } }
|
||
payment = PaymentBodySerializer()
|
||
|
||
# Optional: local metadata only (not sent to GoPay)
|
||
user_id = serializers.IntegerField(required=False)
|
||
|
||
|
||
class RefundSerializer(serializers.Serializer):
|
||
amount = serializers.IntegerField(min_value=1, help_text="Minor units")
|