Skip to content
Closed
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
8 changes: 5 additions & 3 deletions mollie/api/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,11 @@ def _format_request_data(

querystring = generate_querystring(params)
if querystring:
url += "?" + querystring
if "?" in url:
# There is already a querystring in the URL
url += "&" + querystring
else:
url += "?" + querystring
params = None

return url, payload, params
Expand All @@ -204,7 +208,6 @@ def _perform_http_call_apikey(

url, payload, params = self._format_request_data(path, data, params)
try:

headers = {
"Accept": "application/json",
"Authorization": f"Bearer {self.api_key}",
Expand Down Expand Up @@ -239,7 +242,6 @@ def _perform_http_call_oauth(
) -> requests.Response:
url, payload, params = self._format_request_data(path, data, params)
try:

headers = {
"Accept": "application/json",
"Content-Type": "application/json",
Expand Down
4 changes: 2 additions & 2 deletions mollie/api/objects/balance.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ def pending_amount(self):
def get_report(self, **params: Any) -> BalanceReport:
from ..resources import BalanceReports

return BalanceReports(self.client, self).get_report(params=params)
return BalanceReports(self.client, resource_path=f"balances/{self.id}/report").get_report(params=params)

def get_transactions(self, **params: Any) -> ObjectList:
from ..resources import BalanceTransactions

return BalanceTransactions(self.client, self).list(params=params)
return BalanceTransactions(self.client, resource_path=f"balances/{self.id}/transactions").list(params=params)
6 changes: 0 additions & 6 deletions mollie/api/objects/balance_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,6 @@


class BalanceReport(ObjectBase):
@classmethod
def get_resource_class(cls, client):
from ..resources import BalanceReports

return BalanceReports(client)

@property
def resource(self):
return self._get_property("resource")
Expand Down
9 changes: 7 additions & 2 deletions mollie/api/objects/customer.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,21 @@ def created_at(self):
def subscriptions(self):
from ..resources import CustomerSubscriptions

return CustomerSubscriptions(self.client, self)
return CustomerSubscriptions(self.client, resource_path=f"customers/{self.id}/subscriptions")

@property
def mandates(self):
from ..resources import CustomerMandates

return CustomerMandates(self.client, self)
return CustomerMandates(self.client, resource_path=f"customers/{self.id}/mandates")

@property
def payments(self):
from ..resources import CustomerPayments

return CustomerPayments(self.client, self)

# Additional methods

def has_subscriptions(self):
return self._get_link("subscriptions") is not None
6 changes: 3 additions & 3 deletions mollie/api/objects/payment.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,14 +193,14 @@ def chargebacks(self):
"""Return the chargebacks related to this payment."""
from ..resources import PaymentChargebacks

return PaymentChargebacks(self.client, self)
return PaymentChargebacks(self.client, resource_path=f"payments/{self.id}/chargebacks")

@property
def captures(self):
"""Return the captures related to this payment"""
from ..resources import PaymentCaptures

return PaymentCaptures(self.client, self)
return PaymentCaptures(self.client, resource_path=f"payments/{self.id}/captures")

def get_settlement(self):
"""Return the settlement for this payment."""
Expand All @@ -224,7 +224,7 @@ def get_subscription(self):
if url:
from ..resources import CustomerSubscriptions

return CustomerSubscriptions(self.client, customer=None).from_url(url)
return CustomerSubscriptions(self.client).from_url(url)

def get_customer(self):
"""Return the customer for this payment."""
Expand Down
2 changes: 1 addition & 1 deletion mollie/api/objects/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def created_at(self):
def chargebacks(self):
from ..resources import ProfileChargebacks

return ProfileChargebacks(self.client, self)
return ProfileChargebacks(self.client, resource_path=f"chargebacks?profileId={self.id}")

@property
def methods(self):
Expand Down
4 changes: 2 additions & 2 deletions mollie/api/objects/settlement.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,14 @@ def chargebacks(self):
"""Return the chargebacks related to this settlement."""
from ..resources import SettlementChargebacks

return SettlementChargebacks(self.client, self)
return SettlementChargebacks(self.client, resource_path=f"settlements/{self.id}/chargebacks")

@property
def captures(self):
"""Return the captures related to this settlement."""
from ..resources import SettlementCaptures

return SettlementCaptures(self.client, self)
return SettlementCaptures(self.client, resource_path=f"settlements/{self.id}/captures")

def get_invoice(self):
"""Return the invoice related to this settlement."""
Expand Down
16 changes: 11 additions & 5 deletions mollie/api/objects/subscription.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import re

from .base import ObjectBase
from .customer import Customer


class Subscription(ObjectBase):
Expand Down Expand Up @@ -134,14 +133,21 @@ def get_mandate(self):
if self.mandate_id and self.customer_id:
from ..resources import CustomerMandates

customer = Customer({"id": self.customer_id}, self.client)
return CustomerMandates(self.client, customer).get(self.mandate_id)
return CustomerMandates(
self.client,
resource_path=f"customers/{self.customer_id}/mandates",
).get(self.mandate_id)

@property
def payments(self):
# We could also have implemented this using the "payments" entry from the _links, but then we would not have
# the explicit interface using .payments.list()
from ..resources import SubscriptionPayments

customer = Customer({"id": self.customer_id}, self.client)
return SubscriptionPayments(self.client, customer=customer, subscription=self)
url = self._get_link("payments")
return SubscriptionPayments(self.client, resource_path=url)

# Additional methods

def has_payments(self):
return self._get_link("payments") is not None
24 changes: 1 addition & 23 deletions mollie/api/resources/balances.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
from typing import TYPE_CHECKING, Any
from typing import Any

from mollie.api.objects.balance import Balance
from mollie.api.objects.balance_report import BalanceReport
from mollie.api.objects.balance_transaction import BalanceTransaction
from mollie.api.resources.base import ResourceBase, ResourceGetMixin, ResourceListMixin

if TYPE_CHECKING:
from ..client import Client


class Balances(ResourceGetMixin, ResourceListMixin):
RESOURCE_ID_PREFIX: str = "bal_"
Expand Down Expand Up @@ -42,38 +39,19 @@ def get(self, resource_id: str, **params: Any) -> Balance:


class BalanceReports(ResourceBase):

_balance: "Balance"

def __init__(self, client: "Client", balance: "Balance") -> None:
self._balance = balance
super().__init__(client)

def get_resource_object(self, result: dict) -> BalanceReport:
from ..objects.balance_report import BalanceReport

return BalanceReport(result, self.client)

def get_resource_path(self) -> str:
return f"balances/{self._balance.id}/report"

def get_report(self, **params: Any) -> BalanceReport:
path = self.get_resource_path()
result = self.perform_api_call(self.REST_READ, path, params=params)
return self.get_resource_object(result)


class BalanceTransactions(ResourceListMixin):
_balance: "Balance"

def __init__(self, client: "Client", balance: "Balance") -> None:
self._balance = balance
super().__init__(client)

def get_resource_object(self, result: dict) -> BalanceTransaction:
from ..objects.balance_transaction import BalanceTransaction

return BalanceTransaction(result, self.client)

def get_resource_path(self) -> str:
return f"balances/{self._balance.id}/transactions"
10 changes: 7 additions & 3 deletions mollie/api/resources/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ class ResourceBase:

RESOURCE_ID_PREFIX: str = ""

def __init__(self, client: "Client") -> None:
def __init__(self, client: "Client", resource_path: str = "") -> None:
self.client = client
self.resource_path = resource_path

def get_resource_object(self, result: dict) -> Any:
"""
Expand All @@ -34,7 +35,11 @@ def get_resource_object(self, result: dict) -> Any:

def get_resource_path(self) -> str:
"""Return the base URL path in the API for this resource."""
return self.__class__.__name__.lower()
if self.resource_path:
return self.resource_path
else:
# Generate a default path for the resource
return self.__class__.__name__.lower()

def perform_api_call(
self,
Expand All @@ -44,7 +49,6 @@ def perform_api_call(
params: Optional[Dict[str, Any]] = None,
idempotency_key: str = "",
) -> Dict[str, Any]:

resp = self.client.perform_http_call(http_method, path, data, params, idempotency_key)
if "application/hal+json" in resp.headers.get("Content-Type", ""):
# set the content type according to the media type definition
Expand Down
25 changes: 2 additions & 23 deletions mollie/api/resources/captures.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
from typing import TYPE_CHECKING, Any
from typing import Any

from ..objects.capture import Capture
from .base import ResourceBase, ResourceGetMixin, ResourceListMixin

if TYPE_CHECKING:
from ..client import Client
from ..objects.payment import Payment
from ..objects.settlement import Settlement

__all__ = [
"PaymentCaptures",
"SettlementCaptures",
Expand All @@ -24,15 +19,6 @@ def get_resource_object(self, result: dict) -> Capture:
class PaymentCaptures(CapturesBase, ResourceGetMixin, ResourceListMixin):
"""Resource handler for the `/payments/:payment_id:/captures` endpoint."""

_payment: "Payment"

def __init__(self, client: "Client", payment: "Payment") -> None:
self._payment = payment
super().__init__(client)

def get_resource_path(self) -> str:
return f"payments/{self._payment.id}/captures"

def get(self, resource_id: str, **params: Any) -> Capture:
self.validate_resource_id(resource_id, "capture ID")
return super().get(resource_id, **params)
Expand All @@ -41,11 +27,4 @@ def get(self, resource_id: str, **params: Any) -> Capture:
class SettlementCaptures(CapturesBase, ResourceListMixin):
"""Resource handler for the `/settlements/:settlement_id:/captures` endpoint."""

_settlement: "Settlement"

def __init__(self, client: "Client", settlement: "Settlement") -> None:
self._settlement = settlement
super().__init__(client)

def get_resource_path(self) -> str:
return f"settlements/{self._settlement.id}/captures"
pass
42 changes: 5 additions & 37 deletions mollie/api/resources/chargebacks.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
from typing import TYPE_CHECKING, Any
from typing import Any

from ..objects.chargeback import Chargeback
from ..objects.list import ObjectList
from .base import ResourceBase, ResourceGetMixin, ResourceListMixin

if TYPE_CHECKING:
from ..client import Client
from ..objects.payment import Payment
from ..objects.profile import Profile
from ..objects.settlement import Settlement

__all__ = [
"Chargebacks",
"PaymentChargebacks",
Expand All @@ -34,15 +27,6 @@ class Chargebacks(ChargebacksBase, ResourceListMixin):
class PaymentChargebacks(ChargebacksBase, ResourceGetMixin, ResourceListMixin):
"""Resource handler for the `/payments/:payment_id:/chargebacks` endpoint."""

_payment: "Payment"

def __init__(self, client: "Client", payment: "Payment") -> None:
self._payment = payment
super().__init__(client)

def get_resource_path(self) -> str:
return f"payments/{self._payment.id}/chargebacks"

def get(self, resource_id: str, **params: Any) -> Chargeback:
self.validate_resource_id(resource_id, "chargeback ID")
return super().get(resource_id, **params)
Expand All @@ -51,30 +35,14 @@ def get(self, resource_id: str, **params: Any) -> Chargeback:
class SettlementChargebacks(ChargebacksBase, ResourceListMixin):
"""Resource handler for the `/settlements/:settlement_id:/chargebacks` endpoint."""

_settlement: "Settlement"

def __init__(self, client: "Client", settlement: "Settlement") -> None:
self._settlement = settlement
super().__init__(client)

def get_resource_path(self) -> str:
return f"settlements/{self._settlement.id}/chargebacks"
pass


class ProfileChargebacks(ChargebacksBase):
class ProfileChargebacks(Chargebacks):
"""
Resource handler for the `/chargebacks?profileId=:profile_id:` endpoint.

This is separate from the `Chargebacks` resource handler to make it easier to inject the profileId.
This is completely equal to Chargebacks, just here for completeness.
"""

_profile: "Profile"

def __init__(self, client: "Client", profile: "Profile") -> None:
self._profile = profile
super().__init__(client)

def list(self, **params: Any) -> ObjectList:
# Set the profileId in the query params
params.update({"profileId": self._profile.id})
return Chargebacks(self.client).list(**params)
pass
16 changes: 1 addition & 15 deletions mollie/api/resources/mandates.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
from typing import TYPE_CHECKING, Any
from typing import Any

from ..objects.customer import Customer
from ..objects.mandate import Mandate
from .base import ResourceCreateMixin, ResourceDeleteMixin, ResourceGetMixin, ResourceListMixin

if TYPE_CHECKING:
from ..client import Client


__all__ = [
"CustomerMandates",
]
Expand All @@ -18,15 +13,6 @@ class CustomerMandates(ResourceCreateMixin, ResourceDeleteMixin, ResourceGetMixi

RESOURCE_ID_PREFIX = "mdt_"

_customer: Customer

def __init__(self, client: "Client", customer: Customer) -> None:
self._customer = customer
super().__init__(client)

def get_resource_path(self) -> str:
return f"customers/{self._customer.id}/mandates"

def get_resource_object(self, result: dict) -> Mandate:
return Mandate(result, self.client)

Expand Down
Loading