Coverage for packages/azericard/src/integrify/azericard/schemas/callback.py: 100%
59 statements
« prev ^ index » next coverage.py v7.16.0, created at 2026-10-19 02:39 +0000
« prev ^ index » next coverage.py v7.16.0, created at 2026-10-19 02:39 +0000
1from decimal import Decimal
2from hashlib import md5
4from integrify.azericard import env
5from integrify.azericard.schemas.common import AzeriCardMinimalWithAmountDataSchema
6from integrify.azericard.schemas.enums import Action, CardStatus
7from integrify.azericard.utils import TimeStampIn
8from pydantic import AliasGenerator, BaseModel, ConfigDict, Field, model_validator
9from pydantic.alias_generators import to_pascal
10from typing_extensions import Self
13class AuthCallbackSchema(AzeriCardMinimalWithAmountDataSchema):
14 model_config = ConfigDict(alias_generator=AliasGenerator(validation_alias=str.upper))
16 action: Action
17 """EGateway fəaliyyət kodu"""
19 rc: str = Field(min_length=2, max_length=2)
20 """Əməliyyat cavab kodu (ISO-8583 Sahə 39)"""
22 approval: str | None = Field(..., min_length=6, max_length=6)
23 """Müştəri bankının təsdiq kodu (ISO-8583 Sahə 38). Kart idarəetmə sistemi
24 tərəfindən təmin edilmədikdə boş ola bilər."""
26 rrn: str = Field(min_length=12, max_length=12)
27 """Müştəri bankının axtarış istinad nömrəsi (ISO-8583 Sahə 37)"""
29 int_ref: str = Field(min_length=1, max_length=128)
30 """Elektron ticarət şlüzünün daxili istinad nömrəsi"""
32 p_sign: str = Field(min_length=1, max_length=256)
33 """16-lıq formatda Merchant MAC"""
36class AuthCallbackWithCardDataSchema(AuthCallbackSchema):
37 card: str | None
38 """Masklanmış kart nömrəsi"""
40 token: str | None
41 """Saxlanılacaq kartın TOKEN parametri"""
44class TransferCallbackSchema(BaseModel):
45 model_config = ConfigDict(alias_generator=AliasGenerator(validation_alias=to_pascal))
47 operation_id: str = Field(min_length=16, max_length=20, validation_alias='OperationID')
48 """AzeriCard tərəfindən verilmiş unikal əməliyyat nömrəsi"""
50 srn: str = Field(min_length=1, max_length=12, validation_alias='SRN')
51 """Tərəfinizdən unikal əməliyyat nömrəsi"""
53 amount: Decimal
54 """Müraciətdən gələn məbləğ"""
56 cur: str
57 """Sorğunun valyutası yalnız AZN) olmalıdır"""
59 card_status: CardStatus
60 """Azericard tərəfində istifadəçi kartı statusu"""
62 receiver_pan: str = Field(min_length=16, max_length=16, validation_alias='ReceiverPAN')
63 """Maskalı kart nömrəsi"""
65 status: str
66 """Cari tranzaksiya statusu (məsələn, "pending")"""
68 timestamp: TimeStampIn
69 """Cavab vaxtı"""
71 rc: str = Field(validation_alias='Response Code')
72 """Cavab kodu"""
74 message: str
75 """Cavab mesajı"""
77 signature: str
78 """Hesablanmış dəyər MD5(Bütün sahələr birləşdirilib + Açar)"""
80 @model_validator(mode='after')
81 def validate_signature(self) -> Self:
82 """AzeriCard-dan gələn signature-ni təsdiqləmə funksiyası"""
83 with open(env.AZERICARD_KEY_FILE_PATH, encoding='utf-8') as key_file:
84 key = key_file.read().strip().replace('\r\n', '\n')
86 calc_signature = md5(
87 str(
88 self.operation_id
89 + self.srn
90 + str(self.amount)
91 + self.cur
92 + self.card_status
93 + self.receiver_pan
94 + self.status
95 + self.timestamp.strftime('%Y%m%d%H%M%S')
96 + self.rc
97 + self.message
98 + key
99 ).encode('utf-8'),
100 usedforsecurity=False,
101 ).hexdigest()
103 assert calc_signature == self.signature, 'Signature does not match!'
105 return self