python-terminusgps 23.0.0__py3-none-any.whl → 24.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-terminusgps
3
- Version: 23.0.0
3
+ Version: 24.0.0
4
4
  Summary: Provides abstractions/utilities for working with Wialon API, Authorize.NET API, AWS API, and more.
5
5
  Project-URL: Documentation, https://app.terminusgps.com/docs/apps/python-terminusgps/index.html
6
6
  Project-URL: Repository, https://github.com/terminusgps/python-terminusgps
@@ -1,14 +1,16 @@
1
1
  terminusgps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  terminusgps/settings.py,sha256=UBj2tvuBzQDEz05PeFqHG4_ise3Bl6Iu7pxcrtjNaYE,568
3
- terminusgps/authorizenet/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- terminusgps/authorizenet/auth.py,sha256=l3sPpLycqVO-gppU2sH7YAScuHmm3xXylxW6Gdu6a7Q,563
5
- terminusgps/authorizenet/subscriptions.py,sha256=W2oIb1oWXEhtET4bHpUWzuLIl3XbAqMkghAXy0AyWAQ,1366
6
- terminusgps/authorizenet/utils.py,sha256=q8ReDcYIk2eG6d36IM1vZorfeAxKhyQRLdtrIpKTNwA,2212
3
+ terminusgps/authorizenet/__init__.py,sha256=LiGLlWNNiqS7RSOP4Apabx-b9EBYyNbxRY_a0mvJoaE,466
4
+ terminusgps/authorizenet/auth.py,sha256=ICxPPzoUc64VbsIIemEWKrn8xjHGwbNdo2VbtaFCFss,1107
5
+ terminusgps/authorizenet/errors.py,sha256=HG5NwVxQCtOYidVl30y49PC0Ovw5VYdsy9wTgUFMw9M,949
6
+ terminusgps/authorizenet/utils.py,sha256=5aczO2EcMX2bi-kRg8_fnzLzE7qMA9K1qBxAo2AJz1c,2021
7
7
  terminusgps/authorizenet/profiles/__init__.py,sha256=QKjMKcXpCSCEhv6LBCz0yGP8t0VxAyKyYRS4_HLYnxQ,114
8
- terminusgps/authorizenet/profiles/addresses.py,sha256=xAiqETexGXicYOd_M3a4SBuHweeZPDlfWhtpqdvls-g,5466
9
- terminusgps/authorizenet/profiles/base.py,sha256=UTudVCju5-pLJQwoK0IfuT8OvxZVJCX3vApveUY3XE4,2286
10
- terminusgps/authorizenet/profiles/customers.py,sha256=ehtsWhPt0zF8_3dFlgFBWHA4NbQb-6AvOhtjTy3uQDg,8639
11
- terminusgps/authorizenet/profiles/payments.py,sha256=jcF_uJcaeU2JR5Sqza0LccsQGe9F-SUCjvg3o3QskIk,8808
8
+ terminusgps/authorizenet/profiles/addresses.py,sha256=uowUkrr4fa4g7pjgNDrjW0es5t_gH9B8VHI74PbTWFc,6303
9
+ terminusgps/authorizenet/profiles/base.py,sha256=TOUHr22QRQBLErdysOkfcpJBusTjrUTqOmWEyNvMacA,2240
10
+ terminusgps/authorizenet/profiles/customers.py,sha256=xe7LNsqSB_oRCY-teojDTt0O6a5yVf0dyuu86ftc4hA,8377
11
+ terminusgps/authorizenet/profiles/payments.py,sha256=O_oZGUwO8XTApzr0itu-1XQYnWFR4gDpNCusWNzBh7A,11152
12
+ terminusgps/authorizenet/subscriptions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
+ terminusgps/authorizenet/subscriptions/subscriptions.py,sha256=JQHo2FxQyRPJp1jlbD2mIt9RKEJZbADZcfozNTKWbz0,1514
12
14
  terminusgps/aws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
15
  terminusgps/aws/secrets.py,sha256=MxQEmmBLpMUQ2tYAsHdCYf-7RZ84LiogdKcTsACX5dw,361
14
16
  terminusgps/aws/ses.py,sha256=sDca2GjMaZvUt3kUPtGCpcqHiOkij9lMV1ogZofgYUU,2372
@@ -28,7 +30,7 @@ terminusgps/wialon/items/route.py,sha256=PTJx1gmT_PGz7nlSSUS2VzjYD-aAuvkEOIdIFne
28
30
  terminusgps/wialon/items/unit.py,sha256=-jQL5Alvz77FZWteYNM9VNX15jtCufI-DWRRj3hRsgA,8539
29
31
  terminusgps/wialon/items/unit_group.py,sha256=vGVJMBY1BrKK0tP-C1DCIz4Bh6P-HKRnKY1g8g95UIs,5031
30
32
  terminusgps/wialon/items/user.py,sha256=INwAibQVmjNNelepQXMfDevgJqMvIjHHgEjAMLRvhB0,7082
31
- python_terminusgps-23.0.0.dist-info/METADATA,sha256=mWo-bctKKFZdbhH0ROVcDsqvN9kC58jMl1o49TQkFCI,946
32
- python_terminusgps-23.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
33
- python_terminusgps-23.0.0.dist-info/licenses/COPYING,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
34
- python_terminusgps-23.0.0.dist-info/RECORD,,
33
+ python_terminusgps-24.0.0.dist-info/METADATA,sha256=QU-Do0pVNWwhy5D08Y5-n2nKz_mknj6sQMRHgHWpf5s,946
34
+ python_terminusgps-24.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
35
+ python_terminusgps-24.0.0.dist-info/licenses/COPYING,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
36
+ python_terminusgps-24.0.0.dist-info/RECORD,,
@@ -0,0 +1,9 @@
1
+ from django.conf import settings
2
+ from django.core.exceptions import ImproperlyConfigured
3
+
4
+ if not hasattr(settings, "DEBUG"):
5
+ raise ImproperlyConfigured("'DEBUG' setting is required.")
6
+ if not hasattr(settings, "MERCHANT_AUTH_LOGIN_ID"):
7
+ raise ImproperlyConfigured("'MERCHANT_AUTH_LOGIN_ID' setting is required.")
8
+ if not hasattr(settings, "MERCHANT_AUTH_TRANSACTION_KEY"):
9
+ raise ImproperlyConfigured("'MERCHANT_AUTH_TRANSACTION_KEY' setting is required.")
@@ -4,6 +4,13 @@ from django.conf import settings
4
4
 
5
5
 
6
6
  def get_merchant_auth() -> merchantAuthenticationType:
7
+ """
8
+ Returns the merchant authentication information for Authorizenet API requests.
9
+
10
+ :returns: A merchant authentication object.
11
+ :rtype: :py:obj:`~authorizenet.apicontractsv1.merchantAuthenticationType`
12
+
13
+ """
7
14
  return merchantAuthenticationType(
8
15
  name=str(settings.MERCHANT_AUTH_LOGIN_ID),
9
16
  transactionKey=str(settings.MERCHANT_AUTH_TRANSACTION_KEY),
@@ -11,8 +18,22 @@ def get_merchant_auth() -> merchantAuthenticationType:
11
18
 
12
19
 
13
20
  def get_environment() -> str:
21
+ """
22
+ Returns the environment for Authorizenet API requests.
23
+
24
+ :returns: An Authorizenet API environment string.
25
+ :rtype: :py:obj:`str`
26
+
27
+ """
14
28
  return constants.SANDBOX if settings.DEBUG else constants.PRODUCTION
15
29
 
16
30
 
17
31
  def get_validation_mode() -> str:
32
+ """
33
+ Returns the validation mode for Authorizenet API requests.
34
+
35
+ :returns: An Authorizenet API validation string.
36
+ :rtype: :py:obj:`str`
37
+
38
+ """
18
39
  return "testMode" if settings.DEBUG else "liveMode"
@@ -0,0 +1,31 @@
1
+ class ControllerExecutionError(Exception):
2
+ """Raised when an Authorizenet API controller fails to execute."""
3
+
4
+ def __init__(self, message: str, code: str, *args, **kwargs) -> None:
5
+ """
6
+ Sets :py:attr:`message` and :py:attr`code` for the exception.
7
+
8
+ :param message: An Authorizenet API error message.
9
+ :type message: :py:obj:`str`
10
+ :param code: An Authorizenet API error code.
11
+ :type code: :py:obj:`str`
12
+ :returns: Nothing.
13
+ :rtype: :py:obj:`None`
14
+
15
+ """
16
+ super().__init__(message, *args, **kwargs)
17
+ self._message = message
18
+ self._code = code
19
+
20
+ def __str__(self) -> str:
21
+ return f"{self.code}: {self.message}"
22
+
23
+ @property
24
+ def message(self) -> str:
25
+ """An Authorizenet API error message."""
26
+ return self._message
27
+
28
+ @property
29
+ def code(self) -> str:
30
+ """An Authorizenet API error code."""
31
+ return self._code
@@ -1,57 +1,62 @@
1
1
  from authorizenet import apicontractsv1, apicontrollers
2
2
 
3
- from terminusgps.authorizenet.profiles.base import AuthorizenetSubProfileBase
3
+ from .base import AuthorizenetSubProfileBase
4
4
 
5
5
 
6
6
  class AddressProfile(AuthorizenetSubProfileBase):
7
7
  """An Authorizenet customer address profile."""
8
8
 
9
- def create(self, shipping_addr: apicontractsv1.customerAddressType) -> int:
9
+ def create(self, address: apicontractsv1.customerAddressType) -> int:
10
10
  """
11
11
  Creates an Authorizenet address profile.
12
12
 
13
- :param shipping_addr: An Authorizenet customer address.
14
- :type shipping_addr: :py:obj:`~authorizenet.apicontractsv1.customerAddressType`
13
+ :param address: A customer address.
14
+ :type address: :py:obj:`~authorizenet.apicontractsv1.customerAddressType`
15
15
  :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
16
+ :raises ValueError: If the Authorizenet API response was not retrieved.
16
17
  :returns: A new address profile id.
17
18
  :rtype: :py:obj:`int`
18
19
 
19
20
  """
20
- response = self._authorizenet_create_shipping_address(shipping_addr)
21
+ response = self._authorizenet_create_shipping_address(address)
22
+ if response is None:
23
+ raise ValueError("Failed to retrieve Authorizenet API response.")
21
24
  return int(response.customerAddressId)
22
25
 
23
- def update(self, shipping_addr: apicontractsv1.customerAddressType) -> dict:
26
+ def update(self, address: apicontractsv1.customerAddressType) -> dict | None:
24
27
  """
25
28
  Updates the Authorizenet address profile.
26
29
 
27
- :param shipping_addr: A customer shipping address.
28
- :type shipping_addr: :py:obj:`~authorizenet.apicontractsv1.customerAddressType`
30
+ :param address: A customer shipping address.
31
+ :type address: :py:obj:`~authorizenet.apicontractsv1.customerAddressType`
29
32
  :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
30
- :returns: An Authorizenet API response.
31
- :rtype: :py:obj:`dict`
33
+ :returns: An Authorizenet API response, if any.
34
+ :rtype: :py:obj:`dict` | :py:obj:`None`
32
35
 
33
36
  """
34
- return self._authorizenet_update_shipping_address(shipping_addr)
37
+ return self._authorizenet_update_shipping_address(address)
35
38
 
36
- def delete(self) -> dict:
39
+ def delete(self) -> dict | None:
37
40
  """
38
41
  Deletes the Authorizenet address profile.
39
42
 
40
43
  :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
41
44
  :returns: An Authorizenet API response, if any.
42
- :rtype: :py:obj:`dict`
45
+ :rtype: :py:obj:`dict` | :py:obj:`None`
43
46
 
44
47
  """
45
48
  return self._authorizenet_delete_shipping_address()
46
49
 
47
- def _authorizenet_get_shipping_address(self) -> dict:
50
+ def _authorizenet_get_shipping_address(self) -> dict | None:
48
51
  """
49
52
  Executes a :py:obj:`~authorizenet.apicontractsv1.getCustomerShippingAddressRequest` using the Authorizenet API.
50
53
 
54
+ `getCustomerShippingAddressRequest <https://developer.authorize.net/api/reference/index.html#customer-profiles-get-customer-shipping-address>`_
55
+
51
56
  :raises AssertionError: If :py:attr:`id` wasn't set.
52
57
  :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
53
- :returns: An Authorizenet API response.
54
- :rtype: :py:obj:`dict`
58
+ :returns: An Authorizenet API response, if any.
59
+ :rtype: :py:obj:`dict` | :py:obj:`None`
55
60
 
56
61
  """
57
62
  assert self.id, "'id' was not set."
@@ -62,63 +67,67 @@ class AddressProfile(AuthorizenetSubProfileBase):
62
67
  customerAddressId=self.id,
63
68
  )
64
69
  controller = apicontrollers.getCustomerShippingAddressController(request)
65
- response = self.execute_controller(controller)
66
- return response
70
+ return self.execute_controller(controller)
67
71
 
68
72
  def _authorizenet_create_shipping_address(
69
- self, addr: apicontractsv1.customerAddressType
70
- ) -> dict:
73
+ self, address: apicontractsv1.customerAddressType
74
+ ) -> dict | None:
71
75
  """
72
76
  Executes a :py:obj:`~authorizenet.apicontractsv1.createCustomerShippingAddressRequest` using the Authorizenet API.
73
77
 
78
+ `createCustomerShippingAddressRequest <https://developer.authorize.net/api/reference/index.html#customer-profiles-create-customer-shipping-address>`_
79
+
74
80
  :raises AssertionError: If :py:attr:`id` wasn't set.
75
81
  :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
76
- :returns: An Authorizenet API response.
77
- :rtype: :py:obj:`dict`
82
+ :returns: An Authorizenet API response, if any.
83
+ :rtype: :py:obj:`dict` | :py:obj:`None`
78
84
 
79
85
  """
80
86
  request = apicontractsv1.createCustomerShippingAddressRequest(
81
87
  merchantAuthentication=self.merchantAuthentication,
82
88
  customerProfileId=self.customerProfileId,
83
- address=addr,
89
+ address=address,
84
90
  defaultShippingAddress=self.default,
85
91
  )
86
92
  controller = apicontrollers.createCustomerShippingAddressController(request)
87
- response = self.execute_controller(controller)
88
- return response
93
+ return self.execute_controller(controller)
89
94
 
90
95
  def _authorizenet_update_shipping_address(
91
- self, addr: apicontractsv1.customerAddressType
92
- ) -> dict:
96
+ self, address: apicontractsv1.customerAddressType
97
+ ) -> dict | None:
93
98
  """
94
99
  Executes a :py:obj:`~authorizenet.apicontractsv1.updateCustomerShippingAddressRequest` using the Authorizenet API.
95
100
 
101
+ `updateCustomerShippingAddressRequest <https://developer.authorize.net/api/reference/index.html#customer-profiles-update-customer-shipping-address>`_
102
+
96
103
  :raises AssertionError: If :py:attr:`id` wasn't set.
97
104
  :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
98
- :returns: An Authorizenet API response.
99
- :rtype: :py:obj:`dict`
105
+ :returns: An Authorizenet API response, if any.
106
+ :rtype: :py:obj:`dict` | :py:obj:`None`
100
107
 
101
108
  """
102
109
  assert self.id, "'id' was not set."
103
110
 
104
- addr.customerAddressId = self.id
111
+ address.customerAddressId = self.id
105
112
  request = apicontractsv1.updateCustomerShippingAddressRequest(
106
113
  merchantAuthentication=self.merchantAuthentication,
107
114
  customerProfileId=self.customerProfileId,
108
- address=addr,
115
+ address=address,
109
116
  default=self.default,
110
117
  )
111
118
  controller = apicontrollers.updateCustomerShippingAddressController(request)
112
119
  return self.execute_controller(controller)
113
120
 
114
- def _authorizenet_delete_shipping_address(self) -> dict:
121
+ def _authorizenet_delete_shipping_address(self) -> dict | None:
115
122
  """
116
123
  Executes a :py:obj:`~authorizenet.apicontractsv1.deleteCustomerShippingAddressRequest` using the Authorizenet API.
117
124
 
125
+ `deleteCustomerShippingAddressRequest <https://developer.authorize.net/api/reference/index.html#customer-profiles-delete-customer-shipping-address>`_
126
+
118
127
  :raises AssertionError: If :py:attr:`id` wasn't set.
119
128
  :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
120
- :returns: An Authorizenet API response.
121
- :rtype: :py:obj:`dict`
129
+ :returns: An Authorizenet API response, if any.
130
+ :rtype: :py:obj:`dict` | :py:obj:`None`
122
131
 
123
132
  """
124
133
  assert self.id, "'id' was not set."
@@ -129,5 +138,4 @@ class AddressProfile(AuthorizenetSubProfileBase):
129
138
  customerAddressId=self.id,
130
139
  )
131
140
  controller = apicontrollers.deleteCustomerShippingAddressController(request)
132
- response = self.execute_controller(controller)
133
- return response
141
+ return self.execute_controller(controller)
@@ -3,8 +3,8 @@ from typing import override
3
3
 
4
4
  from authorizenet import apicontractsv1
5
5
 
6
- from terminusgps.authorizenet.auth import get_merchant_auth, get_validation_mode
7
- from terminusgps.authorizenet.utils import ControllerExecutionMixin
6
+ from ..auth import get_merchant_auth, get_validation_mode
7
+ from ..utils import ControllerExecutionMixin
8
8
 
9
9
 
10
10
  class AuthorizenetProfileBase(ControllerExecutionMixin):
@@ -1,27 +1,30 @@
1
1
  from authorizenet import apicontractsv1, apicontrollers
2
2
  from authorizenet.apicontractsv1 import customerProfileType
3
3
 
4
- from terminusgps.authorizenet.profiles.base import AuthorizenetProfileBase
5
- from terminusgps.authorizenet.utils import get_customer_profile_ids
4
+ from ..utils import ControllerExecutionError, get_customer_profile_ids
5
+ from .base import AuthorizenetProfileBase
6
6
 
7
7
 
8
8
  class CustomerProfile(AuthorizenetProfileBase):
9
9
  """An Authorizenet customer profile."""
10
10
 
11
- def create(self, email: str, desc: str | None = None) -> int:
11
+ def create(self, email: str, desc: str = "") -> int:
12
12
  """
13
- Creates a customer profile using the Authorizenet API and returns its id.
13
+ Creates a customer profile and returns its id.
14
14
 
15
15
  :param email: An email address.
16
16
  :type email: :py:obj:`str`
17
17
  :param desc: An optional description.
18
- :type desc: :py:obj:`str` | :py:obj:`None`
18
+ :type desc: :py:obj:`str`
19
19
  :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
20
+ :raises ValueError: If the Authorizenet API response was not retrieved.
20
21
  :returns: The new customer profile id.
21
22
  :rtype: :py:obj:`int`
22
23
 
23
24
  """
24
25
  response = self._authorizenet_create_customer_profile(email=email, desc=desc)
26
+ if response is None:
27
+ raise ValueError("Failed to retrieve Authorizenet API response.")
25
28
  return int(response.customerProfileId)
26
29
 
27
30
  def update(self, email: str, desc: str = "") -> None:
@@ -30,7 +33,7 @@ class CustomerProfile(AuthorizenetProfileBase):
30
33
 
31
34
  :param email: An email address.
32
35
  :type email: :py:obj:`str`
33
- :param desc: An optional description. Default is ``""``
36
+ :param desc: An optional description.
34
37
  :type desc: :py:obj:`str`
35
38
  :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
36
39
  :returns: Nothing.
@@ -50,29 +53,23 @@ class CustomerProfile(AuthorizenetProfileBase):
50
53
  """
51
54
  self._authorizenet_delete_customer_profile()
52
55
 
53
- def get_payment_profiles(self) -> list[dict] | None:
54
- """
55
- Returns a list of the customer's payment profiles.
56
-
57
- :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
58
- :returns: A list of customer payment profiles, if they exist.
59
- :rtype: :py:obj:`list` | :py:obj:`None`
60
-
61
- """
62
- response = self._authorizenet_get_customer_profile(issuer_info=False)
63
- return response.get("paymentProfiles") if response else None
64
-
65
- def get_addresses(self) -> list[dict] | None:
66
- """
67
- Returns a list of the customer's address profiles.
68
-
69
- :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
70
- :returns: A list of customer shipping addresses, if they exist.
71
- :rtype: :py:obj:`list` | :py:obj:`None`
56
+ @property
57
+ def payment_profiles(self) -> list[dict] | None:
58
+ """A list of the customer's payment profiles, if any."""
59
+ try:
60
+ response = self._authorizenet_get_customer_profile(issuer_info=False)
61
+ return response.get("paymentProfiles") if response else None
62
+ except ControllerExecutionError:
63
+ return
72
64
 
73
- """
74
- response = self._authorizenet_get_customer_profile(issuer_info=False)
75
- return response.get("shipToList") if response else None
65
+ @property
66
+ def address_profiles(self) -> list[dict] | None:
67
+ """A list of the customer's address profiles, if any."""
68
+ try:
69
+ response = self._authorizenet_get_customer_profile(issuer_info=False)
70
+ return response.get("shipToList") if response else None
71
+ except ControllerExecutionError:
72
+ return
76
73
 
77
74
  @property
78
75
  def exists(self) -> bool:
@@ -109,7 +106,6 @@ class CustomerProfile(AuthorizenetProfileBase):
109
106
  :type email: :py:obj:`str`
110
107
  :param desc: An optional description.
111
108
  :type desc: :py:obj:`str`
112
- :raises AssertionError: If :py:attr:`id` wasn't set.
113
109
  :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
114
110
  :returns: An Authorizenet API response, if any.
115
111
  :rtype: :py:obj:`dict` | :py:obj:`None`
@@ -1,6 +1,6 @@
1
1
  from authorizenet import apicontractsv1, apicontrollers
2
2
 
3
- from terminusgps.authorizenet.profiles.base import AuthorizenetSubProfileBase
3
+ from .base import AuthorizenetSubProfileBase
4
4
 
5
5
 
6
6
  class PaymentProfile(AuthorizenetSubProfileBase):
@@ -8,36 +8,58 @@ class PaymentProfile(AuthorizenetSubProfileBase):
8
8
 
9
9
  def create(
10
10
  self,
11
- billing_addr: apicontractsv1.customerAddressType,
11
+ address: apicontractsv1.customerAddressType,
12
12
  payment: apicontractsv1.paymentType,
13
13
  ) -> int:
14
14
  """
15
15
  Creates an Authorizenet payment profile and returns its id.
16
16
 
17
- :param billing_addr: A billing address.
18
- :type billing_addr: :py:obj:`~authorizenet.apicontractsv1.customerAddressType`
17
+ :param address: A billing address.
18
+ :type address: :py:obj:`~authorizenet.apicontractsv1.customerAddressType`
19
19
  :param payment: A payment object.
20
20
  :type payment: :py:obj:`~authorizenet.apicontractsv1.paymentType`
21
+ :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
22
+ :raises ValueError: If the Authorizenet API response was not retrieved.
21
23
  :returns: The new payment profile's id.
22
24
  :rtype: :py:obj:`int`
23
25
 
24
26
  """
25
- response = self._authorizenet_create_payment_profile(billing_addr, payment)
27
+ response = self._authorizenet_create_payment_profile(address, payment)
28
+ if response is None:
29
+ raise ValueError("Failed to retrieve Authorizenet API response.")
26
30
  return int(response.customerPaymentProfileId)
27
31
 
28
32
  def update(
29
33
  self,
30
- billing_addr: apicontractsv1.customerAddressType,
34
+ address: apicontractsv1.customerAddressType,
31
35
  payment: apicontractsv1.paymentType,
32
- ) -> dict:
33
- """Updates the Authorizenet payment profile."""
34
- return self._authorizenet_update_payment_profile(billing_addr, payment)
36
+ ) -> dict | None:
37
+ """
38
+ Updates the Authorizenet payment profile.
39
+
40
+ :param address: A billing address.
41
+ :type address: :py:obj:`~authorizenet.apicontractsv1.customerAddressType`
42
+ :param payment: A payment method.
43
+ :type payment: :py:obj:`~authorizenet.apicontractsv1.paymentType`
44
+ :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
45
+ :returns: An Authorizenet API reponse, if any.
46
+ :rtype: :py:obj:`dict` | :py:obj:`None`
47
+
48
+ """
49
+ return self._authorizenet_update_payment_profile(address, payment)
35
50
 
36
- def delete(self) -> dict:
37
- """Deletes the Authorizenet payment profile."""
51
+ def delete(self) -> dict | None:
52
+ """
53
+ Deletes the Authorizenet payment profile.
54
+
55
+ :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
56
+ :returns: An Authorizenet API response, if any.
57
+ :rtype: :py:obj:`dict` | :py:obj:`None`
58
+
59
+ """
38
60
  return self._authorizenet_delete_payment_profile()
39
61
 
40
- def get_details(self, issuer_info: bool = False) -> dict:
62
+ def get_details(self, issuer_info: bool = False) -> dict | None:
41
63
  return self._authorizenet_get_payment_profile(issuer_info)
42
64
 
43
65
  def _authorizenet_get_transaction_list_for_customer(
@@ -46,10 +68,12 @@ class PaymentProfile(AuthorizenetSubProfileBase):
46
68
  ordering: str = "submitTimeUTC",
47
69
  offset: int = 1,
48
70
  descending: bool = False,
49
- ) -> dict:
71
+ ) -> dict | None:
50
72
  """
51
73
  Executes a :py:obj:`~authorizenet.apicontractsv1.getTransactionListForCustomerRequest` using the Authorizenet API.
52
74
 
75
+ `getTransactionListForCustomerRequest <https://developer.authorize.net/api/reference/index.html#transaction-reporting-get-transaction-list>`_
76
+
53
77
  :param limit: Total number of transactions to retrieve. Default is ``100``.
54
78
  :type limit: :py:obj:`int`
55
79
  :param ordering: A field to order the transactions by. Default is ``"submitTimeUTC"``.
@@ -60,8 +84,9 @@ class PaymentProfile(AuthorizenetSubProfileBase):
60
84
  :type descending: :py:obj:`bool`
61
85
  :raises ValueError: If ``ordering`` is invalid.
62
86
  :raises AssertionError: If :py:attr:`id` wasn't set.
63
- :returns: An Authorizenet API response.
64
- :rtype: :py:obj:`dict`
87
+ :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
88
+ :returns: An Authorizenet API response, if any.
89
+ :rtype: :py:obj:`dict` | :py:obj:`None`
65
90
 
66
91
  """
67
92
  ordering_options: tuple[str, str] = ("id", "submitTimeUTC")
@@ -78,52 +103,55 @@ class PaymentProfile(AuthorizenetSubProfileBase):
78
103
  paging={"limit": str(limit), "offset": str(offset)},
79
104
  )
80
105
  controller = apicontrollers.getTransactionListForCustomerController(request)
81
- response = self.execute_controller(controller)
82
- return response
106
+ return self.execute_controller(controller)
83
107
 
84
108
  def _authorizenet_create_payment_profile(
85
109
  self,
86
- billing_addr: apicontractsv1.customerAddressType,
110
+ address: apicontractsv1.customerAddressType,
87
111
  payment: apicontractsv1.paymentType,
88
- ) -> dict:
112
+ ) -> dict | None:
89
113
  """
90
114
  Executes a :py:obj:`~authorizenet.apicontractsv1.createCustomerPaymentProfileRequest` using the Authorizenet API.
91
115
 
92
- :param billing_addr: A customer address.
93
- :type billing_addr: :py:obj:`~authorizenet.apicontractsv1.customerAddressType`
116
+ `createCustomerPaymentProfileRequest <https://developer.authorize.net/api/reference/index.html#customer-profiles-create-customer-payment-profile>`_
117
+
118
+ :param address: A billing address.
119
+ :type address: :py:obj:`~authorizenet.apicontractsv1.customerAddressType`
94
120
  :param payment: A payment method.
95
121
  :type payment: :py:obj:`~authorizenet.apicontractsv1.paymentType`
96
- :raises AssertionError: If :py:attr:`id` wasn't set.
97
- :raises : If :py:attr:`id` wasn't set.
98
- :returns: An Authorizenet API response.
99
- :rtype: :py:obj:`dict`
122
+ :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
123
+ :returns: An Authorizenet API response, if any.
124
+ :rtype: :py:obj:`dict` | :py:obj:`None`
100
125
 
101
126
  """
102
127
  request = apicontractsv1.createCustomerPaymentProfileRequest(
103
128
  customerProfileId=self.customerProfileId,
104
129
  merchantAuthentication=self.merchantAuthentication,
105
130
  paymentProfile=apicontractsv1.customerPaymentProfileType(
106
- billTo=billing_addr, payment=payment, defaultPaymentProfile=self.default
131
+ billTo=address, payment=payment, defaultPaymentProfile=self.default
107
132
  ),
108
133
  validationMode=self.validationMode,
109
134
  )
110
135
  controller = apicontrollers.createCustomerPaymentProfileController(request)
111
- response = self.execute_controller(controller)
112
- return response
136
+ return self.execute_controller(controller)
113
137
 
114
- def _authorizenet_get_payment_profile(self, issuer_info: bool = False) -> dict:
138
+ def _authorizenet_get_payment_profile(
139
+ self, issuer_info: bool = False
140
+ ) -> dict | None:
115
141
  """
116
142
  Executes a :py:obj:`~authorizenet.apicontractsv1.getCustomerPaymentProfileRequest` using the Authorizenet API.
117
143
 
144
+ `getCustomerPaymentProfileRequest <https://developer.authorize.net/api/reference/index.html#customer-profiles-get-customer-payment-profile>`_
145
+
118
146
  :param issuer_info: Whether or not to include issuer information in the response.
119
147
  :type issuer_info: :py:obj:`bool`
120
148
  :raises AssertionError: If :py:attr:`id` wasn't set.
121
- :returns: An Authorizenet API response.
122
- :rtype: :py:obj:`dict`
149
+ :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
150
+ :returns: An Authorizenet API response, if any.
151
+ :rtype: :py:obj:`dict` | :py:obj:`None`
123
152
 
124
153
  """
125
154
  assert self.id, "'id' was not set."
126
-
127
155
  request = apicontractsv1.getCustomerPaymentProfileRequest(
128
156
  merchantAuthentication=self.merchantAuthentication,
129
157
  customerProfileId=self.customerProfileId,
@@ -131,24 +159,26 @@ class PaymentProfile(AuthorizenetSubProfileBase):
131
159
  includeIssuerInfo=str(issuer_info).lower(),
132
160
  )
133
161
  controller = apicontrollers.getCustomerPaymentProfileController(request)
134
- response = self.execute_controller(controller)
135
- return response
162
+ return self.execute_controller(controller)
136
163
 
137
164
  def _authorizenet_update_payment_profile(
138
165
  self,
139
- billing_addr: apicontractsv1.customerAddressType,
166
+ address: apicontractsv1.customerAddressType,
140
167
  payment: apicontractsv1.paymentType,
141
- ) -> dict:
168
+ ) -> dict | None:
142
169
  """
143
- Executes a :py:obj:`~authorizenet.apicontractsv1.validateCustomerPaymentProfileRequest` using the Authorizenet API.
170
+ Executes a :py:obj:`~authorizenet.apicontractsv1.updateCustomerPaymentProfileRequest` using the Authorizenet API.
144
171
 
145
- :param billing_addr: A customer address.
146
- :type billing_addr: :py:obj:`~authorizenet.apicontractsv1.customerAddressType`
172
+ `updateCustomerPaymentProfileRequest <https://developer.authorize.net/api/reference/index.html#customer-profiles-update-customer-payment-profile>`_
173
+
174
+ :param address: A customer address.
175
+ :type address: :py:obj:`~authorizenet.apicontractsv1.customerAddressType`
147
176
  :param payment: A payment method.
148
177
  :type payment: :py:obj:`~authorizenet.apicontractsv1.paymentType`
149
178
  :raises AssertionError: If :py:attr:`id` wasn't set.
150
- :returns: An Authorizenet API response.
151
- :rtype: :py:obj:`dict`
179
+ :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
180
+ :returns: An Authorizenet API response, if any.
181
+ :rtype: :py:obj:`dict` | :py:obj:`None`
152
182
 
153
183
  """
154
184
  assert self.id, "'id' was not set."
@@ -157,7 +187,7 @@ class PaymentProfile(AuthorizenetSubProfileBase):
157
187
  merchantAuthentication=self.merchantAuthentication,
158
188
  customerProfileId=self.customerProfileId,
159
189
  paymentProfile=apicontractsv1.customerPaymentProfileType(
160
- billTo=billing_addr,
190
+ billTo=address,
161
191
  payment=payment,
162
192
  defaultPaymentProfile=self.default,
163
193
  customerPaymentProfileId=self.id,
@@ -165,20 +195,22 @@ class PaymentProfile(AuthorizenetSubProfileBase):
165
195
  validationMode=self.validationMode,
166
196
  )
167
197
  controller = apicontrollers.updateCustomerPaymentProfileController(request)
168
- response = self.execute_controller(controller)
169
- return response
198
+ return self.execute_controller(controller)
170
199
 
171
- def _authorizenet_validate_payment_profile(self) -> dict:
200
+ def _authorizenet_validate_payment_profile(self) -> dict | None:
172
201
  """
173
202
  Executes a :py:obj:`~authorizenet.apicontractsv1.validateCustomerPaymentProfileRequest` using the Authorizenet API.
174
203
 
204
+ `validateCustomerPaymentProfileRequest <https://developer.authorize.net/api/reference/index.html#customer-profiles-validate-customer-payment-profile>`_
205
+
175
206
  :raises AssertionError: If :py:attr:`id` wasn't set.
176
- :returns: An Authorizenet API response.
177
- :rtype: :py:obj:`dict`
207
+ :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
208
+ :returns: An Authorizenet API response, if any.
209
+ :rtype: :py:obj:`dict` | :py:obj:`None`
210
+
178
211
 
179
212
  """
180
213
  assert self.id, "'id' was not set."
181
-
182
214
  request = apicontractsv1.validateCustomerPaymentProfileRequest(
183
215
  merchantAuthentication=self.merchantAuthentication,
184
216
  customerProfileId=self.customerProfileId,
@@ -186,16 +218,18 @@ class PaymentProfile(AuthorizenetSubProfileBase):
186
218
  validationMode=self.validationMode,
187
219
  )
188
220
  controller = apicontrollers.validateCustomerPaymentProfileController(request)
189
- response = self.execute_controller(controller)
190
- return response
221
+ return self.execute_controller(controller)
191
222
 
192
- def _authorizenet_delete_payment_profile(self) -> dict:
223
+ def _authorizenet_delete_payment_profile(self) -> dict | None:
193
224
  """
194
225
  Executes a :py:obj:`~authorizenet.apicontractsv1.deleteCustomerPaymentProfileRequest` using the Authorizenet API.
195
226
 
227
+ `deleteCustomerPaymentProfileRequest <https://developer.authorize.net/api/reference/index.html#customer-profiles-delete-customer-payment-profile>`_
228
+
196
229
  :raises AssertionError: If :py:attr:`id` wasn't set.
197
- :returns: An Authorizenet API response.
198
- :rtype: :py:obj:`dict`
230
+ :raises ControllerExecutionError: If something goes wrong during an Authorizenet API call.
231
+ :returns: An Authorizenet API response, if any.
232
+ :rtype: :py:obj:`dict` | :py:obj:`None`
199
233
 
200
234
  """
201
235
  assert self.id, "'id' was not set."
@@ -206,5 +240,4 @@ class PaymentProfile(AuthorizenetSubProfileBase):
206
240
  customerPaymentProfileId=self.id,
207
241
  )
208
242
  controller = apicontrollers.deleteCustomerPaymentProfileController(request)
209
- response = self.execute_controller(controller)
210
- return response
243
+ return self.execute_controller(controller)
File without changes
@@ -1,12 +1,12 @@
1
1
  from authorizenet import apicontractsv1, apicontrollers
2
2
 
3
- from terminusgps.authorizenet.auth import get_merchant_auth
4
- from terminusgps.authorizenet.utils import ControllerExecutionMixin
3
+ from ..auth import get_merchant_auth
4
+ from ..utils import ControllerExecutionMixin
5
5
 
6
6
 
7
7
  class Subscription(ControllerExecutionMixin):
8
8
  def __init__(self, id: str | int | None = None, *args, **kwargs) -> None:
9
- if id and isinstance(id, str) and not id.isdigit():
9
+ if id is not None and isinstance(id, str) and not id.isdigit():
10
10
  raise ValueError(f"'id' must be a digit, got '{id}'.")
11
11
  self.id = int(id) if id else self.create(*args, **kwargs)
12
12
 
@@ -15,8 +15,9 @@ class Subscription(ControllerExecutionMixin):
15
15
  name: str,
16
16
  amount: str,
17
17
  schedule: apicontractsv1.paymentScheduleType,
18
- payment: apicontractsv1.paymentType,
19
- address: apicontractsv1.customerAddressType,
18
+ profile_id: int | str,
19
+ payment_id: int | str,
20
+ address_id: int | str,
20
21
  trial_amount: str = "0.00",
21
22
  ) -> int:
22
23
  request = apicontractsv1.ARBCreateSubscriptionRequest(
@@ -26,8 +27,11 @@ class Subscription(ControllerExecutionMixin):
26
27
  paymentSchedule=schedule,
27
28
  amount=amount,
28
29
  trialAmount=trial_amount,
29
- payment=payment,
30
- bill_to=address,
30
+ profile=apicontractsv1.customerProfileIdType(
31
+ customerProfileId=str(profile_id),
32
+ customerPaymentProfileId=str(payment_id),
33
+ customerAddressId=str(address_id),
34
+ ),
31
35
  ),
32
36
  )
33
37
  controller = apicontrollers.ARBCreateSubscriptionController(request)
@@ -2,17 +2,7 @@ from authorizenet import apicontractsv1, apicontrollers
2
2
  from authorizenet.apicontrollersbase import APIOperationBase
3
3
 
4
4
  from .auth import get_environment, get_merchant_auth
5
-
6
-
7
- class ControllerExecutionError(Exception):
8
- """Raised when an Authorizenet API controller fails to execute."""
9
-
10
- def __init__(self, message: str, code: str, *args, **kwargs) -> None:
11
- self.code = code
12
- super().__init__(message, *args, **kwargs)
13
-
14
- def __str__(self) -> str:
15
- return f"{self.code}: {self.message}"
5
+ from .errors import ControllerExecutionError
16
6
 
17
7
 
18
8
  class ControllerExecutionMixin:
@@ -57,5 +47,8 @@ def get_customer_profile_ids() -> list[int]:
57
47
  response = controller.getresponse()
58
48
 
59
49
  if response is not None and response.messages.resultCode != "Ok":
60
- raise ValueError(response.messages.message["text"].text)
50
+ raise ControllerExecutionError(
51
+ message=response.messages.message[0]["text"].text,
52
+ code=response.messages.message[0]["code"].text,
53
+ )
61
54
  return [int(id) for id in response.ids.getchildren()]