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")