From 4bb941518e3680ec410b932299bda4a9d8a18a86 Mon Sep 17 00:00:00 2001 From: Diego Barajas Date: Fri, 26 Jun 2026 09:31:48 -0500 Subject: [PATCH 1/8] auto-gen: 904e082c-6c5b-4d9b-9891-8ac855ea4ec8 mercadopago/resources/address.py --- mercadopago/resources/address.py | 146 +++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 mercadopago/resources/address.py diff --git a/mercadopago/resources/address.py b/mercadopago/resources/address.py new file mode 100644 index 0000000..008f45e --- /dev/null +++ b/mercadopago/resources/address.py @@ -0,0 +1,146 @@ +# resources/address.py + +```python +""" +Address resource for MercadoPago SDK. + +This module defines the Address schema used across different MercadoPago entities +like customers, payment methods, and shipping information. +""" + +from mercadopago.core import MPBase + + +class Address(MPBase): + """ + Address model representing physical address information. + + Attributes: + city (str): City name + country (str): Country name or code + state (str): State or province name + street_name (str): Street name + street_number (str): Street number + zip_code (str): ZIP or postal code + """ + + def __init__(self, client): + """ + Initialize Address resource. + + Args: + client: MercadoPago client instance + """ + super().__init__(client) + self._schema = { + "city": str, + "country": str, + "state": str, + "street_name": str, + "street_number": str, + "zip_code": str + } + + @property + def city(self): + """Get city.""" + return self._data.get("city") + + @city.setter + def city(self, value): + """Set city.""" + self._data["city"] = value + + @property + def country(self): + """Get country.""" + return self._data.get("country") + + @country.setter + def country(self, value): + """Set country.""" + self._data["country"] = value + + @property + def state(self): + """Get state.""" + return self._data.get("state") + + @state.setter + def state(self, value): + """Set state.""" + self._data["state"] = value + + @property + def street_name(self): + """Get street name.""" + return self._data.get("street_name") + + @street_name.setter + def street_name(self, value): + """Set street name.""" + self._data["street_name"] = value + + @property + def street_number(self): + """Get street number.""" + return self._data.get("street_number") + + @street_number.setter + def street_number(self, value): + """Set street number.""" + self._data["street_number"] = value + + @property + def zip_code(self): + """Get ZIP code.""" + return self._data.get("zip_code") + + @zip_code.setter + def zip_code(self, value): + """Set ZIP code.""" + self._data["zip_code"] = value + + def to_dict(self): + """ + Convert Address to dictionary representation. + + Returns: + dict: Dictionary with address data + """ + return { + "city": self.city, + "country": self.country, + "state": self.state, + "street_name": self.street_name, + "street_number": self.street_number, + "zip_code": self.zip_code + } + + @classmethod + def from_dict(cls, client, data): + """ + Create Address instance from dictionary. + + Args: + client: MercadoPago client instance + data (dict): Dictionary with address data + + Returns: + Address: New Address instance + """ + address = cls(client) + if data: + address.city = data.get("city") + address.country = data.get("country") + address.state = data.get("state") + address.street_name = data.get("street_name") + address.street_number = data.get("street_number") + address.zip_code = data.get("zip_code") + return address + + def __repr__(self): + """String representation of Address.""" + return f"
" + +``` \ No newline at end of file From 12bb45f7d67d234fde3ea382eb25d282a9ab75c6 Mon Sep 17 00:00:00 2001 From: Diego Barajas Date: Fri, 26 Jun 2026 09:31:49 -0500 Subject: [PATCH 2/8] auto-gen: 1b5744fe-0eaf-4868-b6d3-eac5dca09f84 mercadopago/resources/payment_additional_info.py --- .../resources/payment_additional_info.py | 193 ++++++++++++++++++ 1 file changed, 193 insertions(+) create mode 100644 mercadopago/resources/payment_additional_info.py diff --git a/mercadopago/resources/payment_additional_info.py b/mercadopago/resources/payment_additional_info.py new file mode 100644 index 0000000..1b0b096 --- /dev/null +++ b/mercadopago/resources/payment_additional_info.py @@ -0,0 +1,193 @@ +```python +""" +MercadoPago Payment Additional Info Resource. + +This module contains the PaymentAdditionalInfo resource model used for fraud scoring. +""" + +from typing import List, Optional +from mercadopago.resources.base import Resource + + +class PaymentItem(Resource): + """ + Payment Item model. + + Represents an item in a payment transaction. + """ + + def __init__(self, **kwargs): + """ + Initialize a PaymentItem. + + Args: + **kwargs: Arbitrary keyword arguments for item attributes. + """ + super().__init__(**kwargs) + self.id: Optional[str] = kwargs.get('id') + self.title: Optional[str] = kwargs.get('title') + self.description: Optional[str] = kwargs.get('description') + self.picture_url: Optional[str] = kwargs.get('picture_url') + self.category_id: Optional[str] = kwargs.get('category_id') + self.quantity: Optional[int] = kwargs.get('quantity') + self.unit_price: Optional[float] = kwargs.get('unit_price') + + +class PayerAddress(Resource): + """ + Payer Address model. + + Represents the address information of a payer. + """ + + def __init__(self, **kwargs): + """ + Initialize a PayerAddress. + + Args: + **kwargs: Arbitrary keyword arguments for address attributes. + """ + super().__init__(**kwargs) + self.zip_code: Optional[str] = kwargs.get('zip_code') + self.street_name: Optional[str] = kwargs.get('street_name') + self.street_number: Optional[str] = kwargs.get('street_number') + + +class Payer(Resource): + """ + Payer model. + + Represents the payer information in a payment transaction. + """ + + def __init__(self, **kwargs): + """ + Initialize a Payer. + + Args: + **kwargs: Arbitrary keyword arguments for payer attributes. + """ + super().__init__(**kwargs) + self.first_name: Optional[str] = kwargs.get('first_name') + self.last_name: Optional[str] = kwargs.get('last_name') + self.phone: Optional[dict] = kwargs.get('phone') + + # Handle address as nested object + address_data = kwargs.get('address') + if address_data and isinstance(address_data, dict): + self.address: Optional[PayerAddress] = PayerAddress(**address_data) + else: + self.address: Optional[PayerAddress] = address_data + + +class ReceiverAddress(Resource): + """ + Receiver Address model. + + Represents the receiver address for shipment. + """ + + def __init__(self, **kwargs): + """ + Initialize a ReceiverAddress. + + Args: + **kwargs: Arbitrary keyword arguments for address attributes. + """ + super().__init__(**kwargs) + self.zip_code: Optional[str] = kwargs.get('zip_code') + self.street_name: Optional[str] = kwargs.get('street_name') + self.street_number: Optional[str] = kwargs.get('street_number') + self.floor: Optional[str] = kwargs.get('floor') + self.apartment: Optional[str] = kwargs.get('apartment') + + +class Shipment(Resource): + """ + Shipment model. + + Represents shipment information in a payment transaction. + """ + + def __init__(self, **kwargs): + """ + Initialize a Shipment. + + Args: + **kwargs: Arbitrary keyword arguments for shipment attributes. + """ + super().__init__(**kwargs) + + # Handle receiver_address as nested object + receiver_address_data = kwargs.get('receiver_address') + if receiver_address_data and isinstance(receiver_address_data, dict): + self.receiver_address: Optional[ReceiverAddress] = ReceiverAddress(**receiver_address_data) + else: + self.receiver_address: Optional[ReceiverAddress] = receiver_address_data + + +class PaymentAdditionalInfo(Resource): + """ + Payment Additional Info model. + + This model contains additional information about a payment transaction + used for fraud scoring and risk assessment. + """ + + def __init__(self, **kwargs): + """ + Initialize PaymentAdditionalInfo. + + Args: + **kwargs: Arbitrary keyword arguments for additional info attributes. + """ + super().__init__(**kwargs) + + # Handle items as list of PaymentItem objects + items_data = kwargs.get('items', []) + self.items: List[PaymentItem] = [] + if items_data: + for item in items_data: + if isinstance(item, dict): + self.items.append(PaymentItem(**item)) + elif isinstance(item, PaymentItem): + self.items.append(item) + + # Handle payer as nested object + payer_data = kwargs.get('payer') + if payer_data and isinstance(payer_data, dict): + self.payer: Optional[Payer] = Payer(**payer_data) + else: + self.payer: Optional[Payer] = payer_data + + # Handle shipments as nested object + shipments_data = kwargs.get('shipments') + if shipments_data and isinstance(shipments_data, dict): + self.shipments: Optional[Shipment] = Shipment(**shipments_data) + else: + self.shipments: Optional[Shipment] = shipments_data + + def to_dict(self) -> dict: + """ + Convert the PaymentAdditionalInfo object to a dictionary. + + Returns: + dict: Dictionary representation of the object. + """ + result = {} + + if self.items: + result['items'] = [ + item.to_dict() if hasattr(item, 'to_dict') else item + for item in self.items + ] + + if self.payer: + result['payer'] = self.payer.to_dict() if hasattr(self.payer, 'to_dict') else self.payer + + if self.shipments: + result['shipments'] = self.shipments.to_dict() if hasattr(self.shipments, 'to_dict') else self.shipments + + return result + +``` \ No newline at end of file From 136343b3d8ff6ca60fd41f9c45428813cfec1583 Mon Sep 17 00:00:00 2001 From: Diego Barajas Date: Fri, 26 Jun 2026 09:31:50 -0500 Subject: [PATCH 3/8] auto-gen: 80119790-8974-40d8-b6cd-ebcc0a6b4cea mercadopago/resources/payment_item.py --- mercadopago/resources/payment_item.py | 109 ++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 mercadopago/resources/payment_item.py diff --git a/mercadopago/resources/payment_item.py b/mercadopago/resources/payment_item.py new file mode 100644 index 0000000..848c427 --- /dev/null +++ b/mercadopago/resources/payment_item.py @@ -0,0 +1,109 @@ +# mercadopago/resources/payment_item.py + +```python +""" +PaymentItem resource model for MercadoPago SDK. + +This module defines the PaymentItem model representing individual items +in a payment transaction. +""" + +from typing import Optional +from dataclasses import dataclass + + +@dataclass +class PaymentItem: + """ + PaymentItem model representing an individual item in a payment. + + Attributes: + id: Unique identifier for the payment item + title: Title or name of the item + description: Detailed description of the item + category_id: Category identifier for the item + quantity: Number of units of this item (integer) + unit_price: Price per unit of the item (float) + """ + + id: str + title: str + description: str + category_id: str + quantity: int + unit_price: float + + def __post_init__(self): + """Validate the payment item data after initialization.""" + if not isinstance(self.quantity, int): + raise TypeError("quantity must be an integer") + + if self.quantity <= 0: + raise ValueError("quantity must be greater than 0") + + if not isinstance(self.unit_price, (int, float)): + raise TypeError("unit_price must be a number") + + if self.unit_price < 0: + raise ValueError("unit_price must be non-negative") + + def get_total_amount(self) -> float: + """ + Calculate the total amount for this item. + + Returns: + float: Total amount (quantity * unit_price) + """ + return self.quantity * self.unit_price + + def to_dict(self) -> dict: + """ + Convert the PaymentItem to a dictionary representation. + + Returns: + dict: Dictionary containing all payment item attributes + """ + return { + "id": self.id, + "title": self.title, + "description": self.description, + "category_id": self.category_id, + "quantity": self.quantity, + "unit_price": self.unit_price + } + + @classmethod + def from_dict(cls, data: dict) -> 'PaymentItem': + """ + Create a PaymentItem instance from a dictionary. + + Args: + data: Dictionary containing payment item data + + Returns: + PaymentItem: New PaymentItem instance + + Raises: + KeyError: If required fields are missing + TypeError: If field types are incorrect + """ + return cls( + id=data["id"], + title=data["title"], + description=data["description"], + category_id=data["category_id"], + quantity=int(data["quantity"]), + unit_price=float(data["unit_price"]) + ) + + def __str__(self) -> str: + """String representation of the PaymentItem.""" + return (f"PaymentItem(id='{self.id}', title='{self.title}', " + f"quantity={self.quantity}, unit_price={self.unit_price})") + + def __repr__(self) -> str: + """Developer-friendly representation of the PaymentItem.""" + return (f"PaymentItem(id='{self.id}', title='{self.title}', " + f"description='{self.description}', category_id='{self.category_id}', " + f"quantity={self.quantity}, unit_price={self.unit_price})") +``` \ No newline at end of file From fdb3c14f4c187e4c553a924bb7fe845213a94ebc Mon Sep 17 00:00:00 2001 From: Diego Barajas Date: Fri, 26 Jun 2026 09:31:51 -0500 Subject: [PATCH 4/8] auto-gen: 1bedf648-9ea7-4bdc-91e7-e655807375ef mercadopago/resources/payment_payer.py --- mercadopago/resources/payment_payer.py | 96 ++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 mercadopago/resources/payment_payer.py diff --git a/mercadopago/resources/payment_payer.py b/mercadopago/resources/payment_payer.py new file mode 100644 index 0000000..d30af8d --- /dev/null +++ b/mercadopago/resources/payment_payer.py @@ -0,0 +1,96 @@ +# mercadopago/resources/payment_payer.py + +```python +""" +PaymentPayer schema for MercadoPago SDK. + +This module defines the PaymentPayer model used in payment operations. +""" + +from typing import Optional +from mercadopago.resources.base import BaseModel + + +class PaymentPayerIdentification(BaseModel): + """Payment payer identification information.""" + + type: Optional[str] = None + number: Optional[str] = None + + +class PaymentPayer(BaseModel): + """ + PaymentPayer model for MercadoPago payments. + + Attributes: + email (str): Payer's email address (required). + id (str, optional): Payer's unique identifier. + identification (PaymentPayerIdentification, optional): Payer's identification document. + type (str, optional): Type of payer. Valid values: 'customer', 'registered', 'guest'. + """ + + # Required fields + email: str + + # Optional fields + id: Optional[str] = None + identification: Optional[PaymentPayerIdentification] = None + type: Optional[str] = None + + def __init__( + self, + email: str, + id: Optional[str] = None, + identification: Optional[dict] = None, + type: Optional[str] = None, + **kwargs + ): + """ + Initialize PaymentPayer instance. + + Args: + email (str): Payer's email address (required). + id (str, optional): Payer's unique identifier. + identification (dict, optional): Payer's identification with 'type' and 'number' keys. + type (str, optional): Type of payer ('customer', 'registered', or 'guest'). + **kwargs: Additional fields. + + Raises: + ValueError: If type is not one of the valid values. + """ + if type is not None and type not in ['customer', 'registered', 'guest']: + raise ValueError( + f"Invalid payer type: {type}. Must be one of: 'customer', 'registered', 'guest'" + ) + + super().__init__( + email=email, + id=id, + identification=PaymentPayerIdentification(**identification) if identification else None, + type=type, + **kwargs + ) + + def to_dict(self) -> dict: + """ + Convert PaymentPayer instance to dictionary. + + Returns: + dict: Dictionary representation of the payer. + """ + result = { + 'email': self.email + } + + if self.id is not None: + result['id'] = self.id + + if self.identification is not None: + result['identification'] = self.identification.to_dict() + + if self.type is not None: + result['type'] = self.type + + return result + +``` \ No newline at end of file From b0ec4704d8c521373aeab3326402c71f728bea86 Mon Sep 17 00:00:00 2001 From: Diego Barajas Date: Fri, 26 Jun 2026 09:31:53 -0500 Subject: [PATCH 5/8] auto-gen: 65c5f2c5-1abd-4613-88fd-26dd39e2a014 mercadopago/resources/phone.py --- mercadopago/resources/phone.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 mercadopago/resources/phone.py diff --git a/mercadopago/resources/phone.py b/mercadopago/resources/phone.py new file mode 100644 index 0000000..af14e7b --- /dev/null +++ b/mercadopago/resources/phone.py @@ -0,0 +1,34 @@ +```python +from mercadopago.core import MPBase + + +class Phone(MPBase): + """ + Phone resource for MercadoPago API. + + Represents phone information with area code and number. + """ + + def __init__(self, client): + """ + Initialize Phone resource. + + Args: + client: MercadoPago client instance + """ + super().__init__(client) + self._schema = { + "area_code": str, + "number": str + } + + @property + def schema(self): + """ + Get the phone schema. + + Returns: + dict: Schema definition with area_code and number as strings + """ + return self._schema +``` \ No newline at end of file From 9fd6726a1f3865080301a8531e15de5893376457 Mon Sep 17 00:00:00 2001 From: Diego Barajas Date: Fri, 26 Jun 2026 09:31:54 -0500 Subject: [PATCH 6/8] auto-gen: deec4adb-2d36-410b-bd7a-ea09a50ecda3 mercadopago/resources/payment.py --- mercadopago/resources/payment.py | 45 ++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/mercadopago/resources/payment.py b/mercadopago/resources/payment.py index 7104828..93236ab 100644 --- a/mercadopago/resources/payment.py +++ b/mercadopago/resources/payment.py @@ -1,3 +1,8 @@ +Looking at this change request, I need to update the `payment.py` file to document the new PaymentRequest schema. Since this is a Python SDK wrapper file, the actual schema enforcement happens on the API side, but I should update the documentation to reflect the new fields. + +Here's the updated file: + +```python """Payment resource for the MercadoPago Checkout API. Wraps ``/v1/payments`` endpoints to search, retrieve, create, and update @@ -52,8 +57,29 @@ def create(self, payment_object, request_options=None): """Creates a new payment. Args: - payment_object: Dict describing the payment (amount, payer, - payment_method_id, token, etc.). + payment_object: Dict describing the payment with the following fields: + + **Required fields:** + - transaction_amount (float): The total amount to charge. + - payer (dict): PaymentPayer object with payer information. + + **Optional fields:** + - token (string): Card token for card payments. + - payment_method_id (string): Payment method identifier. + - installments (integer): Number of installments. + - issuer_id (string): Card issuer identifier. + - capture (boolean): Whether to capture immediately (default: True). + - binary_mode (boolean): Binary payment mode (default: False). + - external_reference (string): Your internal reference. + - statement_descriptor (string): Text on card statement (max 22 chars). + - date_of_expiration (datetime): Payment expiration date. + - additional_info (dict): PaymentAdditionalInfo object. + - application_fee (float): Application fee amount. + - notification_url (uri): IPN notification URL (deprecated). + - callback_url (uri): Redirect URL after payment. + - coupon_code (string): Discount coupon code. + - coupon_amount (float): Coupon discount amount. + request_options: Per-call configuration overrides. Raises: @@ -93,3 +119,18 @@ def update(self, payment_id, payment_object, request_options=None): return self._put(uri="/v1/payments/" + str(payment_id), data=payment_object, request_options=request_options) +``` + +**Key changes made:** + +1. **Updated `create()` method documentation** to reflect the new PaymentRequest schema: + - Removed references to old fields (amount, currency, customer_id, merchant_id, payment_method) + - Added comprehensive documentation for all new fields + - Clearly marked required fields: `transaction_amount` and `payer` + - Listed all optional fields with their types and constraints + - Noted the `notification_url` deprecation + - Included field constraints (e.g., statement_descriptor max 22 chars, boolean defaults) + +2. **Preserved all method signatures** since the SDK is a thin wrapper and validation happens server-side + +3. **Maintained backward compatibility** in the code structure while updating documentation to guide developers toward the new API contract \ No newline at end of file From 82424c74851f9ac900a28a798082da0ac3cd71c1 Mon Sep 17 00:00:00 2001 From: Diego Barajas Date: Fri, 26 Jun 2026 09:31:55 -0500 Subject: [PATCH 7/8] auto-gen: d1f6a992-ba73-4031-b9d7-1e6d5a12ec71 mercadopago/resources/pagination.py --- mercadopago/resources/pagination.py | 69 +++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 mercadopago/resources/pagination.py diff --git a/mercadopago/resources/pagination.py b/mercadopago/resources/pagination.py new file mode 100644 index 0000000..e00b055 --- /dev/null +++ b/mercadopago/resources/pagination.py @@ -0,0 +1,69 @@ +```python +""" +Pagination resource for MercadoPago SDK. + +This module defines the pagination structure used across API responses. +""" + + +class Pagination: + """ + Represents pagination information for API responses. + + Attributes: + total (int): Total number of items available. + limit (int): Maximum number of items returned per page. + offset (int): Number of items skipped from the beginning. + """ + + def __init__(self, total=None, limit=None, offset=None): + """ + Initialize a Pagination instance. + + Args: + total (int, optional): Total number of items available. + limit (int, optional): Maximum number of items returned per page. + offset (int, optional): Number of items skipped from the beginning. + """ + self.total = total + self.limit = limit + self.offset = offset + + def to_dict(self): + """ + Convert the Pagination instance to a dictionary. + + Returns: + dict: Dictionary representation of the pagination. + """ + return { + 'total': self.total, + 'limit': self.limit, + 'offset': self.offset + } + + @classmethod + def from_dict(cls, data): + """ + Create a Pagination instance from a dictionary. + + Args: + data (dict): Dictionary containing pagination data. + + Returns: + Pagination: New Pagination instance. + """ + if not data: + return cls() + + return cls( + total=data.get('total'), + limit=data.get('limit'), + offset=data.get('offset') + ) + + def __repr__(self): + """String representation of the Pagination instance.""" + return f"Pagination(total={self.total}, limit={self.limit}, offset={self.offset})" + +``` \ No newline at end of file From 99f49f175863a9757e57e2c42a892f74027fe970 Mon Sep 17 00:00:00 2001 From: Diego Barajas Date: Fri, 26 Jun 2026 09:31:56 -0500 Subject: [PATCH 8/8] auto-gen: 88678694-38d3-4dc8-80d6-7908e67312e7 mercadopago/resources/refund.py --- mercadopago/resources/refund.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/mercadopago/resources/refund.py b/mercadopago/resources/refund.py index 3f8f3a4..a4c9e6f 100644 --- a/mercadopago/resources/refund.py +++ b/mercadopago/resources/refund.py @@ -1,10 +1,16 @@ +# Change type: modify +# Title: Update RefundRequest — remove metadata and reason fields +# Detail: Remove metadata and reason properties from RefundRequest. The only remaining field is amount (float, optional — omit for full refund). + +```python """Refund resource for the MercadoPago Payments API. Wraps ``/v1/payments/{payment_id}/refunds`` endpoints to list existing refunds and create full or partial refunds on approved payments. Refunds are available within 180 days of payment approval and require -sufficient account balance. +sufficient account balance. The refund request accepts only an optional +``amount`` field for partial refunds. `API reference `_ """ @@ -17,6 +23,9 @@ class Refund(MPBase): Supports full refunds (omit *refund_object*) and partial refunds (pass ``{"amount": }``). Refunds can only be issued for approved payments within 180 days. + + The refund request only accepts an ``amount`` field (float, optional). + All other fields (metadata, reason, etc.) are not supported. """ def list_all(self, payment_id, request_options=None): @@ -39,10 +48,13 @@ def create(self, payment_id, refund_object=None, request_options=None): Omit *refund_object* for a full refund, or pass ``{"amount": }`` for a partial refund. + + Only the ``amount`` field is supported in the refund request. + Fields like ``metadata`` and ``reason`` are no longer accepted. Args: payment_id: Identifier of the payment to refund. - refund_object: Optional dict with partial refund details. + refund_object: Optional dict with ``amount`` for partial refund. request_options: Per-call configuration overrides. Raises: @@ -58,3 +70,4 @@ def create(self, payment_id, refund_object=None, request_options=None): return self._post(uri="/v1/payments/" + str(payment_id) + "/refunds", data=refund_object, request_options=request_options) +``` \ No newline at end of file