Coverage for polar/payment/schemas.py: 100%

28 statements  

« prev     ^ index     » next       coverage.py v7.10.6, created at 2025-12-05 15:52 +0000

1from typing import Annotated, Any, Literal 1a

2 

3from fastapi import Path 1a

4from pydantic import UUID4, Field, TypeAdapter 1a

5 

6from polar.enums import PaymentProcessor 1a

7from polar.kit.schemas import ( 1a

8 CHECKOUT_ID_EXAMPLE, 

9 ORGANIZATION_ID_EXAMPLE, 

10 IDSchema, 

11 Schema, 

12 SetSchemaReference, 

13 TimestampedSchema, 

14) 

15from polar.models.payment import PaymentStatus 1a

16 

17PaymentID = Annotated[UUID4, Path(description="The payment ID.")] 1a

18 

19 

20class PaymentBase(IDSchema, TimestampedSchema): 1a

21 processor: PaymentProcessor = Field( 1a

22 description="The payment processor.", examples=[PaymentProcessor.stripe] 

23 ) 

24 status: PaymentStatus = Field( 1a

25 description="The payment status.", examples=[PaymentStatus.succeeded] 

26 ) 

27 amount: int = Field(description="The payment amount in cents.", examples=[1000]) 1a

28 currency: str = Field( 1a

29 description="The payment currency. Currently, only `usd` is supported.", 

30 examples=["usd"], 

31 ) 

32 method: str = Field(description="The payment method used.", examples=["card"]) 1a

33 decline_reason: str | None = Field( 1a

34 description="Error code, if the payment was declined.", 

35 examples=["insufficient_funds"], 

36 ) 

37 decline_message: str | None = Field( 1a

38 description="Human-reasable error message, if the payment was declined.", 

39 examples=["Your card has insufficient funds."], 

40 ) 

41 organization_id: UUID4 = Field( 1a

42 description="The ID of the organization that owns the payment.", 

43 examples=[ORGANIZATION_ID_EXAMPLE], 

44 ) 

45 checkout_id: UUID4 | None = Field( 1a

46 description="The ID of the checkout session associated with this payment.", 

47 examples=[CHECKOUT_ID_EXAMPLE], 

48 ) 

49 order_id: UUID4 | None = Field( 1a

50 description="The ID of the order associated with this payment.", 

51 examples=[CHECKOUT_ID_EXAMPLE], 

52 ) 

53 processor_metadata: dict[str, Any] = Field( 1a

54 description="Additional metadata from the payment processor for internal use.", 

55 default_factory=dict, 

56 ) 

57 

58 

59class GenericPayment(PaymentBase): 1a

60 """Schema of a payment with a generic payment method.""" 

61 

62 

63class CardPaymentMetadata(Schema): 1a

64 """Additional metadata for a card payment method.""" 

65 

66 brand: str = Field( 1a

67 description="The brand of the card used for the payment.", 

68 examples=["visa", "amex"], 

69 ) 

70 last4: str = Field( 1a

71 description="The last 4 digits of the card number.", examples=["4242"] 

72 ) 

73 

74 

75class CardPayment(PaymentBase): 1a

76 """Schema of a payment with a card payment method.""" 

77 

78 method: Literal["card"] = Field( 1a

79 description="The payment method used.", examples=["card"] 

80 ) 

81 method_metadata: CardPaymentMetadata = Field( 1a

82 description="Additional metadata for the card payment method." 

83 ) 

84 

85 

86Payment = Annotated[CardPayment | GenericPayment, SetSchemaReference("Payment")] 1a

87 

88PaymentAdapter: TypeAdapter[Payment] = TypeAdapter(Payment) 1a