Skip to content

Commit 13c4bc2

Browse files
authored
Merge pull request #6 from buserbrasil/fix-pyright-errors
Fix pyright errors
2 parents 4760c62 + 4003e17 commit 13c4bc2

File tree

11 files changed

+542
-305
lines changed

11 files changed

+542
-305
lines changed

santander_client/api_client/abstract_client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
class SantanderAbstractApiClient(ABC):
55
@abstractmethod
6-
def get(self, endpoint: str, params: dict = None) -> dict:
6+
def get(self, endpoint: str, params: dict | None = None) -> dict:
77
pass
88

99
@abstractmethod

santander_client/api_client/client.py

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,15 @@ class SantanderApiClient(SantanderAbstractApiClient):
3636

3737
def __init__(self, config: SantanderClientConfiguration):
3838
if not isinstance(config, SantanderClientConfiguration):
39-
raise SantanderClientConfiguration("Objeto de autenticação inválido")
39+
raise SantanderClientException("Objeto de autenticação inválido")
4040

4141
self.base_url = config.base_url.rstrip("/")
4242
self.config = config
4343
self.session = requests.Session()
4444
self.token = None
4545
self.token_expires_at = datetime.now()
4646

47-
def get(self, endpoint: str, params: dict = None) -> dict:
47+
def get(self, endpoint: str, params: dict | None = None) -> dict:
4848
return self._request("GET", endpoint, params=params)
4949

5050
def post(self, endpoint: str, data: dict) -> dict:
@@ -79,12 +79,14 @@ def _authenticate(self) -> None:
7979
self.token_expires_at = datetime.now() + timedelta(
8080
seconds=token_data.get("expires_in", 120)
8181
)
82-
self.session.headers = {
83-
"Authorization": f"Bearer {self.token}",
84-
"X-Application-Key": self.config.client_id,
85-
}
82+
self.session.headers.update(
83+
{
84+
"Authorization": f"Bearer {self.token}",
85+
"X-Application-Key": self.config.client_id,
86+
}
87+
)
8688
self.session.verify = True
87-
self.session.cert = self.config.cert
89+
self.session.cert = self.config.cert # pyright: ignore
8890

8991
def _request_token(self) -> dict:
9092
url = urljoin(self.base_url, TOKEN_ENDPOINT)
@@ -105,7 +107,7 @@ def _request_token(self) -> dict:
105107
)
106108
response.raise_for_status()
107109
except requests.exceptions.RequestException as e:
108-
status_code = getattr(e.response, "status_code", None)
110+
status_code = getattr(e.response, "status_code", 0)
109111
response = try_parse_response_to_json(e.response)
110112
raise SantanderRequestException(
111113
f"Erro na obtenção do Token: {e}", status_code, response
@@ -123,7 +125,11 @@ def _prepare_url(self, endpoint: str) -> str:
123125
return url
124126

125127
def _request(
126-
self, method: str, endpoint: str, data: dict = None, params: dict = None
128+
self,
129+
method: str,
130+
endpoint: str,
131+
data: dict | None = None,
132+
params: dict | None = None,
127133
) -> dict:
128134
self._ensure_requirements()
129135
url = self._prepare_url(endpoint)
@@ -135,12 +141,12 @@ def _request(
135141
response.raise_for_status()
136142
return response.json()
137143
except requests.exceptions.RequestException as e:
138-
status_code = getattr(e.response, "status_code", None)
144+
status_code = getattr(e.response, "status_code", 0)
139145
error_content = try_parse_response_to_json(e.response)
140146
status_description = get_status_code_description(status_code)
141147

142148
raise SantanderRequestException(
143149
status_description, status_code, error_content
144150
)
145151
except Exception as e:
146-
raise SantanderRequestException(f"Erro na requisição: {e}", None, None)
152+
raise SantanderRequestException(f"Erro na requisição: {e}", 0, None) from e

santander_client/api_client/helpers.py

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
from decimal import ROUND_DOWN, Decimal
2-
from datetime import timezone
32
import logging
4-
from dateutil import tz
53
from itertools import cycle
64
from typing import Literal
75
import re
@@ -84,13 +82,6 @@ def get_status_code_description(status_code: int | str) -> str:
8482
return f"{status_code} - {SANTANDER_STATUS_DESCRIPTIONS.get(int(status_code), 'Erro desconhecido')}"
8583

8684

87-
def today():
88-
now = (
89-
timezone.now().replace(tzinfo=tz.UTC).astimezone(tz.gettz("America/Sao_Paulo"))
90-
)
91-
return now.date()
92-
93-
9485
def only_numbers(s):
9586
return re.sub("[^0-9]", "", s) if s else s
9687

santander_client/api_client/workspaces.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def get_first_workspace_id_of_type(
3333
) -> str | None:
3434
_check_client_instance(client)
3535
workspaces = get_workspaces(client)
36-
if len(workspaces) == 0:
36+
if workspaces is None or len(workspaces) == 0:
3737
return None
3838

3939
workspace_id = next(

santander_client/pix.py

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from decimal import Decimal as D
22
import logging
33
from time import sleep
4-
from typing import List, Literal
4+
from typing import List, Literal, cast
55

66
from santander_client.api_client import get_client
77
from santander_client.api_client.exceptions import (
@@ -22,8 +22,9 @@
2222
BeneficiaryDataDict,
2323
ConfirmOrderStatus,
2424
CreateOrderStatus,
25-
SantanderAPIErrorResponse,
26-
SantanderCreatePixResponse,
25+
OrderStatus,
26+
OrderStatusType,
27+
SantanderPixResponse,
2728
TransferPixResult,
2829
)
2930

@@ -40,8 +41,6 @@
4041
"checking": "CONTA_CORRENTE",
4142
}
4243

43-
SantanderPixResponse = SantanderCreatePixResponse | SantanderAPIErrorResponse
44-
4544

4645
def transfer_pix_payment(
4746
pix_info: str | BeneficiaryDataDict, value: D, description: str, tags=[]
@@ -74,16 +73,21 @@ def transfer_pix_payment(
7473

7574
if not pix_id:
7675
raise SantanderClientException(
77-
"ID do pagamento PIX não foi retornada pela criação do pagamento"
76+
"ID do pagamento não foi retornada na criação"
77+
)
78+
79+
if payment_status is None:
80+
raise SantanderClientException(
81+
"Status do pagamento não retornado na criação"
7882
)
7983

8084
confirm_response = _confirm_pix_payment(pix_id, value, payment_status)
8185

82-
return {"success": True, "data": confirm_response}
86+
return {"success": True, "data": confirm_response, "error": ""}
8387
except Exception as e:
8488
error_message = str(e)
8589
logger.error(error_message)
86-
return {"success": False, "error": error_message}
90+
return {"success": False, "error": error_message, "data": None}
8791

8892

8993
def _pix_payment_status_polling(
@@ -92,7 +96,11 @@ def _pix_payment_status_polling(
9296
context: Literal["CREATE", "CONFIRM"],
9397
max_attempts: int,
9498
) -> SantanderPixResponse:
95-
for attempt in range(max_attempts):
99+
response = _request_pix_payment_status(pix_id, context)
100+
if response.get("status") in until_status:
101+
return response
102+
103+
for attempt in range(max_attempts - 1):
96104
response = _request_pix_payment_status(pix_id, context)
97105
payment_status = response.get("status")
98106
logger.info(
@@ -102,7 +110,7 @@ def _pix_payment_status_polling(
102110
if payment_status in until_status:
103111
break
104112

105-
if attempt == max_attempts - 1:
113+
if attempt == max_attempts - 2:
106114
raise SantanderTimeoutToChangeStatusException(
107115
"Limite de tentativas de atualização do status do pagamento PIX atingido",
108116
context,
@@ -114,7 +122,7 @@ def _pix_payment_status_polling(
114122

115123

116124
def _confirm_pix_payment(
117-
pix_id: str, value: D, payment_status: CreateOrderStatus
125+
pix_id: str, value: D, payment_status: OrderStatusType
118126
) -> SantanderPixResponse:
119127
"""Confirma o pagamento PIX, realizando polling até que o status seja PAYED ou permaneça PENDING_CONFIRMATION.
120128
@@ -169,7 +177,7 @@ def _confirm_pix_payment(
169177

170178

171179
def _request_create_pix_payment(
172-
pix_info: BeneficiaryDataDict, value: D, description: str, tags=[]
180+
pix_info: BeneficiaryDataDict | str, value: D, description: str, tags=[]
173181
) -> SantanderPixResponse:
174182
"""Cria uma ordem de pagamento. Caso o status seja REJECTED, a exceção SantanderRejectedTransactionException é lançada.
175183
Regra de negócio aqui: pagamento por beneficiário na request deve ser informado o bank_code ou ispb, nunca os dois."""
@@ -193,13 +201,16 @@ def _request_create_pix_payment(
193201
"documentNumber": pix_info["bank_account"]["document_number"],
194202
"name": pix_info["recebedor"]["name"],
195203
}
196-
if pix_info.get("bank_account"):
197-
if pix_info["bank_account"].get("bank_code_compe"):
198-
beneficiary["bankCode"] = pix_info["bank_account"][
199-
"bank_code_compe"
200-
]
201-
else:
202-
beneficiary["ispb"] = pix_info["bank_account"]["bank_code_ispb"]
204+
bank_account = pix_info["bank_account"]
205+
bank_code = bank_account.get("bank_code_compe", "")
206+
bank_ispb = bank_account.get("bank_code_ispb", "")
207+
if bank_code:
208+
beneficiary["bankCode"] = bank_code
209+
elif bank_ispb:
210+
beneficiary["ispb"] = bank_ispb
211+
else:
212+
raise SantanderValueErrorException("A chave de entrada é inválida")
213+
203214
data.update({"beneficiary": beneficiary})
204215
except KeyError as e:
205216
raise SantanderValueErrorException(
@@ -209,7 +220,7 @@ def _request_create_pix_payment(
209220
raise SantanderValueErrorException("Chave PIX ou Beneficiário não informado")
210221

211222
client = get_client()
212-
response = client.post(PIX_ENDPOINT, data=data)
223+
response = cast(SantanderPixResponse, client.post(PIX_ENDPOINT, data=data))
213224
_check_for_rejected_exception(response, "Criação do pagamento PIX")
214225
return response
215226

@@ -231,6 +242,7 @@ def _request_confirm_pix_payment(pix_payment_id: str, value: D) -> SantanderPixR
231242
"paymentValue": truncate_value(value),
232243
}
233244
response = client.patch(f"{PIX_ENDPOINT}/{pix_payment_id}", data=data)
245+
response = cast(SantanderPixResponse, response)
234246
_check_for_rejected_exception(response, "Confirmação do pagamento PIX")
235247
return response
236248

@@ -249,13 +261,14 @@ def _request_pix_payment_status(
249261

250262
client = get_client()
251263
response = client.get(f"{PIX_ENDPOINT}/{pix_payment_id}")
264+
response = cast(SantanderPixResponse, response)
252265
_check_for_rejected_exception(response, step_description)
253266
return response
254267

255268

256269
def _check_for_rejected_exception(pix_response: SantanderPixResponse, step: str):
257270
"""Uma transação quando rejeitada com status REJECTED, não deve ser continuada"""
258-
if pix_response.get("status") == "REJECTED":
271+
if pix_response.get("status") == OrderStatus.REJECTED:
259272
reject_reason = pix_response.get(
260273
"rejectReason", "Motivo não retornado pelo Santander"
261274
)

santander_client/types.py

Lines changed: 22 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,12 @@ class OrderStatus(ConfirmOrderStatus, CreateOrderStatus):
120120
pass
121121

122122

123-
class SantanderCreatePixResponse(TypedDict):
123+
OrderStatusType = Literal[
124+
"READY_TO_PAY", "PENDING_VALIDATION", "PAYED", "PENDING_CONFIRMATION", "REJECTED"
125+
]
126+
127+
128+
class SantanderTransferResponse(TypedDict):
124129
"""
125130
Resposta da criação de transações pix do Santander (POST).
126131
- Os campos mais importantes aqui são o id, status, paymentValue e transaction.
@@ -148,75 +153,38 @@ class SantanderCreatePixResponse(TypedDict):
148153
transaction: SantanderTransaction
149154
tags: list[str]
150155
paymentValue: str
151-
status: Literal["READY_TO_PAY", "PENDING_VALIDATION", "REJECTED"]
156+
status: OrderStatusType
152157
dictCode: str | None
153158
dictCodeType: Literal["CPF", "CNPJ", "CELULAR", "EMAIL", "EVP"] | None
154159
beneficiary: SantanderBeneficiary | None
155160

156161

157-
class SantanderPixStatusResponse(TypedDict):
158-
"""
159-
Resposta de transações pix do Santander tanto pelo PATCH quanto pelo GET.
160-
- Os campos mais importantes aqui são o id, status, paymentValue e transaction.
162+
class BankAccountDict(TypedDict):
163+
agencia: str
164+
conta: str
165+
conta_dv: str
166+
tipo_conta: Literal["checking", "savings", "salary", "payment"]
167+
document_number: str
168+
bank_code_compe: str | None
169+
bank_code_ispb: str | None
161170

162-
### Status
163-
'status' de sucesso:
164-
- PAYED é o status de pagamento efetuado com sucesso.
165-
- PENDING_CONFIRMATION é o status de pendência de confirmação do pagamento, esse status
166-
pode acontecer caso alguma câmara de compensação fique fora do ar no exato momento da
167-
chamada das APIs, se o banco recebedor está avaliando a transação, se o cliente ficar sem saldo
168-
em conta, entre outros casos.
169-
170-
'status' de erro:
171-
- REJECTED é o status de rejeição do pagamento.
172171

173-
### Campos de retorno opcionais (meramente informativos, que inclusive são enviados por nós):
174-
- Caso seja um pagamento por chave, o campo dictCode e dictCodeType.
175-
- O mesmo vale para o beneficiary, caso seja um pagamento por beneficiário.
176-
"""
177-
178-
id: str
179-
workspaceId: str
180-
debitAccount: str
181-
remittanceInformation: str
182-
nominalValue: str
183-
totalValue: str
184-
payer: SantanderPayer
185-
transaction: SantanderTransaction
186-
tags: list[str]
187-
paymentValue: str
188-
status: Literal[
189-
"READY_TO_PAY",
190-
"PENDING_VALIDATION",
191-
"PAYED",
192-
"PENDING_CONFIRMATION",
193-
"REJECTED",
194-
]
195-
dictCode: str | None
196-
dictCodeType: Literal["CPF", "CNPJ", "CELULAR", "EMAIL", "EVP"] | None
197-
beneficiary: SantanderBeneficiary | None
172+
class ReceiverDataDict(BankAccountDict):
173+
name: str
198174

199175

200176
class BeneficiaryDataDict(TypedDict):
201177
"""Dados do beneficiário para transferência PIX"""
202178

203-
class BankAccountDict(TypedDict):
204-
agencia: str
205-
conta: str
206-
conta_dv: str
207-
tipo_conta: Literal["checking", "savings", "salary", "payment"]
208-
document_number: str
209-
bank_code_compe: str | None
210-
bank_code_ispb: str | None
211-
212-
class ReceiverDataDict(BankAccountDict):
213-
name: str
214-
215179
"Dados do recebedor para transferência PIX"
216180
bank_account: BankAccountDict
217181
recebedor: ReceiverDataDict
218182

219183

184+
SantanderPixResponse = SantanderTransferResponse | SantanderAPIErrorResponse
185+
186+
220187
class TransferPixResult(TypedDict):
221188
success: bool
222-
data: SantanderPixStatusResponse | None
189+
data: SantanderPixResponse | None
190+
error: str

0 commit comments

Comments
 (0)