Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions barte/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,49 @@ class Payment:
fraudData: Optional[FraudData]


@dataclass
class ThreeDSecureBrowser:
ip: str
userAgent: str
acceptHeader: str
language: str
colorDepth: int
screenHeight: int
screenWidth: int
timeZoneOffset: str
javaEnabled: bool
javaScriptEnabled: bool


@dataclass
class ThreeDSecureAddress:
city: str
country: str
streetNumber: str
zipCode: str
state: str
street: str


@dataclass
class ThreeDSecureCardHolder:
email: str
mobilePhone: str


@dataclass
class ThreeDSecure:
dataOnly: bool
requiresLiabilityShift: bool
Comment thread
moniveloso marked this conversation as resolved.
setupId: str
redirectURL: str
requestorURL: str
browser: ThreeDSecureBrowser
billingAddress: ThreeDSecureAddress
shippingAddress: ThreeDSecureAddress
cardHolder: ThreeDSecureCardHolder
Comment thread
moniveloso marked this conversation as resolved.


@dataclass
class SubSellerPayment:
idSubSeller: int
Expand Down Expand Up @@ -312,6 +355,7 @@ class OrderPayload:
description: Optional[str]
subSellerPaymentRequest: Optional[SubSellerPaymentRequest]
metadata: Optional[List[Metadata]]
threeDSecure: Optional[ThreeDSecure] = None


@dataclass
Expand Down
133 changes: 133 additions & 0 deletions tests/test_client.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from dataclasses import asdict
from datetime import datetime
from decimal import Decimal
from unittest.mock import Mock, patch
Expand Down Expand Up @@ -27,6 +28,12 @@
CreateSellerResponse,
InstallmentOption,
Order,
OrderPayload,
Payment,
ThreeDSecure,
ThreeDSecureAddress,
ThreeDSecureBrowser,
ThreeDSecureCardHolder,
)


Expand Down Expand Up @@ -487,6 +494,132 @@ def test_create_order(self, mock_request, barte_client, mock_order_response):
json=order_data,
)

@patch("barte.client.requests.Session.request")
def test_create_order_with_three_d_secure_typed_payload(
self, mock_request, barte_client, mock_order_response
):
"""Test create_order sends threeDSecure when provided in OrderPayload."""
mock_request.return_value.json.return_value = mock_order_response
mock_request.return_value.raise_for_status = Mock()

order_payload = OrderPayload(
title="Compra Exemplo",
uuidBuyer="71d12215-267a-4620-9b17-0715c84d23bd",
startDate="2025-04-16",
value=130,
installments=3,
payment=Payment(
method="CREDIT_CARD_EARLY_SELLER",
brand="mastercard",
cardToken="efde9a25-76f9-4d0a-bfbc-1abbdbd8bc07",
capture=None,
integrationOrderId=None,
card=None,
fraudData=None,
),
attemptReference="123e4567-e89b-12d3-a456-426614174000",
urlCallBack="https://webhook.site/unique-id",
description="Descrição da compra",
subSellerPaymentRequest=None,
metadata=None,
threeDSecure=ThreeDSecure(
dataOnly=False,
requiresLiabilityShift=False,
setupId="e453da0b-b6a1-4c9a-8820-f2da23b3ffb7",
redirectURL="http://localhost:3000/checkout.html",
requestorURL="http://localhost:3000",
browser=ThreeDSecureBrowser(
ip="127.0.0.1",
userAgent="Mozilla/5.0",
acceptHeader="text/html,application/xhtml+xml",
language="pt-BR",
colorDepth=24,
screenHeight=1080,
screenWidth=1920,
timeZoneOffset="-180",
javaEnabled=False,
javaScriptEnabled=True,
),
billingAddress=ThreeDSecureAddress(
city="Uberlândia",
country="BR",
streetNumber="123",
zipCode="38411999",
state="Minas Gerais",
street="Rua Exemplo",
),
shippingAddress=ThreeDSecureAddress(
city="Uberlândia",
country="BR",
streetNumber="123",
zipCode="38411999",
state="Minas Gerais",
street="Rua Exemplo",
),
cardHolder=ThreeDSecureCardHolder(
email="teste@teste.com",
mobilePhone="24999329393",
),
),
)

order = barte_client.create_order(order_payload)

assert isinstance(order, Order)

mock_request.assert_called_once_with(
"POST",
f"{barte_client.base_url}/v2/orders",
params=None,
json=asdict(order_payload),
)

@patch("barte.client.requests.Session.request")
def test_create_order_with_three_d_secure_error(
self, mock_request, barte_client, mock_3ds_error_response
):
"""Test create_order returns BarteError when API returns 3DS invalid data."""
mock_request.return_value.json.return_value = mock_3ds_error_response
mock_request.return_value.raise_for_status = Mock()

order_data = {
"startDate": "2025-04-16",
"value": 130,
"installments": 3,
"title": "Compra Exemplo",
"description": "Descrição da compra",
"payment": {
"method": "CREDIT_CARD_EARLY_SELLER",
"card": {
"cardToken": "efde9a25-76f9-4d0a-bfbc-1abbdbd8bc07",
"cvv": "950",
},
},
"threeDSecure": {
"setupId": "e453da0b-b6a1-4c9a-8820-f2da23b3ffb7",
"dataOnly": False,
"requiresLiabilityShift": False,
},
"uuidBuyer": "71d12215-267a-4620-9b17-0715c84d23bd",
}

with pytest.raises(BarteError) as exc_info:
barte_client.create_order(order_data)

assert exc_info.value.code == "3DS-0001"
assert exc_info.value.message == "Dados 3DS inválidos"
assert (
exc_info.value.action == "Verifique os dados informados e tente novamente"
)
assert exc_info.value.charge_uuid is None

mock_request.assert_called_once_with(
"POST",
f"{barte_client.base_url}/v2/orders",
params=None,
json=order_data,
)

@patch("barte.client.requests.Session.request")
def test_create_order_with_invalid_card(
self, mock_request, barte_client, mock_order_error_response
Expand Down
Loading