From 61983b8fbff267de9305747ea06dc579bd7dfaa6 Mon Sep 17 00:00:00 2001 From: Remi Jannel Date: Thu, 27 Jun 2019 12:59:15 -0700 Subject: [PATCH] Add support for the `SetupIntent` resource and APIs --- .travis.yml | 2 +- stripe/api_resources/__init__.py | 1 + stripe/api_resources/customer.py | 6 +- stripe/api_resources/setup_intent.py | 27 ++++++++ stripe/object_classes.py | 1 + tests/api_resources/test_setup_intent.py | 79 ++++++++++++++++++++++++ tests/conftest.py | 2 +- 7 files changed, 113 insertions(+), 5 deletions(-) create mode 100644 stripe/api_resources/setup_intent.py create mode 100644 tests/api_resources/test_setup_intent.py diff --git a/.travis.yml b/.travis.yml index bc4b34d2b..1cc1a96ee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,7 +25,7 @@ cache: env: global: # If changing this number, please also change it in `tests/conftest.py`. - - STRIPE_MOCK_VERSION=0.58.0 + - STRIPE_MOCK_VERSION=0.60.0 before_install: # Unpack and start stripe-mock so that the test suite can talk to it diff --git a/stripe/api_resources/__init__.py b/stripe/api_resources/__init__.py index 3078b5b94..779e90308 100644 --- a/stripe/api_resources/__init__.py +++ b/stripe/api_resources/__init__.py @@ -57,6 +57,7 @@ from stripe.api_resources.refund import Refund from stripe.api_resources.reversal import Reversal from stripe.api_resources.review import Review +from stripe.api_resources.setup_intent import SetupIntent from stripe.api_resources.sku import SKU from stripe.api_resources.source import Source from stripe.api_resources.source_transaction import SourceTransaction diff --git a/stripe/api_resources/customer.py b/stripe/api_resources/customer.py index f843876dc..991fe16fb 100644 --- a/stripe/api_resources/customer.py +++ b/stripe/api_resources/customer.py @@ -11,13 +11,13 @@ @custom_method("delete_discount", http_verb="delete", http_path="discount") @nested_resource_class_methods( - "source", operations=["create", "retrieve", "update", "delete", "list"] + "balance_transaction", operations=["create", "retrieve", "update", "list"] ) @nested_resource_class_methods( - "tax_id", operations=["create", "retrieve", "delete", "list"] + "source", operations=["create", "retrieve", "update", "delete", "list"] ) @nested_resource_class_methods( - "balance_transaction", operations=["create", "retrieve", "update", "list"] + "tax_id", operations=["create", "retrieve", "delete", "list"] ) class Customer( CreateableAPIResource, diff --git a/stripe/api_resources/setup_intent.py b/stripe/api_resources/setup_intent.py new file mode 100644 index 000000000..bace247c8 --- /dev/null +++ b/stripe/api_resources/setup_intent.py @@ -0,0 +1,27 @@ +from __future__ import absolute_import, division, print_function + +from stripe import util +from stripe.api_resources.abstract import CreateableAPIResource +from stripe.api_resources.abstract import ListableAPIResource +from stripe.api_resources.abstract import UpdateableAPIResource +from stripe.api_resources.abstract import custom_method + + +@custom_method("cancel", http_verb="post") +@custom_method("confirm", http_verb="post") +class SetupIntent( + CreateableAPIResource, ListableAPIResource, UpdateableAPIResource +): + OBJECT_NAME = "setup_intent" + + def cancel(self, idempotency_key=None, **params): + url = self.instance_url() + "/cancel" + headers = util.populate_headers(idempotency_key) + self.refresh_from(self.request("post", url, params, headers)) + return self + + def confirm(self, idempotency_key=None, **params): + url = self.instance_url() + "/confirm" + headers = util.populate_headers(idempotency_key) + self.refresh_from(self.request("post", url, params, headers)) + return self diff --git a/stripe/object_classes.py b/stripe/object_classes.py index 1442a257d..787c84afb 100644 --- a/stripe/object_classes.py +++ b/stripe/object_classes.py @@ -63,6 +63,7 @@ api_resources.reporting.ReportType.OBJECT_NAME: api_resources.reporting.ReportType, api_resources.Reversal.OBJECT_NAME: api_resources.Reversal, api_resources.Review.OBJECT_NAME: api_resources.Review, + api_resources.SetupIntent.OBJECT_NAME: api_resources.SetupIntent, api_resources.sigma.ScheduledQueryRun.OBJECT_NAME: api_resources.sigma.ScheduledQueryRun, api_resources.SKU.OBJECT_NAME: api_resources.SKU, api_resources.Source.OBJECT_NAME: api_resources.Source, diff --git a/tests/api_resources/test_setup_intent.py b/tests/api_resources/test_setup_intent.py new file mode 100644 index 000000000..02d6eecf2 --- /dev/null +++ b/tests/api_resources/test_setup_intent.py @@ -0,0 +1,79 @@ +from __future__ import absolute_import, division, print_function + +import stripe + + +TEST_RESOURCE_ID = "seti_123" + + +class TestSetupIntent(object): + def test_is_listable(self, request_mock): + resources = stripe.SetupIntent.list() + request_mock.assert_requested("get", "/v1/setup_intents") + assert isinstance(resources.data, list) + assert isinstance(resources.data[0], stripe.SetupIntent) + + def test_is_retrievable(self, request_mock): + resource = stripe.SetupIntent.retrieve(TEST_RESOURCE_ID) + request_mock.assert_requested( + "get", "/v1/setup_intents/%s" % TEST_RESOURCE_ID + ) + assert isinstance(resource, stripe.SetupIntent) + + def test_is_creatable(self, request_mock): + resource = stripe.SetupIntent.create(payment_method_types=["card"]) + request_mock.assert_requested("post", "/v1/setup_intents") + assert isinstance(resource, stripe.SetupIntent) + + def test_is_modifiable(self, request_mock): + resource = stripe.SetupIntent.modify( + TEST_RESOURCE_ID, metadata={"key": "value"} + ) + request_mock.assert_requested( + "post", + "/v1/setup_intents/%s" % TEST_RESOURCE_ID, + {"metadata": {"key": "value"}}, + ) + assert isinstance(resource, stripe.SetupIntent) + + def test_is_saveable(self, request_mock): + resource = stripe.SetupIntent.retrieve(TEST_RESOURCE_ID) + + resource.metadata["key"] = "value" + resource.save() + request_mock.assert_requested( + "post", + "/v1/setup_intents/%s" % TEST_RESOURCE_ID, + {"metadata": {"key": "value"}}, + ) + assert isinstance(resource, stripe.SetupIntent) + + def test_can_cancel(self, request_mock): + resource = stripe.SetupIntent.retrieve(TEST_RESOURCE_ID) + resource.cancel() + request_mock.assert_requested( + "post", "/v1/setup_intents/%s/cancel" % TEST_RESOURCE_ID + ) + assert isinstance(resource, stripe.SetupIntent) + + def test_can_cancel_classmethod(self, request_mock): + resource = stripe.SetupIntent.cancel(TEST_RESOURCE_ID) + request_mock.assert_requested( + "post", "/v1/setup_intents/%s/cancel" % TEST_RESOURCE_ID + ) + assert isinstance(resource, stripe.SetupIntent) + + def test_can_confirm(self, request_mock): + resource = stripe.SetupIntent.retrieve(TEST_RESOURCE_ID) + resource.confirm() + request_mock.assert_requested( + "post", "/v1/setup_intents/%s/confirm" % TEST_RESOURCE_ID + ) + assert isinstance(resource, stripe.SetupIntent) + + def test_can_confirm_classmethod(self, request_mock): + resource = stripe.SetupIntent.confirm(TEST_RESOURCE_ID) + request_mock.assert_requested( + "post", "/v1/setup_intents/%s/confirm" % TEST_RESOURCE_ID + ) + assert isinstance(resource, stripe.SetupIntent) diff --git a/tests/conftest.py b/tests/conftest.py index 28e739c55..fb358c4a2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -16,7 +16,7 @@ # When changing this number, don't forget to change it in `.travis.yml` too. -MOCK_MINIMUM_VERSION = "0.58.0" +MOCK_MINIMUM_VERSION = "0.60.0" # Starts stripe-mock if an OpenAPI spec override is found in `openapi/`, and # otherwise fall back to `STRIPE_MOCK_PORT` or 12111.