Skip to content

Commit 31723e8

Browse files
authored
Merge pull request #7 from buserbrasil/refactor-global-configuration
refactor: replace global config with dependency injection
2 parents 13c4bc2 + 469f574 commit 31723e8

File tree

10 files changed

+192
-183
lines changed

10 files changed

+192
-183
lines changed

README.MD

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,26 @@ pip install santander-python-sdk
1414
## Uso
1515

1616
```python
17-
# Configure os dados de autenticação uma vez
18-
set_configuration(SantanderClientConfiguration(
17+
from decimal import Decimal
18+
from santander_client import SantanderApiClient, SantanderClientConfiguration
19+
20+
client = SantanderApiClient(SantanderClientConfiguration(
1921
client_id="client_id",
2022
client_secret="client_pk",
2123
cert="certificate_path",
2224
base_url="api_url"
2325
))
2426

25-
# Realizar um pix para uma chave
26-
transfer = transfer_pix_payment("[email protected]", 9.99, "pix de teste")
27-
28-
# Obter informações de um pix
29-
pix_info = get_transfer("id-da-transferencia-pix")
27+
# Realizar um PIX para uma chave
28+
transfer = transfer_pix_payment(
29+
client,
30+
pix_info="[email protected]", # PIX key
31+
value=Decimal(0.99),
32+
description="My first pix payment"
33+
)
3034

31-
# Uso em atualização
35+
pix_info = get_transfer(transfer["id"])
36+
# ...
3237
```
3338

3439
## Em desenvolvimento
@@ -48,4 +53,4 @@ Este projeto está licenciado sob a licença MIT. Veja o arquivo [LICENSE](LICEN
4853

4954
## Aviso Legal
5055

51-
Este projeto não é afiliado, endossado ou patrocinado pelo Santander.
56+
Este projeto não é afiliado, endossado ou patrocinado pelo Santander.

santander_client/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from santander_client.api_client.client import SantanderApiClient
2+
from santander_client.api_client.client_configuration import (
3+
SantanderClientConfiguration,
4+
)
5+
6+
__all__ = ["SantanderApiClient", "SantanderClientConfiguration"]
Lines changed: 0 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +0,0 @@
1-
import logging
2-
from santander_client.api_client.exceptions import (
3-
SantanderConfigurationException,
4-
SantanderWorkspaceException,
5-
)
6-
from santander_client.api_client.workspaces import get_first_workspace_id_of_type
7-
from santander_client.api_client.client import SantanderApiClient
8-
from santander_client.api_client.client_configuration import (
9-
SantanderClientConfiguration,
10-
)
11-
12-
logger = logging.getLogger("santanderLogger")
13-
14-
santander_client_configuration = None
15-
16-
17-
def set_configuration(configuration: SantanderClientConfiguration) -> None:
18-
if not isinstance(configuration, SantanderClientConfiguration):
19-
raise SantanderConfigurationException("Configuração inválida fornecida.")
20-
21-
global santander_client_configuration
22-
santander_client_configuration = configuration
23-
24-
25-
def get_client() -> SantanderApiClient:
26-
"""
27-
Creates and returns an instance of SantanderApiClient based on the provided configuration.
28-
"""
29-
if not santander_client_configuration:
30-
raise SantanderConfigurationException(
31-
"Configuração do client (SantanderClientConfiguration) não foi denida."
32-
)
33-
34-
santander_client_instance = SantanderApiClient(santander_client_configuration)
35-
36-
if not santander_client_configuration.workspace_id:
37-
workspace_id = get_first_workspace_id_of_type(
38-
santander_client_instance, "PAYMENTS"
39-
)
40-
if not workspace_id:
41-
raise SantanderWorkspaceException(
42-
"Conta sem configuração de workspace na configuração e na conta."
43-
)
44-
45-
logger.info(f"Workspace obtido e configurado com sucesso: {workspace_id}")
46-
santander_client_configuration.set_workspace_id(workspace_id)
47-
48-
return santander_client_instance

santander_client/api_client/client.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,25 @@
11
from datetime import datetime, timedelta
2+
import logging
23
from urllib.parse import urljoin
34
import requests
45

6+
from santander_client.api_client.workspaces import get_first_workspace_id_of_type
7+
58
from .helpers import get_status_code_description, try_parse_response_to_json
69

710
from .abstract_client import SantanderAbstractApiClient
811
from .client_configuration import SantanderClientConfiguration
9-
from .exceptions import SantanderRequestException, SantanderClientException
12+
from .exceptions import (
13+
SantanderRequestException,
14+
SantanderClientException,
15+
SantanderWorkspaceException,
16+
)
1017

1118
BEFORE_EXPIRE_TOKEN_SECONDS = timedelta(seconds=60)
1219
TOKEN_ENDPOINT = "/auth/oauth/v2/token"
1320

21+
logger = logging.getLogger(__name__)
22+
1423

1524
class SantanderApiClient(SantanderAbstractApiClient):
1625
"""
@@ -35,15 +44,25 @@ class SantanderApiClient(SantanderAbstractApiClient):
3544
"""
3645

3746
def __init__(self, config: SantanderClientConfiguration):
38-
if not isinstance(config, SantanderClientConfiguration):
39-
raise SantanderClientException("Objeto de autenticação inválido")
40-
4147
self.base_url = config.base_url.rstrip("/")
4248
self.config = config
4349
self.session = requests.Session()
4450
self.token = None
4551
self.token_expires_at = datetime.now()
4652

53+
self._set_default_workspace_id()
54+
55+
def _set_default_workspace_id(self):
56+
if not self.config.workspace_id:
57+
workspace_id = get_first_workspace_id_of_type(self, "PAYMENTS")
58+
if not workspace_id:
59+
raise SantanderWorkspaceException(
60+
"Conta sem configuração de workspace na configuração e na conta."
61+
)
62+
63+
logger.info(f"Workspace obtido e configurado com sucesso: {workspace_id}")
64+
self.config.set_workspace_id(workspace_id)
65+
4766
def get(self, endpoint: str, params: dict | None = None) -> dict:
4867
return self._request("GET", endpoint, params=params)
4968

santander_client/api_client/workspaces.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77
Para ter acesso ao sistema cliente e consumir as APIs, se faz necessário ter o cadastro de
88
uma ou mais Workspaces, sendo a Workspace a “porta de entrada” para ter o acesso ao Hub de
99
Pagamentos transacional. Rotas de pagamentos, geração de pix, etc, vão precisar do id do workspace.
10-
10+
1111
Existem os seguintes tipos de workspaces
1212
- PAYMENTS para o cliente que deseja fazer pagamentos próprios;
1313
- DIGITAL_CORBAN para o cliente que deseja fazer pagamentos de terceiros de maneira digital;
1414
- PHYSICAL_CORBAN para o cliente que deseja fazer pagamentos e ser correspondente bancário
1515
de maneira subestabelecida ou direta.
16-
16+
1717
### No nosso caso, o uso será para o tipo PAYMENTS.
1818
"""
1919
WorkspaceType = Literal["PHYSICAL_CORBAN", "PAYMENTS", "DIGITAL_CORBAN"]

santander_client/pix.py

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from time import sleep
44
from typing import List, Literal, cast
55

6-
from santander_client.api_client import get_client
6+
from santander_client.api_client.client import SantanderApiClient
77
from santander_client.api_client.exceptions import (
88
SantanderClientException,
99
SantanderRejectedTransactionException,
@@ -43,7 +43,11 @@
4343

4444

4545
def transfer_pix_payment(
46-
pix_info: str | BeneficiaryDataDict, value: D, description: str, tags=[]
46+
client: SantanderApiClient,
47+
pix_info: str | BeneficiaryDataDict,
48+
value: D,
49+
description: str,
50+
tags: list[str] = [],
4751
) -> TransferPixResult:
4852
"""Realiza uma transferência PIX para uma chave PIX ou para um beneficiário
4953
- Se for informado uma chave PIX, o valor deve ser uma string com a chave CPF, CNPJ, EMAIL, CELULAR ou chave aleatória
@@ -65,7 +69,7 @@ def transfer_pix_payment(
6569
)
6670

6771
create_pix_response = _request_create_pix_payment(
68-
pix_info, value, description, tags
72+
client, pix_info, value, description, tags
6973
)
7074
pix_id = create_pix_response.get("id")
7175
logger.info("Santander - PIX criado com sucesso: {pix_id}")
@@ -81,7 +85,7 @@ def transfer_pix_payment(
8185
"Status do pagamento não retornado na criação"
8286
)
8387

84-
confirm_response = _confirm_pix_payment(pix_id, value, payment_status)
88+
confirm_response = _confirm_pix_payment(client, pix_id, value, payment_status)
8589

8690
return {"success": True, "data": confirm_response, "error": ""}
8791
except Exception as e:
@@ -91,17 +95,18 @@ def transfer_pix_payment(
9195

9296

9397
def _pix_payment_status_polling(
98+
client: SantanderApiClient,
9499
pix_id: str,
95100
until_status: List[str],
96101
context: Literal["CREATE", "CONFIRM"],
97102
max_attempts: int,
98103
) -> SantanderPixResponse:
99-
response = _request_pix_payment_status(pix_id, context)
104+
response = _request_pix_payment_status(client, pix_id, context)
100105
if response.get("status") in until_status:
101106
return response
102107

103108
for attempt in range(max_attempts - 1):
104-
response = _request_pix_payment_status(pix_id, context)
109+
response = _request_pix_payment_status(client, pix_id, context)
105110
payment_status = response.get("status")
106111
logger.info(
107112
f"Santander - Verificando status do pagamento PIX por polling: {pix_id} - {payment_status}"
@@ -122,7 +127,7 @@ def _pix_payment_status_polling(
122127

123128

124129
def _confirm_pix_payment(
125-
pix_id: str, value: D, payment_status: OrderStatusType
130+
client: SantanderApiClient, pix_id: str, value: D, payment_status: OrderStatusType
126131
) -> SantanderPixResponse:
127132
"""Confirma o pagamento PIX, realizando polling até que o status seja PAYED ou permaneça PENDING_CONFIRMATION.
128133
@@ -134,19 +139,20 @@ def _confirm_pix_payment(
134139
if payment_status != CreateOrderStatus.READY_TO_PAY:
135140
logger.info(f"Santander - PIX não está pronto para pagamento: {pix_id}")
136141
_pix_payment_status_polling(
142+
client,
137143
pix_id=pix_id,
138144
until_status=[CreateOrderStatus.READY_TO_PAY],
139145
context="CREATE",
140146
max_attempts=MAX_UPDATE_STATUS_ATTEMPTS,
141147
)
142148

143149
try:
144-
confirm_response = _request_confirm_pix_payment(pix_id, value)
150+
confirm_response = _request_confirm_pix_payment(client, pix_id, value)
145151
except SantanderRequestException as e:
146152
logger.error(
147153
f"Santander - Erro ao confirmar pagamento PIX: {str(e)}, {pix_id}, verificando status atual"
148154
)
149-
confirm_response = _request_pix_payment_status(pix_id, "CONFIRM")
155+
confirm_response = _request_pix_payment_status(client, pix_id, "CONFIRM")
150156

151157
if confirm_response.get("status") == ConfirmOrderStatus.PAYED:
152158
return confirm_response
@@ -158,6 +164,7 @@ def _confirm_pix_payment(
158164

159165
try:
160166
confirm_response = _pix_payment_status_polling(
167+
client,
161168
pix_id=pix_id,
162169
until_status=[ConfirmOrderStatus.PAYED],
163170
context="CONFIRM",
@@ -177,7 +184,11 @@ def _confirm_pix_payment(
177184

178185

179186
def _request_create_pix_payment(
180-
pix_info: BeneficiaryDataDict | str, value: D, description: str, tags=[]
187+
client: SantanderApiClient,
188+
pix_info: BeneficiaryDataDict | str,
189+
value: D,
190+
description: str,
191+
tags: list[str] = [],
181192
) -> SantanderPixResponse:
182193
"""Cria uma ordem de pagamento. Caso o status seja REJECTED, a exceção SantanderRejectedTransactionException é lançada.
183194
Regra de negócio aqui: pagamento por beneficiário na request deve ser informado o bank_code ou ispb, nunca os dois."""
@@ -219,13 +230,14 @@ def _request_create_pix_payment(
219230
else:
220231
raise SantanderValueErrorException("Chave PIX ou Beneficiário não informado")
221232

222-
client = get_client()
223233
response = cast(SantanderPixResponse, client.post(PIX_ENDPOINT, data=data))
224234
_check_for_rejected_exception(response, "Criação do pagamento PIX")
225235
return response
226236

227237

228-
def _request_confirm_pix_payment(pix_payment_id: str, value: D) -> SantanderPixResponse:
238+
def _request_confirm_pix_payment(
239+
client: SantanderApiClient, pix_payment_id: str, value: D
240+
) -> SantanderPixResponse:
229241
"""Confirma o pagamento PIX através do PATCH e status AUTHORIZED
230242
O HTTP code de sucesso é 200, mesmo que o status seja REJECTED
231243
Caso o status seja REJECTED, a exceção SantanderRejectedTransactionException é lançada
@@ -236,7 +248,6 @@ def _request_confirm_pix_payment(pix_payment_id: str, value: D) -> SantanderPixR
236248
if not value:
237249
raise SantanderValueErrorException("Valor não informado")
238250

239-
client = get_client()
240251
data = {
241252
"status": "AUTHORIZED",
242253
"paymentValue": truncate_value(value),
@@ -249,7 +260,7 @@ def _request_confirm_pix_payment(pix_payment_id: str, value: D) -> SantanderPixR
249260

250261
@retry_one_time_on_request_exception
251262
def _request_pix_payment_status(
252-
pix_payment_id: str, step_description: str
263+
client: SantanderApiClient, pix_payment_id: str, step_description: str
253264
) -> SantanderPixResponse:
254265
"""
255266
Retorna o estado atual do processamento de um pagamento PIX
@@ -259,7 +270,6 @@ def _request_pix_payment_status(
259270
if not pix_payment_id:
260271
raise SantanderValueErrorException("pix_payment_id não informado")
261272

262-
client = get_client()
263273
response = client.get(f"{PIX_ENDPOINT}/{pix_payment_id}")
264274
response = cast(SantanderPixResponse, response)
265275
_check_for_rejected_exception(response, step_description)

tests/conftest.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import pytest
2+
3+
from santander_client.api_client.client import SantanderApiClient
4+
from santander_client.api_client.client_configuration import (
5+
SantanderClientConfiguration,
6+
)
7+
8+
9+
@pytest.fixture
10+
def api_client():
11+
return SantanderApiClient(
12+
SantanderClientConfiguration(
13+
client_id="test_client_id",
14+
client_secret="test_client_secret",
15+
cert="certificate_path",
16+
base_url="https://trust-sandbox.api.santander.com.br",
17+
workspace_id="8e33d56c-204f-461e-aebe-08baaab6479e",
18+
)
19+
)

tests/test_init.py

Lines changed: 0 additions & 34 deletions
This file was deleted.

0 commit comments

Comments
 (0)