From 60ec06e6ffb1c16a4677da4938138a644159c1ea Mon Sep 17 00:00:00 2001 From: renanneri01 Date: Mon, 27 Jan 2025 10:05:59 -0300 Subject: [PATCH 1/4] [Feature] Initial implementation of the creation order (#1) * Initial implementation of the creation order * Adjust reference devsite --- .pre-commit-config.yaml | 16 +++++++++ mercadopago/resources/__init__.py | 2 ++ mercadopago/resources/order.py | 35 ++++++++++++++++++ mercadopago/sdk.py | 27 +++++++++----- tests/test_order.py | 60 +++++++++++++++++++++++++++++++ 5 files changed, 131 insertions(+), 9 deletions(-) create mode 100644 .pre-commit-config.yaml create mode 100644 mercadopago/resources/order.py create mode 100644 tests/test_order.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..9f72a15 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,16 @@ +repos: + - repo: https://github.com/melisource/fury_websec-git-hooks + rev: v2.0.0 + hooks: + - id: pre_commit_hook + stages: [commit] + - id: post_commit_hook + stages: [post-commit] + + - repo: https://github.com/melisource/fury_datasec-git-hooks + rev: 1.2.2 + hooks: + - id: pre_commit_hook + stages: [commit] + - id: post_commit_hook + stages: [post-commit] diff --git a/mercadopago/resources/__init__.py b/mercadopago/resources/__init__.py index ac555f8..407b471 100644 --- a/mercadopago/resources/__init__.py +++ b/mercadopago/resources/__init__.py @@ -11,6 +11,7 @@ from mercadopago.resources.disbursement_refund import DisbursementRefund from mercadopago.resources.identification_type import IdentificationType from mercadopago.resources.merchant_order import MerchantOrder +from mercadopago.resources.order import Order from mercadopago.resources.payment import Payment from mercadopago.resources.payment_methods import PaymentMethods from mercadopago.resources.plan import Plan @@ -31,6 +32,7 @@ 'HttpClient', 'IdentificationType', 'MerchantOrder', + 'Order', 'Payment', 'PaymentMethods', 'Plan', diff --git a/mercadopago/resources/order.py b/mercadopago/resources/order.py new file mode 100644 index 0000000..cfd370c --- /dev/null +++ b/mercadopago/resources/order.py @@ -0,0 +1,35 @@ +""" + Module: order +""" +from mercadopago.core import MPBase + + +class Order(MPBase): + """ + This class provides the methods to access the API that will allow you to create + your own order experience on your website. + + From basic to advanced configurations, you control the whole experience. + + [Click here for more info](https://www.mercadopago.com/developers/en/guides/online-payments/checkout-api/introduction/) # pylint: disable=line-too-long + """ + + def create(self, order_object, request_options=None): + """[Click here for more info](https://www.mercadopago.com/developers/en/reference/order/online-payments/create/post/) # pylint: disable=line-too-long + + Args: + order_object (dict): Order to be created + request_options (mercadopago.config.request_options, optional): An instance of + RequestOptions can be pass changing or adding custom options to ur REST call. + Defaults to None. + + Raises: + ValueError: Param order_object must be a Dictionary + + Returns: + dict: Order creation response + """ + if not isinstance(order_object, dict): + raise ValueError("Param order_object must be a Dictionary") + + return self._post(uri="/v1/orders", data=order_object, request_options=request_options) diff --git a/mercadopago/sdk.py b/mercadopago/sdk.py index 0536b58..13afaeb 100644 --- a/mercadopago/sdk.py +++ b/mercadopago/sdk.py @@ -12,6 +12,7 @@ DisbursementRefund, IdentificationType, MerchantOrder, + Order, Payment, PaymentMethods, Plan, @@ -33,15 +34,16 @@ class SDK: 5. Disbursement Refund 6. Identification Type 7. Merchant Order - 8. Payment Methods - 9. Payment - 10. Preapproval - 11. Preference - 12. Refund - 13. User - 14. Chargeback - 15. Subscription - 16. Plan + 8. Order + 9. Payment Methods + 10. Payment + 11. Preapproval + 12. Preference + 13. Refund + 14. User + 15. Chargeback + 16. Subscription + 17. Plan """ def __init__( @@ -120,6 +122,13 @@ def merchant_order(self, request_options=None): """ return MerchantOrder(request_options is not None and request_options or self.request_options, self.http_client) + + def order(self, request_options=None): + """ + Returns the attribute value of the function + """ + return Order(request_options is not None and request_options + or self.request_options, self.http_client) def payment(self, request_options=None): """ diff --git a/tests/test_order.py b/tests/test_order.py new file mode 100644 index 0000000..dda7dee --- /dev/null +++ b/tests/test_order.py @@ -0,0 +1,60 @@ +""" + Module: test_order +""" +from datetime import datetime +import os +import unittest +import random +import mercadopago + + +class TestOrder(unittest.TestCase): + """ + Test Module: Order + """ + sdk = mercadopago.SDK(os.environ['ACCESS_TOKEN']) + + def test_create(self): + """ + Test Function: Order + """ + card_token_object = { + "card_number": "5031433215406351", + "security_code": "123", + "expiration_year": "2025", + "expiration_month": "11", + "cardholder": { + "name": "APRO" + } + } + + card_token_created = self.sdk.card_token().create(card_token_object) + random_email_id = random.randint(100000, 999999) + order_object = { + "type": "online", + "total_amount": "1000.00", + "external_reference": "ext_ref_1234", + "transactions": { + "payments": [ + { + "amount": "1000.00", + "payment_method": { + "id": "master", + "type": "credit_card", + "token": card_token_created["response"]["id"], + "installments": 12 + } + } + ] + }, + "payer": { + "email": f"test_payer_{random_email_id}@testuser.com" + } + } + + order_created = self.sdk.order().create(order_object) + self.assertEqual(order_created["status"], 201) + self.assertEqual(order_created["response"]["status"], "processed") + +if __name__ == "__main__": + unittest.main() From 6857ba2449ea0a3ead2802ab35bbecf52f738156 Mon Sep 17 00:00:00 2001 From: Danielen Cestari Nunes Date: Mon, 3 Feb 2025 11:47:29 -0300 Subject: [PATCH 2/4] create endpoint get and process by id --- tests/test_order.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/test_order.py b/tests/test_order.py index dda7dee..6352a36 100644 --- a/tests/test_order.py +++ b/tests/test_order.py @@ -14,7 +14,7 @@ class TestOrder(unittest.TestCase): """ sdk = mercadopago.SDK(os.environ['ACCESS_TOKEN']) - def test_create(self): + def test_create_get(self): """ Test Function: Order """ @@ -56,5 +56,10 @@ def test_create(self): self.assertEqual(order_created["status"], 201) self.assertEqual(order_created["response"]["status"], "processed") + order_get = self.sdk.order().get( + order_created["response"]["id"]) + self.assertEqual(order_get["status"], 200) + + if __name__ == "__main__": unittest.main() From 5266cac468801b1ee6cc63d3c68a3d362d11cbea Mon Sep 17 00:00:00 2001 From: Danielen Cestari Nunes Date: Mon, 3 Feb 2025 11:56:38 -0300 Subject: [PATCH 3/4] update --- mercadopago/resources/order.py | 40 ++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/mercadopago/resources/order.py b/mercadopago/resources/order.py index cfd370c..c7efcac 100644 --- a/mercadopago/resources/order.py +++ b/mercadopago/resources/order.py @@ -33,3 +33,43 @@ def create(self, order_object, request_options=None): raise ValueError("Param order_object must be a Dictionary") return self._post(uri="/v1/orders", data=order_object, request_options=request_options) + + def get(self, order_id, request_options=None): + """[Click here for more info](https://www.mercadopago.com.br/developers/en/reference/order/in-person-payments/point/get-order/get) # pylint: disable=line-too-long + + Args: + order_id (str): The Order ID + request_options (mercadopago.config.request_options, optional): An instance of + RequestOptions can be pass changing or adding custom options to ur REST call. + Defaults to None. + + Raises: + ValueError: Param order_id must be a string + + Returns: + dict: Order ID returned in the response to the request made for its creation. + """ + + if not isinstance(order_id, str): + raise ValueError("Param order_id must be a string") + + return self._get(uri="/v1/orders/" + str(order_id), request_options=request_options) + + def process(self, order_id, request_options=None): + """[Click here for more info](https://www.mercadopago.com.br/developers/pt/reference/order/online/process-order/post # pylint: disable=line-too-long + Args: + order_id (str): ID of the order to be processed. This value is returned in the response to the Create order request. + request_options (mercadopago.config.request_options, optional): An instance of + RequestOptions can be pass changing or adding custom options to ur REST call. + Defaults to None. + + Raises: + ValueError: Param order_id must be a string + Returns: + dict: Order ID returned in the response to the request made for its creation. + """ + + if not isinstance(order_id, str): + raise ValueError("Param order_id must be a string") + + return self._get(uri="/v1/orders/" + str(order_id) + "/process", request_options=request_options) \ No newline at end of file From 5fa24917bb81d8e55459f912eac1d2c98d99a866 Mon Sep 17 00:00:00 2001 From: Danielen Cestari Nunes Date: Mon, 3 Feb 2025 14:33:34 -0300 Subject: [PATCH 4/4] update order tests --- tests/test_order.py | 65 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/tests/test_order.py b/tests/test_order.py index 6352a36..5a37599 100644 --- a/tests/test_order.py +++ b/tests/test_order.py @@ -14,14 +14,14 @@ class TestOrder(unittest.TestCase): """ sdk = mercadopago.SDK(os.environ['ACCESS_TOKEN']) - def test_create_get(self): + def test_create_order_and_get_by_id(self): """ Test Function: Order """ card_token_object = { "card_number": "5031433215406351", "security_code": "123", - "expiration_year": "2025", + "expiration_year": "2055", "expiration_month": "11", "cardholder": { "name": "APRO" @@ -60,6 +60,65 @@ def test_create_get(self): order_created["response"]["id"]) self.assertEqual(order_get["status"], 200) - if __name__ == "__main__": unittest.main() + + +class TestOrderProcess(unittest.TestCase): + sdk = mercadopago.SDK(os.environ['ACCESS_TOKEN']) + + def test_process_order(self): + card_token_object = { + "card_number": "5031433215406351", + "security_code": "123", + "expiration_year": "2055", + "expiration_month": "11", + "cardholder": { + "name": "APRO" + } + } + card_token_created = self.sdk.card_token().create(card_token_object) + if card_token_created.get("status") != 201 or not card_token_created.get("response"): + self.fail(f"Falha ao criar card token: {card_token_created}") + + card_token_id = card_token_created["response"]["id"] + random_email_id = random.randint(100000, 999999) + order_object = { + "type": "online", + "processing_mode": "manual", + "external_reference": "ext_ref_1234", + "total_amount": "200.00", + "transactions": { + "payments": [ + { + "amount": "200.00", + "payment_method": { + "id": "master", + "type": "credit_card", + "token": card_token_id, + "installments": 1 + } + } + ] + }, + "payer": { + "email": f"test_payer_{random_email_id}@testuser.com" + } + } + + order_created = self.sdk.order().create(order_object) + if order_created.get("status") != 201 or not order_created.get("response"): + self.fail(f"Falha ao criar pedido: {order_created}") + + order_id = order_created["response"]["id"] + print("Pedido criado com ID:", order_id) + + process_response = self.sdk.order().process(order_id) + if process_response.get("status") != 200 or not process_response.get("response"): + self.fail(f"Falha ao processar pedido: {process_response}") + + self.assertEqual(process_response["status"], 200, "Status HTTP inválido ao processar o pedido") + print("Pedido processado com sucesso.") + + if __name__ == "__main__": + unittest.main()