diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 99c16e624..35810719a 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,8 +1,8 @@ ## Specifications - - API Version: + - API Version: + - SDK Version: ## Describe the issue ... - diff --git a/.github/workflows/check_php_syntax.yml b/.github/workflows/check_php_syntax.yml index ed5868e85..93af72e0a 100644 --- a/.github/workflows/check_php_syntax.yml +++ b/.github/workflows/check_php_syntax.yml @@ -3,18 +3,18 @@ on: push: pull_request: schedule: - - cron: '0 0 * * *' + - cron: "0 0 * * *" jobs: tests: runs-on: ubuntu-latest strategy: fail-fast: true matrix: - php: [ 7.2 ] + php: [7.4] name: Check PHP ${{ matrix.php }} syntax steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup PHP uses: shivammathur/setup-php@v2 with: diff --git a/.github/workflows/createzip.yml b/.github/workflows/createzip.yml index 2873d8c84..40da216f8 100644 --- a/.github/workflows/createzip.yml +++ b/.github/workflows/createzip.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup PHP uses: shivammathur/setup-php@v2 with: @@ -38,7 +38,7 @@ jobs: sed -i.bak 's/autoload.php/composer-autoload.php/g' build/vendor/scoper-autoload.php mv build/vendor/scoper-autoload.php build/vendor/autoload.php - name: Install zip - uses: montudor/action-zip@v0.1.1 + uses: montudor/action-zip@v1 - name: Finally, create a zip file with all built files. run: zip -r mollie-api-php.zip examples src vendor composer.json LICENSE README.md working-directory: build diff --git a/.github/workflows/fix-codestyle.yml b/.github/workflows/fix-codestyle.yml new file mode 100644 index 000000000..66be903f0 --- /dev/null +++ b/.github/workflows/fix-codestyle.yml @@ -0,0 +1,33 @@ +name: Fix Code Style + +on: [push] + +jobs: + lint: + runs-on: ubuntu-latest + strategy: + fail-fast: true + matrix: + php: [8.4] + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: json, dom, curl, libxml, mbstring + coverage: none + + - name: Install Pint + run: composer global require laravel/pint + + - name: Run Pint + run: pint + + - name: Commit linted files + uses: stefanzweifel/git-auto-commit-action@v5 + with: + commit_message: "Fixes coding style" diff --git a/.github/workflows/php-cs-fixer.yml b/.github/workflows/php-cs-fixer.yml deleted file mode 100644 index a83d7080b..000000000 --- a/.github/workflows/php-cs-fixer.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Check & fix styling - -on: [push] - -jobs: - php-cs-fixer: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v2 - with: - ref: ${{ github.head_ref }} - - - name: Run PHP CS Fixer - uses: docker://oskarstark/php-cs-fixer-ga - with: - args: --config=.php-cs-fixer.dist.php --allow-risky=yes - - - name: Commit changes - uses: stefanzweifel/git-auto-commit-action@v4 - with: - commit_message: Fix styling diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index dc409b109..c9b246124 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -3,18 +3,18 @@ on: push: pull_request: schedule: - - cron: '0 0 * * *' + - cron: "0 0 * * *" jobs: tests: runs-on: ubuntu-latest strategy: fail-fast: true matrix: - php: [7.2, 7.3, 7.4, 8.0, 8.1, 8.2, 8.3, 8.4] + php: [7.4, 8.0, 8.1, 8.2, 8.3, 8.4] name: PHP - ${{ matrix.php }} steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Setup PHP uses: shivammathur/setup-php@v2 with: @@ -22,16 +22,15 @@ jobs: extensions: dom, curl, libxml, mbstring, zip tools: composer:v2 coverage: none - - name: Remove PHP CS Fixer dependency to prevent unnecessary dependency collisions + - name: Remove pint dependency to prevent unnecessary dependency collisions run: | - composer remove --dev friendsofphp/php-cs-fixer + composer remove --dev laravel/pint - name: Install dependencies run: | composer update --prefer-dist --no-interaction --no-progress - name: PHPStan - if: ${{ matrix.php >= 7.3 }} run: | - composer require "phpstan/phpstan:1.12.5" + composer require "phpstan/phpstan" --dev vendor/bin/phpstan analyse --no-progress - name: Execute tests - run: vendor/bin/phpunit --verbose + run: vendor/bin/paratest --verbose diff --git a/.github/workflows/update-changelog.yml b/.github/workflows/update-changelog.yml new file mode 100644 index 000000000..0cdea2336 --- /dev/null +++ b/.github/workflows/update-changelog.yml @@ -0,0 +1,28 @@ +name: "Update Changelog" + +on: + release: + types: [released] + +jobs: + update: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: main + + - name: Update Changelog + uses: stefanzweifel/changelog-updater-action@v1 + with: + latest-version: ${{ github.event.release.name }} + release-notes: ${{ github.event.release.body }} + + - name: Commit updated CHANGELOG + uses: stefanzweifel/git-auto-commit-action@v5 + with: + branch: main + commit_message: Update CHANGELOG + file_pattern: CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..20456c3d7 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,8 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased](https://github.com/mollie/mollie-api-php/compare/v3.0.0...HEAD) diff --git a/README.md b/README.md index faa1275e3..a96330bf7 100644 --- a/README.md +++ b/README.md @@ -32,14 +32,6 @@ The easiest way to install the Mollie API client is by using [Composer](http://g composer require mollie/mollie-api-php ``` -To work with the most recent API version, ensure that you are using a version of this API client that is equal to or greater than 2.0.0. If you prefer to continue using the v1 API, make sure your client version is below 2.0.0. For guidance on transitioning from v1 to v2, please refer to the [migration notes](https://docs.mollie.com/docs/migrating-from-v1-to-v2). - -### Manual Installation ### -If you're not familiar with using composer we've added a ZIP file to the releases containing the API client and all the packages normally installed by composer. -Download the ``mollie-api-php.zip`` from the [releases page](https://github.com/mollie/mollie-api-php/releases). - -Include the ``vendor/autoload.php`` as shown in [Initialize example](https://github.com/mollie/mollie-api-php/blob/master/examples/initialize.php). - ## Usage ## Initializing the Mollie API client, and setting your API key. @@ -49,355 +41,70 @@ $mollie = new \Mollie\Api\MollieApiClient(); $mollie->setApiKey("test_dHar4XY7LxsDOtmnkVtjNVWXLSlXsM"); ``` -With the `MollieApiClient` you can now access any of the following endpoints by selecting them as a property of the client: - -| API | Resource | Code | Link to Endpoint file | -| ----------------------- | ----------------------- | -------------------------- | -------------------------------------------------------------------------- | -| **[Balances API](https://docs.mollie.com/reference/v2/balances-api/overview)** | Balance | `$mollie->balances` | [BalanceEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/BalanceEndpoint.php) | -| | Balance Report | `$mollie->balanceReports` | [BalanceReportEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/BalanceReportEndpoint.php) | -| | Balance Transaction | `$mollie->balanceTransactions` | [BalanceTransactionEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/BalanceTransactionEndpoint.php) | -| **[Chargebacks API](https://docs.mollie.com/reference/v2/chargebacks-api/overview)** | Chargeback |`$mollie->chargebacks` | [ChargebackEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/ChargebackEndpoint.php) | -| | Payment Chargeback | `$mollie->paymentChargebacks` | [PaymentChargebackEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/PaymentChargebackEndpoint.php) | -| **[Clients API](https://docs.mollie.com/reference/v2/clients-api/overview)** | Client | `$mollie->clients` | [ClientEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/ClientEndpoint.php) | -| **[Client Links API](https://docs.mollie.com/reference/v2/client-links-api/overview)** | Client Link | `$mollie->clientLinks` | [ClientLinkEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/ClientLinkEndpoint.php) | -| **[Customers API](https://docs.mollie.com/reference/v2/customers-api/overview)** | Customer | `$mollie->customers` | [CustomerEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/CustomerEndpoint.php) | -| | Customer Payment | `$mollie->customerPayments` | [CustomerPaymentsEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/CustomerPaymentsEndpoint.php) | -| **[Invoices API](https://docs.mollie.com/reference/v2/invoices-api/overview)** | Invoice | `$mollie->invoices` | [InvoiceEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/InvoiceEndpoint.php) | -| **[Mandates API](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/MandateEndpoint.php)** | Mandate | `$mollie->mandates` | [MandateEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/MandateEndpoint.php) | -| **[Methods API](https://docs.mollie.com/reference/v2/methods-api/overview)** | Payment Method | `$mollie->methods` | [MethodEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/MethodEndpoint.php) | -| **[Onboarding API](https://docs.mollie.com/reference/v2/onboarding-api/overview)** | Onboarding |`$mollie->onboarding` | [OnboardingEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/OnboardingEndpoint.php) | -| **[Orders API](https://docs.mollie.com/reference/v2/orders-api/overview)** | Order | `$mollie->orders` | [OrderEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/OrderEndpoint.php) | -| | Order Line | `$mollie->orderLines` | [OrderLineEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/OrderLineEndpoint.php) | -| | Order Payment | `$mollie->orderPayments` | [OrderPaymentEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/OrderPaymentEndpoint.php) | -| **[Organizations API](https://docs.mollie.com/reference/v2/organizations-api/overview)** | Organization | `$mollie->organizations` | [OrganizationEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/OrganizationEndpoint.php) | -| | Organization Partner | `$mollie->organizationPartners` | [OrganizationPartnerEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/OrganizationPartnerEndpoint.php) | -| **[Captures API](https://docs.mollie.com/reference/v2/captures-api/overview)** | Payment Captures | `$mollie->organizations` | [PaymentCaptureEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/PaymentCaptureEndpoint.php) | -| **[Payments API](https://docs.mollie.com/reference/v2/payments-api/overview)** | Payment | `$mollie->payments` | [PaymentEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/PaymentEndpoint.php) | -| | Payment Route | `$mollie->paymentRoutes` | [PaymentRouteEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/PaymentRouteEndpoint.php) | -| **[Payment links API](https://docs.mollie.com/reference/v2/payment-links-api/overview)** | Payment Link | `$mollie->paymentLinks` | [PaymentLinkEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/PaymentLinkEndpoint.php) | -| **[Permissions API](https://docs.mollie.com/reference/v2/permissions-api/overview)** | Permission | `$mollie->permissions` | [PermissionEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/PermissionEndpoint.php) | -| **[Profile API](https://docs.mollie.com/reference/v2/profiles-api/overview)** | Profile | `$mollie->profiles` | [ProfileEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/ProfileEndpoint.php) | -| | Profile Method | `$mollie->profileMethods` | [ProfileMethodEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/ProfileMethodEndpoint.php) | -| **[Refund API](https://docs.mollie.com/reference/v2/refunds-api/overview)** | Refund | `$mollie->refunds` | [RefundEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/RefundEndpoint.php) | -| | Order Refund | `$mollie->orderRefunds` | [OrderRefundEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/OrderRefundEndpoint.php) | -| | Payment Refund | `$mollie->paymentRefunds` | [PaymentRefundEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/PaymentRefundEndpoint.php) | -| **[Settlements API](https://docs.mollie.com/reference/v2/settlements-api/overview)** | Settlement | `$mollie->settlements` | [SettlementsEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/SettlementsEndpoint.php) | -| | Settlement Capture | `$mollie->settlementCaptures` | [SettlementCaptureEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/SettlementCaptureEndpoint.php) | -| | Settlement Chargeback | `$mollie->settlementChargebacks` | [SettlementChargebackEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/SettlementChargebackEndpoint.php) | -| | Settlement Payment | `$mollie->settlementPayments` | [SettlementPaymentEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/SettlementPaymentEndpoint.php) | -| | Settlement Refund | `$mollie->settlementRefunds` | [SettlementRefundEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/SettlementRefundEndpoint.php) | -| **[Shipments API](https://docs.mollie.com/reference/v2/shipments-api/overview)** | Shipment | `$mollie->shipments` | [ShipmentEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/ShipmentEndpoint.php) | -| **[Subscriptions API](https://docs.mollie.com/reference/v2/subscriptions-api/overview)** | Subscription | `$mollie->subscriptions` | [SubscriptionEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/SubscriptionEndpoint.php) | -| **[Terminal API](https://docs.mollie.com/reference/v2/terminals-api/overview)** | Terminal | `$mollie->terminals` | [TerminalEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/TerminalEndpoint.php) | -| **[Wallets API](https://docs.mollie.com/reference/v2/wallets-api/overview)** | Wallet | `$mollie->wallets` | [WalletEndpoint](https://github.com/mollie/mollie-api-php/blob/master/src/Endpoints/WalletEndpoint.php) | - Find our full documentation online on [docs.mollie.com](https://docs.mollie.com). -### Orders ### -#### Creating Orders #### -**[Create Order reference](https://docs.mollie.com/reference/v2/orders-api/create-order)** - -```php -$order = $mollie->orders->create([ - "amount" => [ - "value" => "1027.99", - "currency" => "EUR", - ], - "billingAddress" => [ - "streetAndNumber" => "Keizersgracht 313", - "postalCode" => "1016 EE", - "city" => "Amsterdam", - "country" => "nl", - "givenName" => "Luke", - "familyName" => "Skywalker", - "email" => "luke@skywalker.com", - ], - "shippingAddress" => [ - "streetAndNumber" => "Keizersgracht 313", - "postalCode" => "1016 EE", - "city" => "Amsterdam", - "country" => "nl", - "givenName" => "Luke", - "familyName" => "Skywalker", - "email" => "luke@skywalker.com", - ], - "metadata" => [ - "some" => "data", - ], - "consumerDateOfBirth" => "1958-01-31", - "locale" => "en_US", - "orderNumber" => "1234", - "redirectUrl" => "https://your_domain.com/return?some_other_info=foo", - "webhookUrl" => "https://your_domain.com/webhook", - "method" => "ideal", - "lines" => [ - [ - "sku" => "5702016116977", - "name" => "LEGO 42083 Bugatti Chiron", - "productUrl" => "https://shop.lego.com/nl-NL/Bugatti-Chiron-42083", - "imageUrl" => 'https://sh-s7-live-s.legocdn.com/is/image//LEGO/42083_alt1?$main$', - "quantity" => 2, - "vatRate" => "21.00", - "unitPrice" => [ - "currency" => "EUR", - "value" => "399.00", - ], - "totalAmount" => [ - "currency" => "EUR", - "value" => "698.00", - ], - "discountAmount" => [ - "currency" => "EUR", - "value" => "100.00", - ], - "vatAmount" => [ - "currency" => "EUR", - "value" => "121.14", - ], - ], - // more order line items - ], -]); -``` - -_After creation, the order id is available in the `$order->id` property. You should store this id with your order._ - -After storing the order id you can send the customer off to complete the order payment using `$order->getCheckoutUrl()`. - -```php -header("Location: " . $order->getCheckoutUrl(), true, 303); -``` - -_This header location should always be a GET, thus we enforce 303 http response code_ - -For an order create example, see [Example - New Order](https://github.com/mollie/mollie-api-php/blob/master/examples/orders/create-order.php). - -#### Updating Orders #### -**[Update Order Documentation](https://docs.mollie.com/reference/v2/orders-api/update-order)** - -```php -$order = $mollie->orders->get("ord_kEn1PlbGa"); -$order->billingAddress->organizationName = "Mollie B.V."; -$order->billingAddress->streetAndNumber = "Keizersgracht 126"; -$order->billingAddress->city = "Amsterdam"; -$order->billingAddress->region = "Noord-Holland"; -$order->billingAddress->postalCode = "1234AB"; -$order->billingAddress->country = "NL"; -$order->billingAddress->title = "Dhr"; -$order->billingAddress->givenName = "Piet"; -$order->billingAddress->familyName = "Mondriaan"; -$order->billingAddress->email = "piet@mondriaan.com"; -$order->billingAddress->phone = "+31208202070"; -$order->update(); -``` - -#### Refunding Orders #### -##### Complete ##### -```php -$order = $mollie->orders->get('ord_8wmqcHMN4U'); -$refund = $order->refundAll(); - -echo 'Refund ' . $refund->id . ' was created for order ' . $order->id; -``` - -##### Partially ##### -When executing a partial refund you have to list all order line items that should be refunded. - -```php -$order = $mollie->orders->get('ord_8wmqcHMN4U'); -$refund = $order->refund([ - 'lines' => [ - [ - 'id' => 'odl_dgtxyl', - 'quantity' => 1, - ], - ], - "description" => "Required quantity not in stock, refunding one photo book.", -]); -``` - -#### Cancel Orders #### -**[Cancel Order Documentation](https://docs.mollie.com/reference/v2/orders-api/cancel-order)** - -_When canceling an order it is crucial to check if the order is cancelable before executing the cancel action. For more information see the [possible order statuses](https://docs.mollie.com/orders/status-changes#possible-statuses-for-orders)._ - +#### Example usage #### ```php -$order = $mollie->orders->get("ord_pbjz8x"); - -if ($order->isCancelable) { - $canceledOrder = $order->cancel(); - echo "Your order " . $order->id . " has been canceled."; -} else { - echo "Unable to cancel your order " . $order->id . "."; -} -``` +use Mollie\Api\Http\Data\Money; +use Mollie\Api\Http\Data\CreatePaymentPayload; +use Mollie\Api\Http\Requests\CreatePaymentRequest; -#### Order webhook #### -When the order status changes, the `webhookUrl` you specified during order creation will be called. You can use the `id` from the POST parameters to check the status and take appropriate actions. For more details, refer to [Example - Webhook](https://github.com/mollie/mollie-api-php/blob/master/examples/orders/webhook.php). +$payload = new CreatePaymentPayload( + description: 'My first API payment', + amount: new Money('EUR', '10.00'), + redirectUrl: 'https://webshop.example.org/order/12345/', + webhookUrl: 'https://webshop.example.org/mollie-webhook/' +); -### Payments ### -#### Payment Reception Process #### -**[Payment Reception Process documentation](https://docs.mollie.com/payments/accepting-payments#working-with-the-payments-api)** +/** @var Mollie\Api\Http\Response $response */ +$response = $mollie->send(new CreatePaymentRequest($payload)); -To ensure a successful payment reception, you should follow these steps: - -1. Utilize the Mollie API client to initiate a payment. Specify the desired amount, currency, description, and optionally, a payment method. It's crucial to define a unique redirect URL where the customer should be directed after completing the payment. - -2. Immediately upon payment completion, our platform will initiate an asynchronous request to the configured webhook. This enables you to retrieve payment details, ensuring you know precisely when to commence processing the customer's order. - -3. The customer is redirected to the URL from step (1) and should be pleased to find that the order has been paid and is now in the processing stage. - - -#### Creating Payments #### -**[Create Payment Documentation](https://docs.mollie.com/reference/v2/payments-api/create-payment)** - -```php -$payment = $mollie->payments->create([ - "amount" => [ - "currency" => "EUR", - "value" => "10.00" - ], - "description" => "My first API payment", - "redirectUrl" => "https://webshop.example.org/order/12345/", - "webhookUrl" => "https://webshop.example.org/mollie-webhook/", -]); +/** @var Mollie\Api\Resources\Payment $payment */ +$payment = $response->toResource(); ``` -_After creation, the payment id is available in the `$payment->id` property. You should store this id with your order._ - -After storing the payment id you can send the customer to the checkout using `$payment->getCheckoutUrl()`. -```php -header("Location: " . $payment->getCheckoutUrl(), true, 303); -``` - -_This header location should always be a GET, thus we enforce 303 http response code_ - -For a payment create example, see [Example - New Payment](https://github.com/mollie/mollie-api-php/blob/master/examples/payments/create-payment.php). - -##### Multicurrency ##### -Since API v2.0 it is now possible to create non-EUR payments for your customers. -A full list of available currencies can be found [in our documentation](https://docs.mollie.com/guides/multicurrency). - -```php -$payment = $mollie->payments->create([ - "amount" => [ - "currency" => "USD", - "value" => "10.00" - ], - //... -]); -``` -_After creation, the `settlementAmount` will contain the EUR amount that will be settled on your account._ - -##### Create fully integrated iDEAL payments ##### -To fully integrate iDEAL payments on your website, follow these additional steps: - -1. Retrieve the list of issuers (banks) that support iDEAL. - -```php -$method = $mollie->methods->get(\Mollie\Api\Types\PaymentMethod::IDEAL, ["include" => "issuers"]); -``` - -Use the `$method->issuers` list to let the customer pick their preferred issuer. - -_`$method->issuers` will be a list of objects. Use the property `$id` of this object in the - API call, and the property `$name` for displaying the issuer to your customer._ - -2. Create a payment with the selected issuer: - -```php -$payment = $mollie->payments->create([ - "amount" => [ - "currency" => "EUR", - "value" => "10.00" - ], - "description" => "My first API payment", - "redirectUrl" => "https://webshop.example.org/order/12345/", - "webhookUrl" => "https://webshop.example.org/mollie-webhook/", - "method" => \Mollie\Api\Types\PaymentMethod::IDEAL, - "issuer" => $selectedIssuerId, // e.g. "ideal_INGBNL2A" -]); -``` - -_The `_links` property of the `$payment` object will contain an object `checkout` with a `href` property, which is a URL that points directly to the online banking environment of the selected issuer. -A short way of retrieving this URL can be achieved by using the `$payment->getCheckoutUrl()`._ - -For a more in-depth example, see [Example - iDEAL payment](https://github.com/mollie/mollie-api-php/blob/master/examples/payments/create-ideal-payment.php). - -#### Retrieving Payments #### -**[Retrieve Payment Documentation](https://docs.mollie.com/reference/v2/payments-api/get-payment)** - -We can use the `$payment->id` to retrieve a payment and check if the payment `isPaid`. - -```php -$payment = $mollie->payments->get($payment->id); - -if ($payment->isPaid()) -{ - echo "Payment received."; -} -``` - -Or retrieve a collection of payments. - -```php -$payments = $mollie->payments->page(); -``` - -For an extensive example of listing payments with the details and status, see [Example - List Payments](https://github.com/mollie/mollie-api-php/blob/master/examples/payments/list-payments.php). +## Documentation +For an in-depth understanding of our API, please explore the [Mollie Developer Portal](https://www.mollie.com/developers). Our API documentation is available in English. -#### Refunding payments #### -**[Refund Payment Documentation](https://docs.mollie.com/reference/v2/refunds-api/create-payment-refund)** +For detailed documentation about using this PHP client, see the following guides: -Our API provides support for refunding payments. It's important to note that there is no confirmation step, and all refunds are immediate and final. Refunds are available for all payment methods except for paysafecard and gift cards. +- [Endpoint Collections](docs/endpoint-collections.md) - Learn how to interact with all available API endpoints. +- [HTTP Adapters](docs/http-adapters.md) - Information on customizing HTTP communication. +- [Idempotency](docs/idempotency.md) - Best practices and setup for idempotent requests. +- [Payments](docs/payments.md) - Comprehensive guide on handling payments. +- [Requests](docs/requests.md) - Overview and usage of request objects in the API client. +- [Responses](docs/responses.md) - Handling and understanding responses from the API. +- [Testing](docs/testing.md) - Guidelines for testing with the Mollie API client. -```php -$payment = $mollie->payments->get($payment->id); - -// Refund € 2 of this payment -$refund = $payment->refund([ - "amount" => [ - "currency" => "EUR", - "value" => "2.00" - ] -]); -``` +These guides provide in-depth explanations and examples for advanced usage of the client. -#### Payment webhook #### -When the payment status changes, the `webhookUrl` you specified during payment creation will be called. You can use the `id` from the POST parameters to check the status and take appropriate actions. For more details, refer to [Example - Webhook](https://github.com/mollie/mollie-api-php/blob/master/examples/payments/webhook.php). +## Examples -For a working example, see [Example - Refund payment](https://github.com/mollie/mollie-api-php/blob/master/examples/payments/refund-payment.php). +The Mollie API client comes with a variety of examples to help you understand how to implement various API features. These examples are a great resource for learning how to integrate Mollie payments into your application. -### Enabling debug mode ### +Here are some of the key examples included: -When troubleshooting, it can be highly beneficial to have access to the submitted request within the `ApiException`. To safeguard against inadvertently exposing sensitive request data in your local application logs, the debugging feature is initially turned off. +- **Create Payment**: Demonstrates how to create a new payment. + - [Create a simple payment](examples/payments/create-payment.php) + - [Create an iDEAL payment](examples/payments/create-ideal-payment.php) + - [Create a payment with manual capture](examples/payments/create-capturable-payment.php) -To enable debugging and inspect the request: +- **Manage Customers**: Shows how to manage customers in your Mollie account. + - [Create a customer](examples/customers/create-customer.php) + - [Update a customer](examples/customers/update-customer.php) + - [Delete a customer](examples/customers/delete-customer.php) -```php -/** @var $mollie \Mollie\Api\MollieApiClient */ -$mollie->enableDebugging(); - -try { - $mollie->payments->get('tr_12345678'); -} catch (\Mollie\Api\Exceptions\ApiException $exception) { - $request = $exception->getRequest(); -} -``` +- **Subscriptions and Recurring Payments**: + - [Create a customer for recurring payments](examples/customers/create-customer-first-payment.php) + - [Create a recurring payment](examples/customers/create-customer-recurring-payment.php) -If you are recording instances of `ApiException`, the request details will be included in the logs. It is vital to ensure that no sensitive information is retained within these logs and to perform cleanup after debugging is complete. +For a full list of examples, please refer to the [examples directory](examples/). -To disable debugging again: +These examples are designed to be run in a safe testing environment. Make sure to use your test API keys and review each example's code before integrating it into your production environment. -```php -/** @var $mollie \Mollie\Api\MollieApiClient */ -$mollie->disableDebugging(); -``` +## Upgrading -Please note that debugging is only available when using the default Guzzle http adapter (`Guzzle6And7MollieHttpAdapter`). - -## API documentation ## -For an in-depth understanding of our API, please explore the [Mollie Developer Portal](https://www.mollie.com/developers). Our API documentation is available in English. +Please see [UPGRADING](UPGRADING.md) for details. ## Contributing to Our API Client ## Would you like to contribute to improving our API client? We welcome [pull requests](https://github.com/mollie/mollie-api-php/pulls?utf8=%E2%9C%93&q=is%3Apr). But, if you're interested in contributing to a technology-focused organization, Mollie is actively recruiting developers and system engineers. Discover our current [job openings](https://jobs.mollie.com/) or [reach out](mailto:personeel@mollie.com). diff --git a/UPGRADING.md b/UPGRADING.md new file mode 100644 index 000000000..4b9363491 --- /dev/null +++ b/UPGRADING.md @@ -0,0 +1,277 @@ +- [x] remove `OrganizationsCollection` and change parent class of `OrganizationEndpoint` to `EndpointAbstract` +- [x] remove `RouteCollection` and change parent class of `PaymentRouteEndpoint` to `EndpointAbstract` +- [ ] check naming methods and standardise them (e.g. `SettlementCaptureEndpoint@pageForId()` vs `PaymentChargbackEndpoint@listForId()`) +- [x] Type cast embedded resources. I.e. when including refunds and chargebacks on a GET payment request, the refunds and chargebacks are not type cast. +- [x] [PSR-18 Support](https://github.com/mollie/mollie-api-php/issues/703) +- [ ] ~~rename `MethodEndpoint@all()` or remove it to avoid confusion over `allAvailable()` vs `all()`~~ -> marked as deprecated +- [x] Add Type: CaptureMode +- [x] change return types on resources +- [ ] check resources that have embedded resources whether they need to call an endpoint to provide the data +- [ ] check endpoint calls in resources for unnecessary code + - [x] check if we can add a trait for getPresetOptions and withPresetOptions +- [x] removed deprecated OrderStatus::REFUNDED OrderLineStatus::REFUNDED +- [x] refactored collections for easier usage +- [ ] update documentation +- [ ] add sessions endpoint (added by @sandervanhooft) +--- +Posting this here for now. For the upgrading steps I have created a separate file. For the changelog we don't have any file yet. May be worth to start a `CHANGELOG.md` file which is automatically filled via a github action from the release notes. + +# Upgrading +## From v2 to v3 +### Removed unused Collections +This change should not have any impact on your code, but if you have a type hint for any of the following classes, make sure to remove it +- `Mollie\Api\Resources\OrganizationCollection` +- `Mollie\Api\Resources\RouteCollection` + +### Removed deprecations +The following was removed due to a deprecation +- `Mollie\Api\Types\OrderStatus::REFUNDED` +- `Mollie\Api\Types\OrderLineStatus::REFUNDED` +- all Orders related endpoints + - properties starting with `orders` prefix or related to any `Order*Endpoint` + - `orderPayments` + - `orderRefunds` + - `orderLines` + - `orderPayments` + - Shipments endpoint (all properties prefixed with `shipments` / `Shipment*Endpoint`) + +### Removed non-valid method params +**Mollie\Api\EndpointCollection\CustomerPaymentsEndpointCollection** +- `createFor()` and `createForId()` removed third argument `$filters` + +**Mollie\Api\EndpointCollection\InvoiceEndpointCollection** +- `get()` removed second argument `$parameters` + +**Mollie\Api\EndpointCollection\MandateEndpointCollection** +- `createFor()` and `createForId()` removed third argument `$filters` + +**Mollie\Api\EndpointCollection\PaymentCaptureEndpointCollection** +- `createFor()` and `createForId()` removed third argument `$filters` + +### Removed methods +**Mollie\Api\EndpointCollection\InvoiceEndpointCollection** +- `all()` was removed -> use `page()` instead + +### change of function names +Accross the codebase we have had inconsistent namings like `listFor()` as well as `pageFor()` and `page()`. Those have been standardized. Endpoints that return a paginated response use the `page*()` naming while non-paginated endpoints use `list*()`. The following method names were changed. + +**Mollie\Api\EndpointCollection\BalanceTransactionEndpointCollection** +- `balanceTransactions->listFor()` into `balanceTransactions->pageFor()` +- `balanceTransactions->listForId()` into `balanceTransactions->pageForId()` + +**Mollie\Api\EndpointCollection\CustomerPaymentsEndpointCollection** +- `customerPayments->listFor()` into `customerPayments->pageFor()` +- `customerPayments->listForId()` into `customerPayments->pageForId()` + +**Mollie\Api\EndpointCollection\MandateEndpointCollection** +- `mandates->listFor()` into `mandates->pageFor()` +- `mandates->listForId()` into `mandates->pageForId()` + +**Mollie\Api\EndpointCollection\PaymentRefundEndpointCollection** +- `paymentRefunds->listFor()` into `paymentRefunds->pageFor()` +- `paymentRefunds->listForId()` into `paymentRefunds->pageForId()` + +**Mollie\Api\EndpointCollection\MethodEndpointCollection** +- `methods->allAvailable()` has been renamed into `methods->all()` now returns all available methods (both enabled and disabled) - previously returned only all enabled methods +- former `methods->all()` has been renamed to `methods->allEnabled()` +- `methods->allActive()` is deprecated + +The reasoning behind this change is to make the method names more intuitive: +- `all()` returns ALL methods (both enabled and disabled) +- `allEnabled()` returns only the enabled methods (previously called `allActive()`) +- The `allActive()` method is deprecated and will be removed in v4 + +**Mollie\Api\EndpointCollection\OnboardingEndpointCollection** +- `get()` was changed into `status()` +- depricated `submit()` and `create()` were removed -> use `ClientLinkEndpointCollection@create()` instead + +**Mollie\Api\EndpointCollection\PaymentCaptureEndpointCollection** +- `paymentCaptures->listFor()` into `paymentCaptures->pageFor()` +- `paymentCaptures->listForId()` into `paymentCaptures->pageForId()` + +**Mollie\Api\EndpointCollection\PaymentChargebackEndpointCollection** +- `listFor()` into `pageFor()` +- `listForId()` into `pageForId()` + +**Mollie\Api\EndpointCollection\PaymentRefundEndpointCollection** +- `pageFor(Payment $payment, array $parameters = [])` changed to `pageFor(Payment $payment, ?string $from = null, ?int $limit = null, array $filters = [])` +- `pageForId(string $paymentId, array $parameters = [])` changed to `pageForId(string $paymentId, ?string $from = null, ?int $limit = null, array $filters = [])` + +**Mollie\Api\EndpointCollection\SubscriptionEndpointCollection** +- `listFor` changed to `pageFor` +- `listForId` changed to `pageForId` +- `page` which previously returned all subscriptions, was renamed into `allFor` +- `allForId` and `iteratorForAll` were added to return all subscriptions + +### Renamed methods +**Mollie\Api\EndpointCollection\PermissionEndpointCollection** +- `all()` was renamed to `list()` to maintain consistency with other non-paginated endpoints + +### Removed non-valid method params +**Mollie\Api\EndpointCollection\PermissionEndpointCollection** +- `get()` second argument changed from `array $parameters` to `array|bool $testmode` to match API documentation + +# Changelog +### Type cast embeded Resources +In previous versions resources requested via `embed` param on requests like [get-payment](https://docs.mollie.com/reference/get-payment) were not casted into their respective collection or resource classes. Starting with this version all embeded resources are typecasted. + +```php +$payment = $mollie->payments->get('...', ['embed' => ['refunds']]); + +$this->assertInstanceOf(RefundCollection::class, $payment->_embedded->refunds); +``` + +### Added CaptureMode +A new `Mollie\Api\Types\CaptureMode` class which can be used when using on the [create-payment request](https://docs.mollie.com/reference/create-payment) (s. *captureMode*) when using the [capture feature](https://docs.mollie.com/reference/create-capture). + +### PSR-18 Support +We added a new HTTP-adapter which supports PSR-18. The following example demonstrates on how to use the new adapter. + +**Note**: The example uses `nyholm/psr7` to get all necessary factories required. You can use the same factories by running `composer require nyholm/psr7`. + +```php +use Mollie\Api\MollieApiClient; +use Psr\Http\Client\ClientInterface; +use Nyholm\Psr7\Factory\Psr17Factory; +use GuzzleHttp\Client as GuzzleClient; +use Psr\Http\Message\RequestFactoryInterface; +use Psr\Http\Message\StreamFactoryInterface; +use Mollie\Api\HttpAdapter\PSR18MollieHttpAdapter; + +// Create instances of the required classes +$httpClient = new GuzzleClient(); // Instance of ClientInterface +$requestFactory = new Psr17Factory(); // Instance of RequestFactoryInterface +$streamFactory = new Psr17Factory(); // Instance of StreamFactoryInterface + +// Instantiate the PSR18MollieHttpAdapter +$mollieHttpAdapter = new PSR18MollieHttpAdapter( + $httpClient, + $requestFactory, + $streamFactory +); + +$client = new MollieApiClient($mollieHttpAdapter); + +$client->setApiKey("test_qM2fCcTADeP6m87E5yFbnzfcUGpEDb"); +$client->payments->page(); +``` + +### Added Collection Methods +Two new collection methods were added which can be used to simplify interacting with collection resources. + +- `contains(callable $callback): bool` +- `filter(callable $callback): static` + +### Testmode is automatically removed.. +..If an API key is used as authentication. + +Say Goodby to the annoying `[...]. Try switching live / test API keys.` + +### Requests, Payloads and Queries +The new version can be used as before **without any changes to the codebase** (except the few mentioned above). The underlying codebase was changed drastically to allow a few improvements. There are now 3 different ways to interact with the client. + +#### The old way +Just as you used to... Pass in arrays of data and receive your Resource/ResourceCollection. + +```php +// old way of creating a payment +$payment = $mollie->payments->create([ + "amount" => [ + "currency" => "EUR", + "value" => "10.00" + ], + "description" => "My first API payment", + "redirectUrl" => "https://webshop.example.org/order/12345/", + "webhookUrl" => "https://webshop.example.org/mollie-webhook/", +]); +``` + +#### Slightly improved +With this approach you can use new Objects and therefore actually know what data is required to pass into the method, but you can still using the old way of calling the request. + +```php +// improved +use Mollie\Api\Http\Data\Money; +use Mollie\Api\Http\Data\CreatePaymentPayload; + +$payload = new CreatePaymentPayload( + description: 'My first API payment', + amount: new Money('EUR', '10.00'), + redirectUrl: 'https://webshop.example.org/order/12345/', + webhookUrl: 'https://webshop.example.org/mollie-webhook/' +); + +$payment = $mollie->payments->create($payload); +``` +#### This is the way! +Finally, the new way of interacting with the client: +1. create your payload +2. pass it into your request +3. send it +4. inspect response +4b. receive your Resoure/ResourceCollection + +```php +// newest ;-) +use Mollie\Api\Http\Data\Money; +use Mollie\Api\Http\Data\CreatePaymentPayload; +use Mollie\Api\Http\Requests\CreatePaymentRequest; + +$payload = new CreatePaymentPayload( + description: 'My first API payment', + amount: new Money('EUR', '10.00'), + redirectUrl: 'https://webshop.example.org/order/12345/', + webhookUrl: 'https://webshop.example.org/mollie-webhook/' +); + +$response = $mollie->send($payload); + +$payment = $response->toResource(); +$jsonData = $response->json(); +$status = $response->status(); +``` + +With this you get a `Response` and can also inspect its status, body or any other payload. If you want to use the `$client->send()` method but don't want to call the `->toResource()` method to receive your Resource, you can simply call `MollieApiClient::shouldAutoHydrate()`. + +--- + +## Some Context... +..on how the new request cycle works +Screenshot 2024-09-09 at 11 03 17 + +### Added contractId parameter for Method Issuers +The `enable()` method on the `MethodIssuerEndpointCollection` now supports an optional `contractId` parameter when enabling voucher issuers. This parameter can be used when an intermediary party (contractor) is involved([1](https://docs.mollie.com/reference/enable-method-issuer)). + +```php +// Enable a method issuer with a contract ID +$issuer = $mollie->methodIssuers->enable( + profileId: 'pfl_...', + methodId: 'voucher', + issuerId: 'issuer_id', + contractId: 'contract_123' // Optional parameter +); +``` + +The contract ID can be updated as long as it hasn't been approved yet by repeating the API call with a different contract ID. + +### Added optional testmode parameter +The following methods now accept an optional `testmode` parameter: + +**Mollie\Api\EndpointCollection\PaymentLinkEndpointCollection** +- `get(string $paymentLinkId, ?bool $testmode = null)` +- `update(string $paymentLinkId, $payload = [], ?bool $testmode = null)` +- `delete(string $paymentLinkId, ?bool $testmode = null)` + +This parameter can be used when working with organization-level credentials such as OAuth access tokens to specify whether the operation should be performed in test mode. For API key credentials, this parameter can be omitted as the mode is determined by the key type. + +```php +// Example with testmode parameter +$paymentLink = $mollie->paymentLinks->get('pl_...', testmode: true); +$paymentLink = $mollie->paymentLinks->update('pl_...', ['description' => 'Updated'], testmode: true); +$mollie->paymentLinks->delete('pl_...', testmode: true); +``` + +--- + +- removed `STATUS` prefix on all type constants +- collection constructors changed, they don't include the counted items anymore diff --git a/composer.json b/composer.json index 04def5417..46cd65ccc 100644 --- a/composer.json +++ b/composer.json @@ -47,18 +47,21 @@ } ], "require": { - "php": "^7.2|^8.0", + "php": "^7.4|^8.0", "ext-curl": "*", "ext-json": "*", "ext-openssl": "*", - "composer/ca-bundle": "^1.2" + "composer/ca-bundle": "^1.4", + "nyholm/psr7": "^1.8", + "psr/http-factory": "^1.1", + "psr/http-message": "^2.0" }, "require-dev": { - "eloquent/liberator": "^2.0||^3.0", - "friendsofphp/php-cs-fixer": "^3.0", - "guzzlehttp/guzzle": "^6.3 || ^7.0", - "phpstan/phpstan": "^1.12", - "phpunit/phpunit": "^8.5 || ^9.5" + "brianium/paratest": "^6.11", + "guzzlehttp/guzzle": "^7.6", + "laravel/pint": "^1.18", + "phpstan/phpstan": "^2.0", + "phpunit/phpunit": "^9.6" }, "suggest": { "mollie/oauth2-mollie-php": "Use OAuth to authenticate with the Mollie API. This is needed for some endpoints. Visit https://docs.mollie.com/ for more information." @@ -79,6 +82,6 @@ }, "scripts": { "test": "./vendor/bin/phpunit tests", - "format": "./vendor/bin/php-cs-fixer fix --allow-risky=yes" + "format": "./vendor/bin/pint" } } diff --git a/docs/endpoint-collections.md b/docs/endpoint-collections.md new file mode 100644 index 000000000..c1f326a9a --- /dev/null +++ b/docs/endpoint-collections.md @@ -0,0 +1,778 @@ +# Introduction +Endpoint collections provide a fluent interface for interacting with Mollie's API. Each collection manages specific resource types like payments, customers, and subscriptions, offering methods to create, retrieve, update, and delete these resources. + +## Setup + +1. **Initialize the Mollie Client:** + +```php +$mollie = new \Mollie\Api\MollieApiClient(); +$mollie->setApiKey("test_*************************"); +``` + +2. **Access Endpoints via the Client:** +```php +// Payments endpoint +$mollie->payments->... + +// Customers endpoint +$mollie->customers->... + +// Other endpoints +$mollie->balances->... +$mollie->orders->... +``` + +3. **Call methods** + +**Simple: Using arrays** +This approach is direct but provides less type safety: +```php +$payment = $mollie->payments->create([ + 'amount' => [ + 'currency' => 'EUR', + 'value' => '10.00' + ], + 'description' => 'My first API payment' +]); +``` + +**Advanced: Using typed payloads/queries** +This approach provides full IDE support and type safety: +```php +use Mollie\Api\Http\Data\Money; +use Mollie\Api\Http\Data\CreatePaymentPayload; + +$payment = $mollie->payments->create( + new CreatePaymentPayload( + description: 'My first API payment', + amount: new Money('EUR', '10.00') + ) +); +``` + +If you have an array and need to interact with the payload or query, you can use a dedicated factory to convert the array into a typed class. + +use Mollie\Api\Http\Data\Money; +use Mollie\Api\Factories\CreatePaymentPayloadFactory; + +// Fully untyped data +$createPaymentPayload = CreatePaymentPayloadFactory::new([ + 'amount' => [ + 'currency' => 'EUR', + 'value' => '10.00' + ], + 'description' => 'My first API payment' +]); + +// Partially untyped +$createPaymentPayload = CreatePaymentPayloadFactory::new([ + 'amount' => new Money('EUR', '10.00'), + 'description' => 'My first API payment' +]); + +// Access payload +$createPaymentPayload->amount->... +``` + +This approach allows you to seamlessly convert arrays into typed objects, providing better IDE support and type safety while working with your data. + +# Available Endpoints + +## Balances + +[Official Documentation](https://docs.mollie.com/reference/v2/balances-api/get-balance) + +**Available Queries:** +- `GetPaginatedBalanceQuery` - For listing balances with pagination + +### Balance Information + +```php +// Get primary balance +$balance = $mollie->balances->primary(); + +// Get specific balance +$balance = $mollie->balances->get('bal_12345'); + +// List balances +$balances = $mollie->balances->page(); +``` + +## Balance Reports + +[Official Documentation](https://docs.mollie.com/reference/v2/balance-reports-api/get-balance-report) + +**Available Queries:** +- `GetBalanceReportQuery` - For retrieving balance reports + +### Balance Report Details + +```php +// Get report for specific balance +$report = $mollie->balanceReports->getForId('bal_12345', [ + 'from' => '2024-01-01', + 'until' => '2024-01-31', + 'grouping' => 'transaction-categories' +]); +``` + +## Balance Transactions + +[Official Documentation](https://docs.mollie.com/reference/v2/balance-transactions-api/list-balance-transactions) + +**Available Queries:** +- `GetPaginatedBalanceQuery` - For listing balance transactions with pagination + +### Balance Transaction Management + +```php +// Get transactions for a balance +$transactions = $mollie->balanceTransactions->pageFor($balance); + +// Use iterator for all transactions +foreach ($mollie->balanceTransactions->iteratorFor($balance) as $transaction) { + echo $transaction->id; +} +``` + +## Chargebacks + +[Official Documentation](https://docs.mollie.com/reference/v2/chargebacks-api/get-chargeback) + +**Available Queries:** +- `GetPaginatedChargebacksQuery` - For listing chargebacks with pagination + +### Chargeback Management + +```php +// Get all chargebacks +$chargebacks = $mollie->chargebacks->page(); + +// Use iterator for all chargebacks +foreach ($mollie->chargebacks->iterator() as $chargeback) { + echo $chargeback->id; +} +``` + +## Clients + +[Official Documentation](https://docs.mollie.com/reference/v2/clients-api/get-client) + +**Available Queries:** +- `GetClientQuery` - For retrieving client details + +### Client Management + +```php +// Get a specific client +$client = $mollie->clients->get('org_12345678', [ + 'testmode' => true +]); + +// List all clients +$clients = $mollie->clients->page( + from: 'org_12345678', + limit: 50 +); +``` + +## Customers + +[Official Documentation](https://docs.mollie.com/reference/v2/customers-api/create-customer) + +**Available Payloads:** +- `CreateCustomerPayload` - For creating new customers +- `UpdateCustomerPayload` - For updating existing customers + +### Customer Management + +```php +// Create a customer +$customer = $mollie->customers->create([ + 'name' => 'John Doe', + 'email' => 'john@example.org', +]); + +// Get a customer +$customer = $mollie->customers->get('cst_8wmqcHMN4U'); + +// Update a customer +$customer = $mollie->customers->update('cst_8wmqcHMN4U', [ + 'name' => 'Updated Name' +]); + +// Delete a customer +$mollie->customers->delete('cst_8wmqcHMN4U'); + +// List customers +$customers = $mollie->customers->page(); +``` + +## Invoices + +[Official Documentation](https://docs.mollie.com/reference/v2/invoices-api/get-invoice) + +**Available Queries:** +- `GetPaginatedInvoiceQuery` - For listing invoices with pagination + +### Invoice Management + +```php +// Get a specific invoice +$invoice = $mollie->invoices->get('inv_xBEbP9rvAq'); + +// List all invoices +$invoices = $mollie->invoices->page( + from: 'inv_xBEbP9rvAq', + limit: 50 +); +``` + +## Mandates + +[Official Documentation](https://docs.mollie.com/reference/v2/mandates-api/create-mandate) + +**Available Payloads:** +- `CreateMandatePayload` - For creating new mandates + +### Mandate Management + +```php +// Create a mandate for a customer +$mandate = $mollie->mandates->createFor($customer, [ + 'method' => \Mollie\Api\Types\PaymentMethod::DIRECTDEBIT, + 'consumerName' => 'John Doe', + 'consumerAccount' => 'NL55INGB0000000000', + 'consumerBic' => 'INGBNL2A', + 'signatureDate' => '2024-01-01', + 'mandateReference' => 'YOUR-COMPANY-MD13804' +]); + +// Get a mandate +$mandate = $mollie->mandates->getFor($customer, 'mdt_h3gAaD5zP'); + +// Revoke a mandate +$mollie->mandates->revokeFor($customer, 'mdt_h3gAaD5zP'); + +// List mandates +$mandates = $mollie->mandates->pageFor($customer); +``` + +## Methods + +[Official Documentation](https://docs.mollie.com/reference/v2/methods-api/get-method) + +**Available Queries:** +- `GetPaymentMethodQuery` - For retrieving method details +- `GetAllMethodsQuery` - For listing all available methods +- `GetEnabledPaymentMethodsQuery` - For listing enabled methods + +### Payment Methods + +```php +// Get a method +$method = $mollie->methods->get(\Mollie\Api\Types\PaymentMethod::IDEAL); + +// List all methods +$methods = $mollie->methods->all(); + +// List enabled methods +$methods = $mollie->methods->allEnabled([ + 'amount' => [ + 'currency' => 'EUR', + 'value' => '100.00' + ] +]); +``` + +### Method Issuers + +```php +// Enable an issuer +$issuer = $mollie->methodIssuers->enable( + 'pfl_v9hTwCvYqw', + \Mollie\Api\Types\PaymentMethod::IDEAL, + 'ideal_INGBNL2A' +); + +// Disable an issuer +$mollie->methodIssuers->disable( + 'pfl_v9hTwCvYqw', + \Mollie\Api\Types\PaymentMethod::IDEAL, + 'ideal_INGBNL2A' +); +``` + +## Onboarding + +[Official Documentation](https://docs.mollie.com/reference/v2/onboarding-api/get-onboarding-status) + +**Available Queries:** +- `GetOnboardingStatusQuery` - For retrieving onboarding status + +### Onboarding Management + +```php +// Get onboarding status +$onboarding = $mollie->onboarding->status(); +``` + +## Organizations + +[Official Documentation](https://docs.mollie.com/reference/v2/organizations-api/get-organization) + +**Available Queries:** +- `GetOrganizationQuery` - For retrieving organization details + +### Organization Management + +```php +// Get an organization +$organization = $mollie->organizations->get('org_12345678'); + +// Get current organization +$organization = $mollie->organizations->current(); + +// Get partner status +$partner = $mollie->organizations->partnerStatus(); +``` + +## Permissions + +[Official Documentation](https://docs.mollie.com/reference/v2/permissions-api/get-permission) + +**Available Queries:** +- `GetPermissionQuery` - For retrieving permission details + +### Permission Management + +```php +// Get a permission +$permission = $mollie->permissions->get('payments.read'); + +// List all permissions +$permissions = $mollie->permissions->list(); +``` + +## Payments + +[Official Documentation](https://docs.mollie.com/reference/v2/payments-api/create-payment) + +**Available Payloads:** +- `CreatePaymentPayload` - For creating new payments +- `UpdatePaymentPayload` - For updating existing payments + +**Available Queries:** +- `GetPaymentQuery` - For retrieving payments with optional embeds +- `GetPaginatedPaymentsQuery` - For listing payments with pagination + +### Payment Management + +```php +// Create a payment using typed payload +use Mollie\Api\Http\Data\Money; +use Mollie\Api\Http\Data\CreatePaymentPayload; + +$payload = new CreatePaymentPayload( + description: 'Order #12345', + amount: new Money('EUR', '10.00'), + redirectUrl: 'https://webshop.example.org/order/12345/', + webhookUrl: 'https://webshop.example.org/mollie-webhook/' +); + +$payment = $mollie->payments->create($payload); + +// Get a payment +$payment = $mollie->payments->get('tr_7UhSN1zuXS'); + +// Update a payment +$payment = $mollie->payments->update('tr_7UhSN1zuXS', [ + 'description' => 'Updated description' +]); + +// Cancel a payment +$mollie->payments->cancel('tr_7UhSN1zuXS'); + +// List payments +$payments = $mollie->payments->page(); +``` + +### Payment Links + +[Official Documentation](https://docs.mollie.com/reference/v2/payment-links-api/create-payment-link) + +**Available Payloads:** +- `CreatePaymentLinkPayload` - For creating payment links +- `UpdatePaymentLinkPayload` - For updating payment links + +### Payment Captures + +[Official Documentation](https://docs.mollie.com/reference/v2/captures-api/get-capture) + +**Available Payloads:** +- `CreatePaymentCapturePayload` - For creating captures + +**Available Queries:** +- `GetPaymentCaptureQuery` - For retrieving capture details +- `GetPaginatedPaymentCapturesQuery` - For listing captures + +### Payment Chargebacks + +```php +// Get a chargeback +$chargeback = $mollie->paymentChargebacks->getFor($payment, 'chb_n9z0tp'); + +// List chargebacks for payment +$chargebacks = $mollie->paymentChargebacks->pageFor($payment); +``` + +### Payment Routes + +```php +// Update release date for a route +$route = $mollie->paymentRoutes->updateReleaseDateFor( + $payment, + 'rt_abc123', + '2024-01-01' +); +``` + +## Profiles + +[Official Documentation](https://docs.mollie.com/reference/v2/profiles-api/create-profile) + +**Available Payloads:** +- `CreateProfilePayload` - For creating new profiles + +**Available Factories:** +- `ProfileFactory` - For creating profile instances + +### Profile Management + +```php +// Create a profile +$profile = $mollie->profiles->create(new CreateProfilePayload( + 'My Test Profile', + 'https://example.org', + 'info@example.org', + '+31612345678', + 'test' +)); + +// Get a profile +$profile = $mollie->profiles->get('pfl_v9hTwCvYqw'); + +// Get current profile +$profile = $mollie->profiles->getCurrent(); + +// Update a profile +$profile = $mollie->profiles->update('pfl_v9hTwCvYqw', [ + 'name' => 'Updated Profile Name' +]); + +// Delete a profile +$mollie->profiles->delete('pfl_v9hTwCvYqw'); + +// List profiles +$profiles = $mollie->profiles->page(); +``` + +### Profile Methods + +```php +// Enable a method +$method = $mollie->profileMethods->enable( + 'pfl_v9hTwCvYqw', + \Mollie\Api\Types\PaymentMethod::IDEAL +); + +// Disable a method +$mollie->profileMethods->disable( + 'pfl_v9hTwCvYqw', + \Mollie\Api\Types\PaymentMethod::IDEAL +); +``` + +## Refunds + +[Official Documentation](https://docs.mollie.com/reference/v2/refunds-api/create-refund) + +**Available Payloads:** +- `CreateRefundPaymentPayload` - For creating refunds on payments +- `CreateRefundOrderPayload` - For creating refunds on orders + +**Available Queries:** +- `GetPaginatedRefundsQuery` - For listing refunds with pagination + +### Refund Management + +```php +// Create a refund for a payment +$refund = $mollie->refunds->createForPayment($paymentId, [ + 'amount' => [ + 'currency' => 'EUR', + 'value' => '15.00' + ], + 'description' => 'Refund for returned item' +]); + +// List refunds +$refunds = $mollie->refunds->page(); +``` + +## Sales Invoices + +[Official Documentation TBA] + +**Available Payloads:** +- `CreateSalesInvoicePayload` - For creating sales invoices +- `UpdateSalesInvoicePayload` - For updating existing sales invoices + +**Available Queries:** +- `GetPaginatedSalesInvoiceQuery` - For listing sales invoices with pagination + +### Sales Invoice Management + +```php +use Mollie\Api\Types\VatMode; +use Mollie\Api\Types\VatScheme; +use Mollie\Api\Types\PaymentTerm; +use Mollie\Api\Types\RecipientType; +use Mollie\Api\Types\RecipientType; +use Mollie\Api\Types\SalesInvoiceStatus; + +// Create a sales invoice +$salesInvoice = $mollie->salesInvoices->create([ + 'currency' => 'EUR', + 'status' => SalesInvoiceStatus::DRAFT, + 'vatScheme' => VatScheme::STANDARD, + 'vatMode' => VatMode::INCLUSIVE, + 'paymentTerm' => PaymentTerm::DAYS_30, + 'recipientIdentifier' => 'XXXXX', + 'recipient' => [ + 'type' => RecipientType::CONSUMER, + 'email' => 'darth@vader.deathstar', + 'streetAndNumber' => 'Sample Street 12b', + 'postalCode' => '2000 AA', + 'city' => 'Amsterdam', + 'country' => 'NL', + 'locale' => 'nl_NL' + ], + 'lines' => [ + [ + 'description' => 'Monthly subscription fee', + 'quantity' => 1, + 'vatRate' => '21', + 'unitPrice' => [ + 'currency' => 'EUR', + 'value' => '10,00' + ] + ] + ] +]); + +// Get a sales invoice +$salesInvoice = $mollie->salesInvoices->get('invoice_12345'); + +// Update a sales invoice +$salesInvoice = $mollie->salesInvoices->update('invoice_12345', [ + 'description' => 'Updated description' +]); + +// Delete a sales invoice +$mollie->salesInvoices->delete('invoice_12345'); + +// List sales invoices +$salesInvoices = $mollie->salesInvoices->page(); +``` + +## Sessions + +[Official Documentation](https://docs.mollie.com/reference/v2/sessions-api/create-session) + +**Available Payloads:** +- `CreateSessionPayload` - For creating sessions + +**Available Queries:** +- `GetPaginatedSessionsQuery` - For listing sessions with pagination + +### Session Management + +```php +// Create a session +$session = $mollie->sessions->create([ + 'amount' => [ + 'currency' => 'EUR', + 'value' => '100.00' + ], + 'description' => 'Session for service' +]); + +// Get a session +$session = $mollie->sessions->get('sessionId'); +``` + +## Settlements + +[Official Documentation](https://docs.mollie.com/reference/v2/settlements-api/get-settlement) + +**Available Queries:** +- `GetPaginatedSettlementsQuery` - For listing settlements with pagination + +### Settlement Management + +```php +// Get a settlement +$settlement = $mollie->settlements->get('settlementId'); + +// List settlements +$settlements = $mollie->settlements->page(); +``` + +### Settlement Captures + +```php +// Get captures for a settlement +$captures = $mollie->settlementCaptures->pageFor($settlement); + +// Use iterator +foreach ($mollie->settlementCaptures->iteratorFor($settlement) as $capture) { + echo $capture->id; +} +``` + +### Settlement Chargebacks + +```php +// List chargebacks for a settlement +$chargebacks = $mollie->settlementChargebacks->pageFor($settlement); + +// Use iterator +foreach ($mollie->settlementChargebacks->iteratorFor($settlement) as $chargeback) { + echo $chargeback->id; +} +``` + +### Settlement Payments + +```php +// List payments in a settlement +$payments = $mollie->settlementPayments->pageFor($settlement); + +// Use iterator +foreach ($mollie->settlementPayments->iteratorFor($settlement) as $payment) { + echo $payment->id; +} +``` + +## Subscriptions + +[Official Documentation](https://docs.mollie.com/reference/v2/subscriptions-api/create-subscription) + +**Available Payloads:** +- `CreateSubscriptionPayload` - For creating subscriptions + +**Available Queries:** +- `GetAllPaginatedSubscriptionsQuery` - For listing all subscriptions + +### Subscription Management + +```php +// Create a subscription +$subscription = $mollie->subscriptions->createForCustomer('customerId', [ + 'amount' => [ + 'currency' => 'EUR', + 'value' => '25.00' + ], + 'interval' => '1 month', + 'description' => 'Monthly subscription' +]); + +// List subscriptions +$subscriptions = $mollie->subscriptions->pageForCustomer('customerId'); +``` + +## Terminals + +[Official Documentation](https://docs.mollie.com/reference/v2/terminals-api/get-terminal) + +**Available Queries:** +- `GetPaginatedTerminalsQuery` - For listing terminals with pagination + +### Terminal Management + +```php +// Get a terminal +$terminal = $mollie->terminals->get('terminalId'); + +// List terminals +$terminals = $mollie->terminals->page(); +``` + +## Wallets + +[Official Documentation](https://docs.mollie.com/reference/v2/wallets-api/request-apple-pay-payment-session) + +**Available Payloads:** +- `RequestApplePayPaymentSessionPayload` - For requesting Apple Pay payment sessions + +### Wallet Management + +```php +// Request an Apple Pay payment session +$session = $mollie->wallets->requestApplePayPaymentSession([ + 'domainName' => 'example.com', + 'validationUrl' => 'https://apple-pay-gateway.apple.com/paymentservices/startSession' +]); +``` + +## Common Patterns + +### Pagination + +Most list methods support pagination: + +```php +// Get first page +$payments = $mollie->payments->page(); + +// Get specific page +$payments = $mollie->payments->page( + from: 'tr_7UhSN1zuXS', // Start from this ID + limit: 50 // Items per page +); + +// Get all items using iterator +foreach ($mollie->payments->iterator() as $payment) { + echo $payment->id; +} +``` + +### Error Handling + +Handle errors using `ApiException`: + +```php +try { + $payment = $mollie->payments->get('tr_xxx'); +} catch (\Mollie\Api\Exceptions\ApiException $e) { + echo "API call failed: {$e->getMessage()}"; +} +``` + +## Common Data Types + +- `Money` - For handling currency amounts +- `Metadata` - For handling custom metadata +- `DataCollection` - For handling collections of data +- `Data` - Base class for payload/query objects + +## Factories + +**Query Factories:** +- `PaginatedQueryFactory` - For creating paginated queries +- `SortablePaginatedQueryFactory` - For creating sortable paginated queries + +**Payload Factories:** +- `CreatePaymentPayloadFactory` - For creating payment payloads diff --git a/docs/http-adapters.md b/docs/http-adapters.md new file mode 100644 index 000000000..46d05aa25 --- /dev/null +++ b/docs/http-adapters.md @@ -0,0 +1,74 @@ +# HTTP Adapters + +## Overview + +An HTTP adapter is a component that manages the communication between your application and an API. It abstracts the details of making HTTP requests and handling responses, allowing you to use different HTTP clients (like Guzzle, cURL, or custom clients) interchangeably without changing the way you interact with the API. + +## MollieHttpAdapterPicker + +The `MollieHttpAdapterPicker` is responsible for selecting the appropriate HTTP adapter based on the environment or the provided HTTP client. If no client is specified in the `MollieApiClient` constructor, it picks a default adapter. + +### How It Works + +1. **No Client Specified**: If no client is provided, it checks if Guzzle is available and picks the appropriate version of the Guzzle adapter. +2. **Custom Client Provided**: If a custom client is provided and it implements the `HttpAdapterContract`, it is used directly. If it's a Guzzle client, it is wrapped in a `GuzzleMollieHttpAdapter`. +3. **Unrecognized Client**: Throws an `UnrecognizedClientException` if the client is not recognized. + +## Creating a Custom Adapter + +To create a custom HTTP adapter: +1. Implement HttpAdapterContract. +2. Use HasDefaultFactories Trait to simplify adapter implementation. + +```php +use Mollie\Api\Contracts\HttpAdapterContract; +use Mollie\Api\Traits\HasDefaultFactories; + +class MyCustomHttpAdapter implements HttpAdapterContract { + use HasDefaultFactories; + + public function sendRequest(PendingRequest $pendingRequest): Response { + // Implementation for sending HTTP request + } + + public function version(): ?string { + return 'my-custom-adapter/1.0'; + } +} +``` + +### Debugging + +When debugging mode is enabled, adapters remove sensitive information before they fire an exception. + +Adapters that support debugging must implement the `SupportsDebuggingContract`. This contract defines methods `enableDebugging()` and `disableDebugging()` to control debugging behavior. + +```php +use Mollie\Api\Contracts\SupportsDebuggingContract; + +class MyCustomHttpAdapter implements HttpAdapterContract, SupportsDebuggingContract { + // Implementation of debugging methods +} +``` + +## Available Adapters + +Out of the box, the Mollie API client provides several adapters: + +- **GuzzleMollieHttpAdapter**: Wraps a Guzzle HTTP client for sending requests. +- **CurlMollieHttpAdapter**: Uses cURL for sending HTTP requests. This is the default if Guzzle is not available. + +## Enabling Debugging + +Debugging can be enabled through the `HandlesDebugging` trait. This trait allows you to toggle debugging on the HTTP client, which is useful for development and troubleshooting. + +### How to Enable Debugging + +1. **Enable Debugging**: Call `enableDebugging()` on the Mollie API client instance. This sets the debugging mode on the underlying HTTP adapter, if it supports debugging. + +2. **Disable Debugging**: Call `disableDebugging()` to turn off debugging. + +```php +$mollieClient->enableDebugging(); +$mollieClient->disableDebugging(); +``` diff --git a/docs/idempotency.md b/docs/idempotency.md new file mode 100644 index 000000000..020afd3f8 --- /dev/null +++ b/docs/idempotency.md @@ -0,0 +1,57 @@ +# Idempotency + +## Overview + +Idempotency ensures that multiple identical requests to an API result in the same outcome without creating duplicate resources or effects. This is crucial for operations that involve financial transactions to prevent unintended charges or state changes. + +Mollie API supports idempotent requests for critical operations such as creating payments or refunds. This is automatically managed by the API client using the `ApplyIdempotencyKey` middleware. + +For more detailed information, refer to the [Mollie API Idempotency Documentation](https://docs.mollie.com/reference/api-idempotency). + +## Automatic Idempotency Key Handling + +The Mollie API client automatically handles idempotency for mutating requests (POST, PATCH, DELETE) through the `ApplyIdempotencyKey` middleware. This middleware checks if the request is a mutating type and applies an idempotency key if one is not already provided. + +### How It Works + +1. **Check Request Type**: The middleware checks if the request method is POST, PATCH, or DELETE. +2. **Apply Idempotency Key**: If the request is mutating, the middleware will: + - Use a custom idempotency key if provided. + - Otherwise, generate a key using the configured `IdempotencyKeyGenerator` if available. + - If no generator is set and no key is provided, no idempotency key is applied. + +### Customizing Idempotency Key + +You can customize how idempotency keys are generated or applied in several ways: + +- **Provide a Custom Key**: Manually set an idempotency key for a specific request. +- **Use a Custom Generator**: Implement the `IdempotencyKeyGeneratorContract` to provide a custom method of generating idempotency keys. + +#### Example: Setting a Custom Key + +```php +$mollie->setIdempotencyKey('your_custom_key_here'); +``` + +#### Example: Using a Custom Key Generator + +Implement your key generator: + +```php +class MyCustomKeyGenerator implements IdempotencyKeyGeneratorContract { + public function generate(): string { + return 'custom_' . bin2hex(random_bytes(10)); + } +} + +$mollie->setIdempotencyKeyGenerator(new MyCustomKeyGenerator()); +``` + +## Best Practices + +- **Unique Keys**: Ensure that each idempotency key is unique to each operation. Typically, UUIDs are used for this purpose. +- **Handling Errors**: Handle errors gracefully, especially when an API call with an idempotency key fails. Check the error message to understand whether you should retry the request with the same key or a new key. + +## Conclusionz + +Using idempotency keys in your API requests to Mollie can significantly enhance the reliability of your payment processing system, ensuring that payments are not unintentionally duplicated and that your application behaves predictably even in the face of network and service interruptions. diff --git a/docs/payments.md b/docs/payments.md new file mode 100644 index 000000000..2d98141d4 --- /dev/null +++ b/docs/payments.md @@ -0,0 +1,93 @@ +##### Multicurrency ##### +Since API v2.0 it is now possible to create non-EUR payments for your customers. +A full list of available currencies can be found [in our documentation](https://docs.mollie.com/guides/multicurrency). + +```php +$payment = $mollie->payments->create([ + "amount" => [ + "currency" => "USD", + "value" => "10.00" + ], + //... +]); +``` +_After creation, the `settlementAmount` will contain the EUR amount that will be settled on your account._ + +##### Create fully integrated iDEAL payments ##### +To fully integrate iDEAL payments on your website, follow these additional steps: + +1. Retrieve the list of issuers (banks) that support iDEAL. + +```php +$method = $mollie->methods->get(\Mollie\Api\Types\PaymentMethod::IDEAL, ["include" => "issuers"]); +``` + +Use the `$method->issuers` list to let the customer pick their preferred issuer. + +_`$method->issuers` will be a list of objects. Use the property `$id` of this object in the + API call, and the property `$name` for displaying the issuer to your customer._ + +2. Create a payment with the selected issuer: + +```php +$payment = $mollie->payments->create([ + "amount" => [ + "currency" => "EUR", + "value" => "10.00" + ], + "description" => "My first API payment", + "redirectUrl" => "https://webshop.example.org/order/12345/", + "webhookUrl" => "https://webshop.example.org/mollie-webhook/", + "method" => \Mollie\Api\Types\PaymentMethod::IDEAL, + "issuer" => $selectedIssuerId, // e.g. "ideal_INGBNL2A" +]); +``` + +_The `_links` property of the `$payment` object will contain an object `checkout` with a `href` property, which is a URL that points directly to the online banking environment of the selected issuer. +A short way of retrieving this URL can be achieved by using the `$payment->getCheckoutUrl()`._ + +For a more in-depth example, see [Example - iDEAL payment](https://github.com/mollie/mollie-api-php/blob/master/examples/payments/create-ideal-payment.php). + +#### Retrieving Payments #### +**[Retrieve Payment Documentation](https://docs.mollie.com/reference/v2/payments-api/get-payment)** + +We can use the `$payment->id` to retrieve a payment and check if the payment `isPaid`. + +```php +$payment = $mollie->payments->get($payment->id); + +if ($payment->isPaid()) +{ + echo "Payment received."; +} +``` + +Or retrieve a collection of payments. + +```php +$payments = $mollie->payments->page(); +``` + +For an extensive example of listing payments with the details and status, see [Example - List Payments](https://github.com/mollie/mollie-api-php/blob/master/examples/payments/list-payments.php). + +#### Refunding payments #### +**[Refund Payment Documentation](https://docs.mollie.com/reference/v2/refunds-api/create-payment-refund)** + +Our API provides support for refunding payments. It's important to note that there is no confirmation step, and all refunds are immediate and final. Refunds are available for all payment methods except for paysafecard and gift cards. + +```php +$payment = $mollie->payments->get($payment->id); + +// Refund € 2 of this payment +$refund = $payment->refund([ + "amount" => [ + "currency" => "EUR", + "value" => "2.00" + ] +]); +``` + +#### Payment webhook #### +When the payment status changes, the `webhookUrl` you specified during payment creation will be called. You can use the `id` from the POST parameters to check the status and take appropriate actions. For more details, refer to [Example - Webhook](https://github.com/mollie/mollie-api-php/blob/master/examples/payments/webhook.php). + +For a working example, see [Example - Refund payment](https://github.com/mollie/mollie-api-php/blob/master/examples/payments/refund-payment.php). diff --git a/docs/requests.md b/docs/requests.md new file mode 100644 index 000000000..aa889d6fe --- /dev/null +++ b/docs/requests.md @@ -0,0 +1,48 @@ +# Requests + +## Overview + +The Mollie API client uses request classes to communicate with the Mollie API. Each request class handles specific API endpoints and operations. + +## Sending a Request + +To send a request using the Mollie API client, you typically need to: + +1. **Create an instance of the client**: + ```php + use Mollie\Api\MollieApiClient; + + $mollie = new MollieApiClient(); + $mollie->setApiKey('test_dHar4XY7LxsDOtmnkVtjNVWXLSlXsM'); + ``` + +2. **Create and configure the request**: + Depending on the operation, you might need to create an instance of a specific request class and configure it with necessary parameters. + +3. **Send the request**: + Use the client to send the request and handle the response. + + ```php + use Mollie\Api\MollieApiClient; + use Mollie\Api\Http\Data\Money; + use Mollie\Api\Http\Data\CreatePaymentPayload; + use Mollie\Api\Http\Requests\CreatePaymentRequest; + + $mollie = new MollieApiClient(); + $createPaymentRequest = new CreatePaymentRequest( + new CreatePaymentPayload( + 'Test payment', + new Money('EUR', '10.00'), + 'https://example.org/redirect', + 'https://example.org/webhook' + ) + ); + + /** @var \Mollie\Api\Http\Response $response */ + $response = $mollie->send($createPaymentRequest); + + $this->assertEquals(200, $response->status()); + + /** @var \Mollie\Api\Resources\Payment */ + $payment = $response->toResource(); + ``` diff --git a/docs/responses.md b/docs/responses.md new file mode 100644 index 000000000..cd7058112 --- /dev/null +++ b/docs/responses.md @@ -0,0 +1,43 @@ +# Responses + +Whether you interact with the endpoints using the traditional method (`$mollie->payments->...`) or the new `Request` classes, you can always inspect the `Response`. + +## Resource Hydration +By default, the response from the `EndpointCollection`s automatically hydrates into the corresponding `Resource` or `ResourceCollection` objects. You can still access the raw response using the `->getResponse()` method. + +```php +/** @var Mollie\Api\Resources\Payment $payment */ +$payment = $mollie->payments->get('tr_*********'); + +$response = $payment->getResponse(); +``` + +With the Request-based approach, you get a Response by default: + +```php +/** @var Mollie\Api\Http\Response $response */ +$response = $mollie->send(new GetPaymentRequest('tr_*********')); + +/** + * Accessing the response is mainly for debugging, + * like checking the status or inspecting the payload or URL. + */ +$status = $response->status(); +$sentPayload = $response->getPendingRequest()->payload; +$sentUrlWithFilters = $response->getPendingRequest()->getUri(); + +/** @var Mollie\Api\Resources\Payment $payment */ +$payment = $response->toResource(); +``` + +Thanks to the DelegatesToResource Trait in Response, you can still access methods and attributes from the underlying Resource: + +```php +// calling a method on the underlying Mollie\Api\Resources\Payment object +$response->hasSplitPayments(); + +// accessing an attribute on the underlying Mollie\Api\Resources\Payment object +$amount = $response->amount; +``` + +If you prefer the old approach of directly receiving the Resource class, you can enable **auto-hydration** by calling `MollieApiClient::setAutoHydrate()`. diff --git a/docs/testing.md b/docs/testing.md new file mode 100644 index 000000000..f5888d9c7 --- /dev/null +++ b/docs/testing.md @@ -0,0 +1,55 @@ +# Testing with Mollie API Client + +## Overview + +Version 3 of the Mollie API client refines the handling of the test mode parameter: + +- **Automatic Removal of Test Mode**: When using an API key, the test mode parameter is managed based on the key prefix (`test_` or `live_`). +- **Explicit Test Mode Control**: For operations requiring explicit control, such as when using OAuth tokens, you can still pass the `testmode` parameter. + +## Enabling Test Mode + +### Global Test Mode + +You can enable test mode globally on the Mollie client. This setting will apply test mode to all operations performed with the client. + +```php +use Mollie\Api\MollieApiClient; + +$mollie = new MollieApiClient(); +$mollie->setApiKey("test_dHar4XY7LxsDOtmnkVtjNVWXLSlXsM"); +$mollie->test(true); // Enable test mode globally +``` + +### Per Request Test Mode + +For specific control, you can enable test mode per request. This is useful for mixed-mode operations. + +```php +// Creating a payment in test mode +use Mollie\Api\MollieApiClient; +use Mollie\Api\Http\Data\Money; +use Mollie\Api\Http\Data\CreatePaymentPayload; +use Mollie\Api\Http\Requests\CreatePaymentRequest; + +$mollie = new MollieApiClient(); +$createPaymentRequest = new CreatePaymentRequest( + new CreatePaymentPayload( + 'Test payment', + new Money('EUR', '10.00'), + 'https://example.org/redirect', + 'https://example.org/webhook' + ) +); + +$mollie->send($createPaymentRequest->test(true)); +``` + +### Using Test Mode with Endpoint Collections + +When using endpoint collections, pass the test mode parameter directly to methods that support it. + +```php +// Fetch a customer in test mode +$customer = $mollie->customers->get('cust_12345678', testmode: true); +``` diff --git a/examples/captures/create-capture.php b/examples/captures/create-capture.php index a51030ea8..65d374406 100644 --- a/examples/captures/create-capture.php +++ b/examples/captures/create-capture.php @@ -1,15 +1,20 @@ paymentCaptures->createForId('tr_WDqYK6vllg', [ - "amount" => [ - "currency" => "EUR", - "value" => "5.00", - ], - "description" => "Order #12345", - ]); + $response = $mollie->send(new CreatePaymentCaptureRequest('tr_WDqYK6vllg', new CreatePaymentCapturePayload( + 'Order #12345', + new Money('EUR', '5.00') + ))); + + $capture = $response->toResource(); - echo "

New capture created " . htmlspecialchars($capture->id) . " (" . htmlspecialchars($capture->description) . ").

"; + echo '

New capture created '.htmlspecialchars($capture->id).' ('.htmlspecialchars($capture->description).').

'; } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/captures/get-capture.php b/examples/captures/get-capture.php index 77b658d7c..0f6e076dd 100644 --- a/examples/captures/get-capture.php +++ b/examples/captures/get-capture.php @@ -1,13 +1,16 @@ payments->get('tr_WDqYK6vllg'); - $capture = $payment->getCapture('cpt_4qqhO89gsT'); + $response = $mollie->send(new GetPaymentCaptureRequest('tr_WDqYK6vllg', 'cpt_4qqhO89gsT')); - $amount = $capture->amount->currency . ' ' . $capture->amount->value; + $capture = $response->toResource(); + $amount = $capture->amount->currency.' '.$capture->amount->value; - echo 'Captured ' . $amount; + echo 'Captured '.$amount; } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/captures/list-captures.php b/examples/captures/list-captures.php index 8567db76d..2ead8b80f 100644 --- a/examples/captures/list-captures.php +++ b/examples/captures/list-captures.php @@ -1,13 +1,16 @@ payments->get('tr_WDqYK6vllg'); - $captures = $payment->captures(); + $response = $mollie->send(new GetPaginatedPaymentCapturesRequest('tr_WDqYK6vllg')); - foreach ($captures as $capture) { - $amount = $capture->amount->currency . ' ' . $capture->amount->value; - echo 'Captured ' . $amount . ' for payment ' . $payment->id; + foreach ($payment = $response->toResource() as $capture) { + $amount = $capture->amount->currency.' '.$capture->amount->value; + echo 'Captured '.$amount.' for payment '.$payment->id; } } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/client-links/create-client-link.php b/examples/client-links/create-client-link.php index 789a90fe5..941a1babb 100644 --- a/examples/client-links/create-client-link.php +++ b/examples/client-links/create-client-link.php @@ -1,18 +1,24 @@ clientLinks->create([ - "owner" => [ - "email" => "foo@test.com", - "givenName" => "foo", - "familyName" => "bar", - "locale" => "nl_NL", - ], - "name" => "Foo Company", - "address" => [ - "streetAndNumber" => "Keizersgracht 313", - "postalCode" => "1016 EE", - "city" => "Amsterdam", - "country" => "nl", - ], - "registrationNumber" => "30204462", - "vatNumber" => "NL123456789B01", - ]); + $response = $mollie->send(new CreateClientLinkRequest(new CreateClientLinkPayload( + new Owner('foo@test.com', 'foo', 'bar', 'nl_NL'), + 'Foo Company', + new OwnerAddress('NL', 'Keizersgracht 313', '1016 EE', 'Amsterdam'), + '30204462', + 'NL123456789B01', + ))); + + $clientLink = $response->toResource(); /** * Get the redirect url for the client link, by passing in the 'client_id' of the your app, @@ -46,7 +44,7 @@ * * For more info see: https://docs.mollie.com/reference/oauth2/authorize#parameters */ - $redirectUrl = $clientLink->getRedirectUrl("app_j9Pakf56Ajta6Y65AkdTtAv", "decafbad", "force", [ + $redirectUrl = $clientLink->getRedirectUrl('app_j9Pakf56Ajta6Y65AkdTtAv', 'decafbad', 'force', [ 'onboarding.read', 'onboarding.write', ]); @@ -55,7 +53,7 @@ * Send the customer off to finalize the organization creation. * This request should always be a GET, thus we enforce 303 http response code */ - header("Location: " . $redirectUrl, true, 303); + header('Location: '.$redirectUrl, true, 303); } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/customers/create-customer-first-payment.php b/examples/customers/create-customer-first-payment.php index 0775f27b4..96761e314 100644 --- a/examples/customers/create-customer-first-payment.php +++ b/examples/customers/create-customer-first-payment.php @@ -1,19 +1,27 @@ customers->page(null, 1)[0]; + $customer = $mollie->send(new GetPaginatedCustomerRequest)->toResource()[0]; /* * Generate a unique order id for this example. It is important to include this unique attribute @@ -24,7 +32,7 @@ /* * Determine the url parts to these example files. */ - $protocol = isset($_SERVER['HTTPS']) && strcasecmp('off', $_SERVER['HTTPS']) !== 0 ? "https" : "http"; + $protocol = isset($_SERVER['HTTPS']) && strcasecmp('off', $_SERVER['HTTPS']) !== 0 ? 'https' : 'http'; $hostname = $_SERVER['HTTP_HOST']; /** @@ -32,21 +40,20 @@ * * @See: https://docs.mollie.com/reference/v2/customers-api/create-customer-payment */ - $payment = $customer->createPayment([ - "amount" => [ - "value" => "10.00", // You must send the correct number of decimals, thus we enforce the use of strings - "currency" => "EUR", - ], - "description" => "First payment - Order #{$orderId}", - "redirectUrl" => "{$protocol}://{$hostname}/payments/return.php?order_id={$orderId}", - "webhookUrl" => "{$protocol}://{$hostname}/payments/webhook.php", - "metadata" => [ - "order_id" => $orderId, - ], + $payload = CreatePaymentPayloadFactory::new([ + 'description' => "First payment - Order #{$orderId}", + 'amount' => new Money('EUR', '10.00'), + 'redirectUrl' => "{$protocol}://{$hostname}/payments/return.php?order_id={$orderId}", + 'webhookUrl' => "{$protocol}://{$hostname}/payments/webhook.php", + 'metadata' => new Metadata([ + 'order_id' => $orderId, + ]), + 'sequenceType' => SequenceType::FIRST, + ])->create(); - // Flag this payment as a first payment to allow recurring payments later. - "sequenceType" => \Mollie\Api\Types\SequenceType::SEQUENCETYPE_FIRST, - ]); + $payment = $mollie->send( + new CreateCustomerPaymentRequest($customer->id, $payload) + ); /* * In this example we store the order with its payment status in a database. @@ -60,7 +67,7 @@ * After completion, the customer will have a pending or valid mandate that can be * used for recurring payments and subscriptions. */ - header("Location: " . $payment->getCheckoutUrl(), true, 303); + header('Location: '.$payment->getCheckoutUrl(), true, 303); } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/customers/create-customer-payment.php b/examples/customers/create-customer-payment.php index 5713dd18d..a8b278dc9 100644 --- a/examples/customers/create-customer-payment.php +++ b/examples/customers/create-customer-payment.php @@ -1,4 +1,5 @@ createPayment([ - "amount" => [ - "value" => "10.00", // You must send the correct number of decimals, thus we enforce the use of strings - "currency" => "EUR", + 'amount' => [ + 'value' => '10.00', // You must send the correct number of decimals, thus we enforce the use of strings + 'currency' => 'EUR', ], - "description" => "Order #{$orderId}", - "redirectUrl" => "{$protocol}://{$hostname}/payments/return.php?order_id={$orderId}", - "webhookUrl" => "{$protocol}://{$hostname}/payments/webhook.php", - "metadata" => [ - "order_id" => $orderId, + 'description' => "Order #{$orderId}", + 'redirectUrl' => "{$protocol}://{$hostname}/payments/return.php?order_id={$orderId}", + 'webhookUrl' => "{$protocol}://{$hostname}/payments/webhook.php", + 'metadata' => [ + 'order_id' => $orderId, ], ]); @@ -54,7 +55,7 @@ * Send the customer off to complete the payment. * This request should always be a GET, thus we enforce 303 http response code */ - header("Location: " . $payment->getCheckoutUrl(), true, 303); + header('Location: '.$payment->getCheckoutUrl(), true, 303); } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/customers/create-customer-recurring-payment.php b/examples/customers/create-customer-recurring-payment.php index dedae9179..039ee5b8c 100644 --- a/examples/customers/create-customer-recurring-payment.php +++ b/examples/customers/create-customer-recurring-payment.php @@ -1,4 +1,5 @@ customers->page(null, 1)[0]; - + $customer = $mollie->customers->collect(null, 1)[0]; + /* * Generate a unique order id for this example. */ @@ -23,7 +24,7 @@ /* * Determine the url parts to these example files. */ - $protocol = isset($_SERVER['HTTPS']) && strcasecmp('off', $_SERVER['HTTPS']) !== 0 ? "https" : "http"; + $protocol = isset($_SERVER['HTTPS']) && strcasecmp('off', $_SERVER['HTTPS']) !== 0 ? 'https' : 'http'; $hostname = $_SERVER['HTTP_HOST']; /** @@ -32,20 +33,20 @@ * @See: https://docs.mollie.com/reference/v2/customers-api/create-customer-payment */ $payment = $customer->createPayment([ - "amount" => [ - "value" => "10.00", // You must send the correct number of decimals, thus we enforce the use of strings - "currency" => "EUR", + 'amount' => [ + 'value' => '10.00', // You must send the correct number of decimals, thus we enforce the use of strings + 'currency' => 'EUR', ], - "description" => "On-demand payment - Order #{$orderId}", - "webhookUrl" => "{$protocol}://{$hostname}/payments/webhook.php", - "metadata" => [ - "order_id" => $orderId, + 'description' => "On-demand payment - Order #{$orderId}", + 'webhookUrl' => "{$protocol}://{$hostname}/payments/webhook.php", + 'metadata' => [ + 'order_id' => $orderId, ], // Flag this payment as a recurring payment. - "sequenceType" => \Mollie\Api\Types\SequenceType::SEQUENCETYPE_RECURRING, + 'sequenceType' => \Mollie\Api\Types\SequenceType::RECURRING, ]); - + /* * In this example we store the order with its payment status in a database. */ @@ -55,8 +56,8 @@ * The payment will be either pending or paid immediately. The customer * does not have to perform any payment steps. */ - echo "

Selected mandate is '" . htmlspecialchars($payment->mandateId) . "' (" . htmlspecialchars($payment->method) . ").

\n"; - echo "

The payment status is '" . htmlspecialchars($payment->status) . "'.

\n"; + echo "

Selected mandate is '".htmlspecialchars($payment->mandateId)."' (".htmlspecialchars($payment->method).").

\n"; + echo "

The payment status is '".htmlspecialchars($payment->status)."'.

\n"; } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/customers/create-customer.php b/examples/customers/create-customer.php index 3608ab9cb..eab9c2a6a 100644 --- a/examples/customers/create-customer.php +++ b/examples/customers/create-customer.php @@ -1,4 +1,5 @@ customers->create([ - "name" => "Luke Skywalker", - "email" => "luke@example.org", - "metadata" => [ - "isJedi" => true, + 'name' => 'Luke Skywalker', + 'email' => 'luke@example.org', + 'metadata' => [ + 'isJedi' => true, ], ]); - echo "

New customer created " . htmlspecialchars($customer->id) . " (" . htmlspecialchars($customer->name) . ").

"; + echo '

New customer created '.htmlspecialchars($customer->id).' ('.htmlspecialchars($customer->name).').

'; } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/customers/delete-customer.php b/examples/customers/delete-customer.php index 188e92640..2db397211 100644 --- a/examples/customers/delete-customer.php +++ b/examples/customers/delete-customer.php @@ -1,4 +1,5 @@ customers->delete("cst_fE3F6nvX"); - echo "

Customer deleted!

"; + $mollie->customers->delete('cst_fE3F6nvX'); + echo '

Customer deleted!

'; } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/customers/list-customer-payments.php b/examples/customers/list-customer-payments.php index ae7329baa..39d0167dd 100644 --- a/examples/customers/list-customer-payments.php +++ b/examples/customers/list-customer-payments.php @@ -1,4 +1,5 @@ customers->page(null, 1)[0]; + $customer = $mollie->customers->collect(null, 1)[0]; /* * Get the all payments for this API key ordered by newest. */ $payments = $customer->payments(); - echo "'; } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/customers/update-customer.php b/examples/customers/update-customer.php index 49984e362..21d40a0f3 100644 --- a/examples/customers/update-customer.php +++ b/examples/customers/update-customer.php @@ -1,4 +1,5 @@ customers->get("cst_cUe8HjeBuz"); + $customer = $mollie->customers->get('cst_cUe8HjeBuz'); /** * Customer fields that can be updated. * * @See https://docs.mollie.com/reference/v2/customers-api/update-customer */ - $customer->name = "Luke Sky"; - $customer->email = "luke@example.org"; - $customer->locale = "en_US"; + $customer->name = 'Luke Sky'; + $customer->email = 'luke@example.org'; + $customer->locale = 'en_US'; $customer->metadata->isJedi = true; $customer->update(); - echo "

Customer updated: " . htmlspecialchars($customer->name) . "

"; + echo '

Customer updated: '.htmlspecialchars($customer->name).'

'; } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/functions.php b/examples/functions.php index d97ef07e7..4c9c29981 100644 --- a/examples/functions.php +++ b/examples/functions.php @@ -1,4 +1,5 @@ setApiKey("test_dHar4XY7LxsDOtmnkVtjNVWXLSlXsM"); +$mollie = new \Mollie\Api\MollieApiClient; +$mollie->setApiKey('test_dHar4XY7LxsDOtmnkVtjNVWXLSlXsM'); diff --git a/examples/initialize_with_oauth.php b/examples/initialize_with_oauth.php index a12ef401a..669175c46 100644 --- a/examples/initialize_with_oauth.php +++ b/examples/initialize_with_oauth.php @@ -7,13 +7,13 @@ ini_set('display_startup_errors', '1'); error_reporting(E_ALL); -require_once __DIR__ . "/../vendor/autoload.php"; -require_once __DIR__ . "/functions.php"; +require_once __DIR__.'/../vendor/autoload.php'; +require_once __DIR__.'/functions.php'; /* * Initialize the Mollie API library with OAuth. * * See: https://docs.mollie.com/oauth/overview */ -$mollie = new \Mollie\Api\MollieApiClient(); -$mollie->setAccessToken("access_Wwvu7egPcJLLJ9Kb7J632x8wJ2zMeJ"); +$mollie = new \Mollie\Api\MollieApiClient; +$mollie->setAccessToken('access_Wwvu7egPcJLLJ9Kb7J632x8wJ2zMeJ'); diff --git a/examples/invoices/list-invoices.php b/examples/invoices/list-invoices.php index 53b539ebb..be0c45158 100644 --- a/examples/invoices/list-invoices.php +++ b/examples/invoices/list-invoices.php @@ -1,4 +1,5 @@ invoices->all(); foreach ($invoices as $invoice) { - echo '
  • Invoice ' . htmlspecialchars($invoice->reference) . ': (' . htmlspecialchars($invoice->issuedAt) . ')'; - echo '
    Status: ' . $invoice->status; + echo '
  • Invoice '.htmlspecialchars($invoice->reference).': ('.htmlspecialchars($invoice->issuedAt).')'; + echo '
    Status: '.$invoice->status; echo ''; foreach ($invoice->lines as $line) { echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; echo ''; } - echo ''; + echo ''; echo '
    PeriodDescriptionCountVAT PercentageAmount
    ' . htmlspecialchars($line->period) . '' . htmlspecialchars($line->description) . '' . htmlspecialchars($line->count) . '' . htmlspecialchars($line->vatPercentage) . '' . htmlspecialchars($line->amount->currency . " " . $line->amount->value) . ''.htmlspecialchars($line->period).''.htmlspecialchars($line->description).''.htmlspecialchars($line->count).''.htmlspecialchars($line->vatPercentage).''.htmlspecialchars($line->amount->currency.' '.$line->amount->value).'
    Gross Total' . htmlspecialchars($invoice->grossAmount->value . " " . $invoice->grossAmount->currency) . '
    Gross Total'.htmlspecialchars($invoice->grossAmount->value.' '.$invoice->grossAmount->currency).'
    '; - echo 'Click here to open PDF'; + echo 'Click here to open PDF'; echo '
  • '; } } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/mandates/create-mandate.php b/examples/mandates/create-mandate.php index b628e9255..92a30ce4f 100644 --- a/examples/mandates/create-mandate.php +++ b/examples/mandates/create-mandate.php @@ -1,4 +1,5 @@ customers->page(null, 1)[0]; + $customer = $mollie->customers->collect(null, 1)[0]; /* * Create a SEPA Direct Debit mandate for the customer */ $mandate = $customer->createMandate([ - "method" => \Mollie\Api\Types\MandateMethod::DIRECTDEBIT, - "consumerAccount" => 'NL34ABNA0243341423', - "consumerName" => 'B. A. Example', + 'method' => \Mollie\Api\Types\MandateMethod::DIRECTDEBIT, + 'consumerAccount' => 'NL34ABNA0243341423', + 'consumerName' => 'B. A. Example', ]); - echo "

    Mandate created with id " . $mandate->id . " for customer " . $customer->name . "

    "; + echo '

    Mandate created with id '.$mandate->id.' for customer '.$customer->name.'

    '; } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/mandates/list-mandates.php b/examples/mandates/list-mandates.php index 7d0161643..fd37db867 100644 --- a/examples/mandates/list-mandates.php +++ b/examples/mandates/list-mandates.php @@ -1,4 +1,5 @@ customers->get("cst_cUa8HjKBus"); + $customer = $mollie->customers->get('cst_cUa8HjKBus'); /* * List the mandates of this customer */ - echo "'; } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/mandates/revoke-mandate.php b/examples/mandates/revoke-mandate.php index ba7093352..f499bbfaf 100644 --- a/examples/mandates/revoke-mandate.php +++ b/examples/mandates/revoke-mandate.php @@ -1,4 +1,5 @@ customers->get("cst_cUa8HjKBus"); + $customer = $mollie->customers->get('cst_cUa8HjKBus'); /* * Retrieve an existing mandate by his mandateId */ - $mandate = $customer->getMandate("mdt_pa3s7rGnrC"); + $mandate = $customer->getMandate('mdt_pa3s7rGnrC'); /* * Revoke the mandate */ $mandate->revoke(); - echo "

    Mandate has been successfully revoked.

    "; + echo '

    Mandate has been successfully revoked.

    '; } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/orders/cancel-order-lines.php b/examples/orders/cancel-order-lines.php deleted file mode 100644 index f0f827f7c..000000000 --- a/examples/orders/cancel-order-lines.php +++ /dev/null @@ -1,44 +0,0 @@ -orders->get($orderId); - $line = $order->lines()->get($lineId); - if ($line && $line->isCancelable) { - $order->cancelLines([ - 'lines' => [ - [ - 'id' => $lineId, - 'quantity' => 1, // optional parameter - ], - ], - ]); - - $updatedOrder = $mollie->orders->get($orderId); - - echo 'Your order ' . $order->id . ' was updated:'; - foreach ($order->lines as $line) { - echo $line->description . '. Status: ' . $line->status . '.'; - } - } else { - echo "Unable to cancel line " . $lineId . " for your order " . $orderId . "."; - } -} catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); -} diff --git a/examples/orders/cancel-order.php b/examples/orders/cancel-order.php deleted file mode 100644 index 4c4143594..000000000 --- a/examples/orders/cancel-order.php +++ /dev/null @@ -1,26 +0,0 @@ -orders->get("ord_pbjz8x"); - if ($order->isCancelable) { - $canceledOrder = $order->cancel(); - echo "Your order " . $order->id . " has been canceled."; - } else { - echo "Unable to cancel your order " . $order->id . "."; - } -} catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); -} diff --git a/examples/orders/create-order.php b/examples/orders/create-order.php deleted file mode 100644 index 9dc431899..000000000 --- a/examples/orders/create-order.php +++ /dev/null @@ -1,118 +0,0 @@ -orders->create([ - "amount" => [ - "value" => "1027.99", - "currency" => "EUR", - ], - "billingAddress" => [ - "streetAndNumber" => "Keizersgracht 313", - "postalCode" => "1016 EE", - "city" => "Amsterdam", - "country" => "nl", - "givenName" => "Luke", - "familyName" => "Skywalker", - "email" => "luke@skywalker.com", - ], - "shippingAddress" => [ - "streetAndNumber" => "Keizersgracht 313", - "postalCode" => "1016 EE", - "city" => "Amsterdam", - "country" => "nl", - "givenName" => "Luke", - "familyName" => "Skywalker", - "email" => "luke@skywalker.com", - ], - "metadata" => [ - "order_id" => $orderId, - ], - "consumerDateOfBirth" => "1958-01-31", - "locale" => "en_US", - "orderNumber" => strval($orderId), - "redirectUrl" => "{$protocol}://{$hostname}{$path}/return.php?order_id={$orderId}", - "webhookUrl" => "{$protocol}://{$hostname}{$path}/webhook.php", - "method" => "ideal", - "lines" => [ - [ - "sku" => "5702016116977", - "name" => "LEGO 42083 Bugatti Chiron", - "productUrl" => "https://shop.lego.com/nl-NL/Bugatti-Chiron-42083", - "imageUrl" => 'https://sh-s7-live-s.legocdn.com/is/image//LEGO/42083_alt1?$main$', - "quantity" => 2, - "vatRate" => "21.00", - "unitPrice" => [ - "currency" => "EUR", - "value" => "399.00", - ], - "totalAmount" => [ - "currency" => "EUR", - "value" => "698.00", - ], - "discountAmount" => [ - "currency" => "EUR", - "value" => "100.00", - ], - "vatAmount" => [ - "currency" => "EUR", - "value" => "121.14", - ], - ], - [ - "type" => "digital", - "sku" => "5702015594028", - "name" => "LEGO 42056 Porsche 911 GT3 RS", - "productUrl" => "https://shop.lego.com/nl-NL/Porsche-911-GT3-RS-42056", - "imageUrl" => 'https://sh-s7-live-s.legocdn.com/is/image/LEGO/42056?$PDPDefault$', - "quantity" => 1, - "vatRate" => "21.00", - "unitPrice" => [ - "currency" => "EUR", - "value" => "329.99", - ], - "totalAmount" => [ - "currency" => "EUR", - "value" => "329.99", - ], - "vatAmount" => [ - "currency" => "EUR", - "value" => "57.27", - ], - ], - ], - ]); - - /* - * Send the customer off to complete the order payment. - * This request should always be a GET, thus we enforce 303 http response code - */ - header("Location: " . $order->getCheckoutUrl(), true, 303); -} catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); -} diff --git a/examples/orders/list-methods.php b/examples/orders/list-methods.php deleted file mode 100644 index 5289b160c..000000000 --- a/examples/orders/list-methods.php +++ /dev/null @@ -1,28 +0,0 @@ -methods->all(['resource' => 'orders']); - foreach ($methods as $method) { - echo '
    '; - echo ' '; - echo htmlspecialchars($method->description) . ' (' . htmlspecialchars($method->id) . ')'; - echo '
    '; - } -} catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); -} diff --git a/examples/orders/list-orders.php b/examples/orders/list-orders.php deleted file mode 100644 index e311b16e4..000000000 --- a/examples/orders/list-orders.php +++ /dev/null @@ -1,48 +0,0 @@ -'; - $latestOrders = $mollie->orders->page(); - printOrders($latestOrders); - - $previousOrders = $latestOrders->next(); - printOrders($previousOrders); - echo ''; -} catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); -} - -function printOrders($orders) -{ - if (empty($orders)) { - return ; - } - - foreach ($orders as $order) { - echo '
  • Order ' . htmlspecialchars($order->id) . ': (' . htmlspecialchars($order->createdAt) . ')'; - echo '
    Status: ' . htmlspecialchars($order->status); - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo '
    Billed toShipped toTotal amount
    ' . htmlspecialchars($order->shippingAddress->givenName) . ' ' . htmlspecialchars($order->shippingAddress->familyName) . '' . htmlspecialchars($order->billingAddress->givenName) . ' ' . htmlspecialchars($order->billingAddress->familyName) . '' . htmlspecialchars($order->amount->currency) . str_replace('.', ',', htmlspecialchars($order->amount->value)) . '
    '; - echo 'Click here to pay'; - echo '
  • '; - } -} diff --git a/examples/orders/refund-order-completely.php b/examples/orders/refund-order-completely.php deleted file mode 100644 index 35e112f29..000000000 --- a/examples/orders/refund-order-completely.php +++ /dev/null @@ -1,25 +0,0 @@ -orders->get('ord_8wmqcHMN4U'); - $refund = $order->refundAll(); - - echo 'Refund ' . $refund->id . ' was created for order ' . $order->id; - echo 'You will receive ' . $refund->amount->currency . $refund->amount->value; -} catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); -} diff --git a/examples/orders/refund-order-partially.php b/examples/orders/refund-order-partially.php deleted file mode 100644 index 5970de291..000000000 --- a/examples/orders/refund-order-partially.php +++ /dev/null @@ -1,33 +0,0 @@ -orders->get('ord_8wmqcHMN4U'); - $refund = $order->refund([ - 'lines' => [ - [ - 'id' => 'odl_dgtxyl', - 'quantity' => 1, - ], - ], - "description" => "Required quantity not in stock, refunding one photo book.", - ]); - - echo 'Refund ' . $refund->id . ' was created for part of your order ' . $order->id; - echo 'You will receive ' . $refund->amount->currency . $refund->amount->value; -} catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); -} diff --git a/examples/orders/update-order-line.php b/examples/orders/update-order-line.php deleted file mode 100644 index 8456eb044..000000000 --- a/examples/orders/update-order-line.php +++ /dev/null @@ -1,44 +0,0 @@ -orders->get("ord_kEn1PlbGa"); - $line = $order->lines()->get('odl_1.uh5oen'); - - $line->name = "Update line name description"; - - $orderWithNewLineName = $line->update(); - - /* - * Send the customer off to complete the order payment. - * This request should always be a GET, thus we enforce 303 http response code - */ - header("Location: " . $orderWithNewLineName->getCheckoutUrl(), true, 303); -} catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); -} diff --git a/examples/orders/update-order-lines-multiple.php b/examples/orders/update-order-lines-multiple.php deleted file mode 100644 index 0fded1460..000000000 --- a/examples/orders/update-order-lines-multiple.php +++ /dev/null @@ -1,71 +0,0 @@ - \Mollie\Api\Types\OrderLineUpdateOperationType::ADD, - "data" => [ - "type" => \Mollie\Api\Types\OrderLineType::TYPE_DIGITAL, - "name" => "Adding new orderline", - "quantity" => 2, - "sku" => "12345679", - "totalAmount" => [ - "currency" => "EUR", - "value" => "30.00", - ], - "unitPrice" => [ - "currency" => "EUR", - "value" => "15.00", - ], - "vatAmount" => [ - "currency" => "EUR", - "value" => "0.00", - ], - "vatRate" => "0.00", - ], - ]; - $updateOrderLine = [ - "operation" => \Mollie\Api\Types\OrderLineUpdateOperationType::UPDATE, - "data" => [ - "id" => "odl_1.1l9vx0", - "name" => "New order line name", - ], - ]; - $cancelOrderLine = [ - "operation" => \Mollie\Api\Types\OrderLineUpdateOperationType::CANCEL, - "data" => [ - "id" => "odl_1.4hqjw6", - ], - ]; - - $operations = [ - $addOrderLine, - $updateOrderLine, - $cancelOrderLine, - ]; - - $order = $mollie->orderLines->updateMultiple('ord_pbjz8x', $operations); - -} catch (\Mollie\Api\Exceptions\ApiException $e) { - /* - * When updating order lines for orders that used a pay after delivery method such as Klarna Pay Later, the - * supplier (Klarna) may decline the requested changes. This results in an error response from the Mollie API. - * The order initial remains intact without applying the requested changes. - */ - echo "API call failed: " . htmlspecialchars($e->getMessage()); -} diff --git a/examples/orders/update-order.php b/examples/orders/update-order.php deleted file mode 100644 index f33e72658..000000000 --- a/examples/orders/update-order.php +++ /dev/null @@ -1,45 +0,0 @@ -orders->get("ord_kEn1PlbGa"); - $order->billingAddress->organizationName = "Mollie B.V."; - $order->billingAddress->streetAndNumber = "Keizersgracht 126"; - $order->billingAddress->city = "Amsterdam"; - $order->billingAddress->region = "Noord-Holland"; - $order->billingAddress->postalCode = "1234AB"; - $order->billingAddress->country = "NL"; - $order->billingAddress->title = "Dhr"; - $order->billingAddress->givenName = "Piet"; - $order->billingAddress->familyName = "Mondriaan"; - $order->billingAddress->email = "piet@mondriaan.com"; - $order->billingAddress->phone = "+31208202070"; - $order->update(); - - /* - * Send the customer off to complete the order payment. - * This request should always be a GET, thus we enforce 303 http response code - */ - header("Location: " . $order->getCheckoutUrl(), true, 303); -} catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); -} diff --git a/examples/orders/webhook.php b/examples/orders/webhook.php deleted file mode 100644 index c2bd5ce07..000000000 --- a/examples/orders/webhook.php +++ /dev/null @@ -1,50 +0,0 @@ -orders->get($_POST["id"]); - $orderId = $order->metadata->order_id; - - /* - * Update the order in the database. - */ - database_write($orderId, $order->status); - - if ($order->isPaid() || $order->isAuthorized()) { - /* - * The order is paid or authorized - * At this point you'd probably want to start the process of delivering the product to the customer. - */ - } elseif ($order->isCanceled()) { - /* - * The order is canceled. - */ - } elseif ($order->isExpired()) { - /* - * The order is expired. - */ - } elseif ($order->isCompleted()) { - /* - * The order is completed. - */ - } elseif ($order->isPending()) { - /* - * The order is pending. - */ - } -} catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); -} diff --git a/examples/pagination/backwards.php b/examples/pagination/backwards.php index 2b87bad6e..bbd574402 100644 --- a/examples/pagination/backwards.php +++ b/examples/pagination/backwards.php @@ -1,4 +1,5 @@ orders->page($orderId); + $page = $mollie->orders->collect($orderId); while ($page->hasPrevious()) { foreach ($page as $order) { - echo($order->id); + echo $order->id; } $page = $page->previous(); @@ -51,8 +52,8 @@ // iterating backwards using the iterator by passing iterateBackwards = true // in php 8.0+ you could also use the named parameter syntax iterator(iterateBackwards: true) foreach ($mollie->orders->iterator(null, null, [], true) as $order) { - echo($order->id); + echo $order->id; } } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/pagination/basic_usage.php b/examples/pagination/basic_usage.php index 9411fe39a..6bd62d6ea 100644 --- a/examples/pagination/basic_usage.php +++ b/examples/pagination/basic_usage.php @@ -1,4 +1,5 @@ orders->page(); + $page = $mollie->orders->collect(); while ($page->hasNext()) { foreach ($page as $order) { - echo($order->id); + echo $order->id; } $page = $page->next(); } - // using the iterator we can iterate over all orders directly foreach ($mollie->orders->iterator() as $order) { - echo($order->id); + echo $order->id; } } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/payment-links/create-payment-link.php b/examples/payment-links/create-payment-link.php index a3f018929..8e8ecebc2 100644 --- a/examples/payment-links/create-payment-link.php +++ b/examples/payment-links/create-payment-link.php @@ -1,4 +1,5 @@ paymentLinks->create([ - "amount" => [ - "currency" => "EUR", - "value" => "10.00", // You must send the correct number of decimals, thus we enforce the use of strings + 'amount' => [ + 'currency' => 'EUR', + 'value' => '10.00', // You must send the correct number of decimals, thus we enforce the use of strings ], - "description" => "Bicycle tires", - "webhookUrl" => "{$protocol}://{$hostname}{$path}/webhook.php", // optional + 'description' => 'Bicycle tires', + 'webhookUrl' => "{$protocol}://{$hostname}{$path}/webhook.php", // optional ]); /* * Send the customer off to complete the payment. * This request should always be a GET, thus we enforce 303 http response code */ - header("Location: " . $paymentLink->getCheckoutUrl(), true, 303); + header('Location: '.$paymentLink->getCheckoutUrl(), true, 303); } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/payment-links/list-payment-links.php b/examples/payment-links/list-payment-links.php index b39c56cc5..f32bae2b8 100644 --- a/examples/payment-links/list-payment-links.php +++ b/examples/payment-links/list-payment-links.php @@ -1,4 +1,5 @@ paymentLinks->page(); + $paymentLinks = $mollie->paymentLinks->collect(); - echo "
      "; + echo '
        '; foreach ($paymentLinks as $paymentLink) { - echo "
      • "; - echo "" . htmlspecialchars($paymentLink->id) . "
        "; - echo htmlspecialchars($paymentLink->description) . "
        "; - echo htmlspecialchars($paymentLink->amount->currency) . " " . htmlspecialchars($paymentLink->amount->value) . "
        "; - echo "Link: " . htmlspecialchars($paymentLink->getCheckoutUrl()) . "
        "; + echo '
      • '; + echo "".htmlspecialchars($paymentLink->id).'
        '; + echo htmlspecialchars($paymentLink->description).'
        '; + echo htmlspecialchars($paymentLink->amount->currency).' '.htmlspecialchars($paymentLink->amount->value).'
        '; + echo 'Link: '.htmlspecialchars($paymentLink->getCheckoutUrl()).'
        '; - echo "
      • "; + echo ''; } - echo "
      "; + echo '
    '; } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/payments/create-capturable-payment.php b/examples/payments/create-capturable-payment.php index 36c078c2b..09b025a59 100644 --- a/examples/payments/create-capturable-payment.php +++ b/examples/payments/create-capturable-payment.php @@ -1,4 +1,5 @@ payments->create([ - "amount" => [ - "currency" => "EUR", - "value" => "10.00", // You must send the correct number of decimals, thus we enforce the use of strings + 'amount' => [ + 'currency' => 'EUR', + 'value' => '10.00', // You must send the correct number of decimals, thus we enforce the use of strings ], - "description" => "Order #{$orderId}", - "redirectUrl" => "{$protocol}://{$hostname}{$path}/return.php?order_id={$orderId}", - "webhookUrl" => "{$protocol}://{$hostname}{$path}/webhook.php", - "metadata" => [ - "order_id" => $orderId, + 'description' => "Order #{$orderId}", + 'redirectUrl' => "{$protocol}://{$hostname}{$path}/return.php?order_id={$orderId}", + 'webhookUrl' => "{$protocol}://{$hostname}{$path}/webhook.php", + 'metadata' => [ + 'order_id' => $orderId, ], - "captureMode" => 'manual', - "method" => "creditcard", + 'captureMode' => 'manual', + 'method' => 'creditcard', ]); /* @@ -58,7 +59,7 @@ * Send the customer off to complete the payment. * This request should always be a GET, thus we enforce 303 http response code */ - header("Location: " . $payment->getCheckoutUrl(), true, 303); + header('Location: '.$payment->getCheckoutUrl(), true, 303); } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/payments/create-ideal-payment.php b/examples/payments/create-ideal-payment.php index 92328a7fe..7fe839d64 100644 --- a/examples/payments/create-ideal-payment.php +++ b/examples/payments/create-ideal-payment.php @@ -1,4 +1,5 @@ methods->get(\Mollie\Api\Types\PaymentMethod::IDEAL, ["include" => "issuers"]); + if ($_SERVER['REQUEST_METHOD'] != 'POST') { + $method = $mollie->methods->get(\Mollie\Api\Types\PaymentMethod::IDEAL, ['include' => 'issuers']); echo '
    Select your bank:
    "; - echo "

    "; - echo 'Create a payment
    '; - echo 'Create an iDEAL payment
    '; - echo 'List payments
    '; - echo "

    "; + echo '

    '; + echo 'Create a payment
    '; + echo 'Create an iDEAL payment
    '; + echo 'List payments
    '; + echo '

    '; } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/payments/return.php b/examples/payments/return.php index ec53f0bbc..fef8ca35a 100644 --- a/examples/payments/return.php +++ b/examples/payments/return.php @@ -1,4 +1,5 @@ payments->get($_GET["order_id"]); +if ($status !== 'paid') { + $payment = $mollie->payments->get($_GET['order_id']); $status = $payment->status; /* * Optionally, update the database here, or wait for the webhook to arrive. @@ -30,13 +31,13 @@ /* * Determine the url parts to these example files. */ -$protocol = isset($_SERVER['HTTPS']) && strcasecmp('off', $_SERVER['HTTPS']) !== 0 ? "https" : "http"; +$protocol = isset($_SERVER['HTTPS']) && strcasecmp('off', $_SERVER['HTTPS']) !== 0 ? 'https' : 'http'; $hostname = $_SERVER['HTTP_HOST']; $path = dirname($_SERVER['REQUEST_URI'] ?? $_SERVER['PHP_SELF']); -echo "

    Your payment status is '" . htmlspecialchars($status) . "'.

    "; -echo "

    "; -echo 'Create a payment
    '; -echo 'Create an iDEAL payment
    '; -echo 'List payments
    '; -echo "

    "; +echo "

    Your payment status is '".htmlspecialchars($status)."'.

    "; +echo '

    '; +echo 'Create a payment
    '; +echo 'Create an iDEAL payment
    '; +echo 'List payments
    '; +echo '

    '; diff --git a/examples/payments/update-payment.php b/examples/payments/update-payment.php index 8149d5a4c..cf5ae03e7 100644 --- a/examples/payments/update-payment.php +++ b/examples/payments/update-payment.php @@ -1,4 +1,5 @@ payments->get("tr_7UhSN1zuXS"); + $payment = $mollie->payments->get('tr_7UhSN1zuXS'); $newOrderId = 98765; - $payment->description = "Order #".$newOrderId; - $payment->redirectUrl = "https://example.org/webshop/order/98765/"; - $payment->webhookUrl = "https://example.org/webshop/payments/webhook/"; - $payment->metadata = ["order_id" => $newOrderId]; + $payment->description = 'Order #'.$newOrderId; + $payment->redirectUrl = 'https://example.org/webshop/order/98765/'; + $payment->webhookUrl = 'https://example.org/webshop/payments/webhook/'; + $payment->metadata = ['order_id' => $newOrderId]; $payment = $payment->update(); /* @@ -37,7 +37,7 @@ * Send the customer off to complete the payment. * This request should always be a GET, thus we enforce 303 http response code */ - header("Location: " . $payment->getCheckoutUrl(), true, 303); + header('Location: '.$payment->getCheckoutUrl(), true, 303); } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/payments/webhook.php b/examples/payments/webhook.php index ef907b763..6eab0b09e 100644 --- a/examples/payments/webhook.php +++ b/examples/payments/webhook.php @@ -1,4 +1,5 @@ payments->get($_POST["id"]); + $payment = $mollie->payments->get($_POST['id']); $orderId = $payment->metadata->order_id; /* @@ -61,5 +62,5 @@ */ } } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/profiles/create-profile.php b/examples/profiles/create-profile.php index c06f87988..804a44f1e 100644 --- a/examples/profiles/create-profile.php +++ b/examples/profiles/create-profile.php @@ -1,4 +1,5 @@ profiles->create([ - "name" => "My website name", - "website" => "https://www.mywebsite.com", - "email" => "info@mywebsite.com", - "phone" => "+31208202070", - "businessCategory" => "MARKETPLACES", - "mode" => "live", + 'name' => 'My website name', + 'website' => 'https://www.mywebsite.com', + 'email' => 'info@mywebsite.com', + 'phone' => '+31208202070', + 'businessCategory' => 'MARKETPLACES', + 'mode' => 'live', ]); - echo "

    Profile created: " . htmlspecialchars($profile->name) . "

    "; + echo '

    Profile created: '.htmlspecialchars($profile->name).'

    '; } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "

    API call failed: " . htmlspecialchars($e->getMessage()) . "

    "; + echo '

    API call failed: '.htmlspecialchars($e->getMessage()).'

    '; } diff --git a/examples/profiles/delete-profile.php b/examples/profiles/delete-profile.php index 3ca675ea2..39b7f1969 100644 --- a/examples/profiles/delete-profile.php +++ b/examples/profiles/delete-profile.php @@ -1,4 +1,5 @@ profiles->delete("pfl_v9hTwCvYqw"); - echo "

    Profile deleted

    "; + $profile = $mollie->profiles->delete('pfl_v9hTwCvYqw'); + echo '

    Profile deleted

    '; } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "

    API call failed: " . htmlspecialchars($e->getMessage()) . "

    "; + echo '

    API call failed: '.htmlspecialchars($e->getMessage()).'

    '; } diff --git a/examples/profiles/list-profiles.php b/examples/profiles/list-profiles.php index 49a88d6dc..146b91978 100644 --- a/examples/profiles/list-profiles.php +++ b/examples/profiles/list-profiles.php @@ -1,4 +1,5 @@ profiles->page(); + $profiles = $mollie->profiles->collect(); foreach ($profiles as $profile) { echo '
    '; - echo htmlspecialchars($profile->name) . - ' - ' . htmlspecialchars($profile->website) . - ' (' . htmlspecialchars($profile->id) . ')'; + echo htmlspecialchars($profile->name). + ' - '.htmlspecialchars($profile->website). + ' ('.htmlspecialchars($profile->id).')'; echo '
    '; } } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/profiles/update-profile.php b/examples/profiles/update-profile.php index 69a384e17..97a1e63f0 100644 --- a/examples/profiles/update-profile.php +++ b/examples/profiles/update-profile.php @@ -1,4 +1,5 @@ profiles->get("pfl_eA4MSz7Bvy"); + $profile = $mollie->profiles->get('pfl_eA4MSz7Bvy'); /** * Profile fields that can be updated. * * @See https://docs.mollie.com/reference/v2/profiles-api/update-profile */ - $profile->name = "Mollie B.V."; + $profile->name = 'Mollie B.V.'; $profile->website = 'www.mollie.com'; $profile->email = 'info@mollie.com'; $profile->phone = '0612345670'; - $profile->businessCategory = "MARKETPLACES"; + $profile->businessCategory = 'MARKETPLACES'; $profile->update(); - echo "

    Profile updated: " . htmlspecialchars($profile->name) . "

    "; + echo '

    Profile updated: '.htmlspecialchars($profile->name).'

    '; } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "

    API call failed: " . htmlspecialchars($e->getMessage()) . "

    "; + echo '

    API call failed: '.htmlspecialchars($e->getMessage()).'

    '; } diff --git a/examples/sales-invoices/create-sales-invoice.php b/examples/sales-invoices/create-sales-invoice.php new file mode 100644 index 000000000..e1d6cd0e4 --- /dev/null +++ b/examples/sales-invoices/create-sales-invoice.php @@ -0,0 +1,50 @@ +salesInvoices->create([ + 'currency' => 'EUR', + 'status' => SalesInvoiceStatus::DRAFT, + 'vatScheme' => 'standard', + 'vatMode' => 'inclusive', + 'paymentTerm' => '30 days', + 'recipientIdentifier' => 'XXXXX', + 'recipient' => [ + 'type' => 'consumer', + 'email' => 'darth@vader.deathstar', + 'streetAndNumber' => 'Sample Street 12b', + 'postalCode' => '2000 AA', + 'city' => 'Amsterdam', + 'country' => 'NL', + 'locale' => 'nl_NL', + ], + 'lines' => [ + [ + 'description' => 'Monthly subscription fee', + 'quantity' => 1, + 'vatRate' => '21', + 'unitPrice' => [ + 'currency' => 'EUR', + 'value' => '10.00', // Corrected the format from '10,00' to '10.00' to match typical API expectations + ], + ], + ], + ]); + + echo '

    New sales invoice created with ID: '.htmlspecialchars($salesInvoice->id).'

    '; +} catch (\Mollie\Api\Exceptions\ApiException $e) { + echo 'API call failed: '.htmlspecialchars($e->getMessage()); +} diff --git a/examples/sales-invoices/delete-sales-invoice.php b/examples/sales-invoices/delete-sales-invoice.php new file mode 100644 index 000000000..eb75be6bf --- /dev/null +++ b/examples/sales-invoices/delete-sales-invoice.php @@ -0,0 +1,26 @@ +salesInvoices->delete($invoiceId); + + echo '

    Sales invoice deleted with ID: '.htmlspecialchars($invoiceId).'

    '; +} catch (\Mollie\Api\Exceptions\ApiException $e) { + echo 'API call failed: '.htmlspecialchars($e->getMessage()); +} diff --git a/examples/sales-invoices/list-sales-invoices.php b/examples/sales-invoices/list-sales-invoices.php new file mode 100644 index 000000000..7eb1d6e03 --- /dev/null +++ b/examples/sales-invoices/list-sales-invoices.php @@ -0,0 +1,29 @@ +'; + $salesInvoices = $mollie->salesInvoices->page(); + foreach ($salesInvoices as $invoice) { + echo '
  • Invoice '.htmlspecialchars($invoice->id).': ('.htmlspecialchars($invoice->issuedAt).')'; + echo '
    Status: '.htmlspecialchars($invoice->status).''; + echo '
    Total Amount: '.htmlspecialchars($invoice->amount->currency).' '.htmlspecialchars($invoice->amount->value).''; + echo '
  • '; + } + echo ''; +} catch (\Mollie\Api\Exceptions\ApiException $e) { + echo 'API call failed: '.htmlspecialchars($e->getMessage()); +} diff --git a/examples/sales-invoices/update-sales-invoice.php b/examples/sales-invoices/update-sales-invoice.php new file mode 100644 index 000000000..27433ecb8 --- /dev/null +++ b/examples/sales-invoices/update-sales-invoice.php @@ -0,0 +1,41 @@ +salesInvoices->update($invoiceId, [ + 'status' => \Mollie\Api\Types\SalesInvoiceStatus::PAID, + 'recipientIdentifier' => 'XXXXX', + 'lines' => [ + [ + 'id' => 'line_001', + 'description' => 'Updated subscription fee', + 'quantity' => 2, + 'vatRate' => '21', + 'unitPrice' => [ + 'currency' => 'EUR', + 'value' => '15.00', + ], + ], + ], + ]); + + echo '

    Sales invoice updated with ID: '.htmlspecialchars($updatedInvoice->id).'

    '; +} catch (\Mollie\Api\Exceptions\ApiException $e) { + echo 'API call failed: '.htmlspecialchars($e->getMessage()); +} diff --git a/examples/sessions/cancel-session.php b/examples/sessions/cancel-session.php index 2b679b546..1545b50e4 100644 --- a/examples/sessions/cancel-session.php +++ b/examples/sessions/cancel-session.php @@ -1,4 +1,5 @@ sessions->get("sess_dfsklg13jO"); + $session = $mollie->sessions->get('sess_dfsklg13jO'); $session->cancel(); } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/sessions/create-session.php b/examples/sessions/create-session.php index 5f9f351ba..3f2836ba3 100644 --- a/examples/sessions/create-session.php +++ b/examples/sessions/create-session.php @@ -1,4 +1,5 @@ sessions->create([ - "paymentData" => [ - "amount" => [ - "value" => "10.00", - "currency" => "EUR", + 'paymentData' => [ + 'amount' => [ + 'value' => '10.00', + 'currency' => 'EUR', ], - "description" => "Order #12345", + 'description' => 'Order #12345', ], - "method" => "paypal", - "methodDetails" => [ - "checkoutFlow" => "express", + 'method' => 'paypal', + 'methodDetails' => [ + 'checkoutFlow' => 'express', ], - "returnUrl" => "{$protocol}://{$hostname}{$path}/shippingSelection.php?order_id={$sessionId}", - "cancelUrl" => "{$protocol}://{$hostname}{$path}/cancel.php?order_id={$sessionId}", + 'returnUrl' => "{$protocol}://{$hostname}{$path}/shippingSelection.php?order_id={$sessionId}", + 'cancelUrl' => "{$protocol}://{$hostname}{$path}/cancel.php?order_id={$sessionId}", ]); /* * Send the customer off to complete the payment. * This request should always be a GET, thus we enforce 303 http response code */ - header("Location: " . $session->getRedirectUrl(), true, 303); + header('Location: '.$session->getRedirectUrl(), true, 303); } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/sessions/list-sessions.php b/examples/sessions/list-sessions.php index 9a50b897c..fc1c66d12 100644 --- a/examples/sessions/list-sessions.php +++ b/examples/sessions/list-sessions.php @@ -1,14 +1,14 @@ '; } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } function printSessions($sessions) @@ -33,16 +33,16 @@ function printSessions($sessions) } foreach ($sessions as $session) { - echo '
  • Session ' . htmlspecialchars($session->id) . ': (' . htmlspecialchars($session->failedAt) . ')'; - echo '
    Status: ' . htmlspecialchars($session->status); + echo '
  • Session '.htmlspecialchars($session->id).': ('.htmlspecialchars($session->failedAt).')'; + echo '
    Status: '.htmlspecialchars($session->status); echo ''; echo ''; - echo ''; - echo ''; - echo ''; + echo ''; + echo ''; + echo ''; echo ''; echo '
    Billed toShipped toTotal amount
    ' . htmlspecialchars($session->shippingAddress->givenName) . ' ' . htmlspecialchars($session->shippingAddress->familyName) . '' . htmlspecialchars($session->billingAddress->givenName) . ' ' . htmlspecialchars($session->billingAddress->familyName) . '' . htmlspecialchars($session->amount->currency) . str_replace('.', ',', htmlspecialchars($session->amount->value)) . ''.htmlspecialchars($session->shippingAddress->givenName).' '.htmlspecialchars($session->shippingAddress->familyName).''.htmlspecialchars($session->billingAddress->givenName).' '.htmlspecialchars($session->billingAddress->familyName).''.htmlspecialchars($session->amount->currency).str_replace('.', ',', htmlspecialchars($session->amount->value)).'
    '; - echo 'Click here to pay'; + echo 'Click here to pay'; echo '
  • '; } } diff --git a/examples/sessions/update-session.php b/examples/sessions/update-session.php index 7c489f454..d6b742c7c 100644 --- a/examples/sessions/update-session.php +++ b/examples/sessions/update-session.php @@ -1,4 +1,5 @@ sessions->get("sess_dfsklg13jO"); - $session->billingAddress->organizationName = "Mollie B.V."; - $session->billingAddress->streetAndNumber = "Keizersgracht 126"; - $session->billingAddress->city = "Amsterdam"; - $session->billingAddress->region = "Noord-Holland"; - $session->billingAddress->postalCode = "1234AB"; - $session->billingAddress->country = "NL"; - $session->billingAddress->title = "Dhr"; - $session->billingAddress->givenName = "Piet"; - $session->billingAddress->familyName = "Mondriaan"; - $session->billingAddress->email = "piet@mondriaan.com"; - $session->billingAddress->phone = "+31208202070"; + $session = $mollie->sessions->get('sess_dfsklg13jO'); + $session->billingAddress->organizationName = 'Mollie B.V.'; + $session->billingAddress->streetAndNumber = 'Keizersgracht 126'; + $session->billingAddress->city = 'Amsterdam'; + $session->billingAddress->region = 'Noord-Holland'; + $session->billingAddress->postalCode = '1234AB'; + $session->billingAddress->country = 'NL'; + $session->billingAddress->title = 'Dhr'; + $session->billingAddress->givenName = 'Piet'; + $session->billingAddress->familyName = 'Mondriaan'; + $session->billingAddress->email = 'piet@mondriaan.com'; + $session->billingAddress->phone = '+31208202070'; $session->update(); /* * Send the customer off to complete the order payment. * This request should always be a GET, thus we enforce 303 http response code */ - header("Location: " . $session->getRedirectUrl(), true, 303); + header('Location: '.$session->getRedirectUrl(), true, 303); } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/settlements/list-settlements.php b/examples/settlements/list-settlements.php index cc93c893f..707183fda 100644 --- a/examples/settlements/list-settlements.php +++ b/examples/settlements/list-settlements.php @@ -1,4 +1,5 @@ settlements->page(); + $settlements = $mollie->settlements->collect(); echo '
      '; foreach ($settlements as $settlement) { - echo '
    • Settlement ' . htmlspecialchars($settlement->reference) . ': (' . htmlspecialchars($settlement->createdAt) . ')'; + echo '
    • Settlement '.htmlspecialchars($settlement->reference).': ('.htmlspecialchars($settlement->createdAt).')'; echo ''; // Convert from stdClass to array $settlement_periods = json_decode(json_encode($settlement->periods), true); @@ -23,31 +24,31 @@ foreach ($months as $month => $monthly_settlement) { foreach ($monthly_settlement['revenue'] as $revenue) { echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; echo ''; } foreach ($monthly_settlement['costs'] as $revenue) { echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; - echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; + echo ''; echo ''; } } } - echo ''; + echo ''; echo '
      MonthDescriptionCountNetVATGross
      ' . htmlspecialchars($year . '-' . $month) . '' . htmlspecialchars($revenue['description']) . '' . htmlspecialchars($revenue['count']) . ' x' . htmlspecialchars($revenue['amountNet']['value'] ? $revenue['amountNet']['value'] . " " . $revenue['amountNet']['currency'] : '-') . '' . htmlspecialchars($revenue['amountVat']['value'] ? $revenue['amountVat']['value'] . " " . $revenue['amountVat']['currency'] : '-') . '' . htmlspecialchars($revenue['amountGross']['value'] ? $revenue['amountGross']['value'] . " " . $revenue['amountGross']['currency'] : '-') . ''.htmlspecialchars($year.'-'.$month).''.htmlspecialchars($revenue['description']).''.htmlspecialchars($revenue['count']).' x'.htmlspecialchars($revenue['amountNet']['value'] ? $revenue['amountNet']['value'].' '.$revenue['amountNet']['currency'] : '-').''.htmlspecialchars($revenue['amountVat']['value'] ? $revenue['amountVat']['value'].' '.$revenue['amountVat']['currency'] : '-').''.htmlspecialchars($revenue['amountGross']['value'] ? $revenue['amountGross']['value'].' '.$revenue['amountGross']['currency'] : '-').'
      ' . htmlspecialchars($year . '-' . $month) . '' . htmlspecialchars($revenue['description']) . '' . htmlspecialchars($revenue['count']) . ' x' . htmlspecialchars($revenue['amountNet']['value'] ? $revenue['amountNet']['value'] . " " . $revenue['amountNet']['currency'] : '-') . '' . htmlspecialchars($revenue['amountVat']['value'] ? $revenue['amountVat']['value'] . " " . $revenue['amountVat']['currency'] : '-') . '' . htmlspecialchars($revenue['amountGross']['value'] ? $revenue['amountGross']['value'] . " " . $revenue['amountGross']['currency'] : '-') . ''.htmlspecialchars($year.'-'.$month).''.htmlspecialchars($revenue['description']).''.htmlspecialchars($revenue['count']).' x'.htmlspecialchars($revenue['amountNet']['value'] ? $revenue['amountNet']['value'].' '.$revenue['amountNet']['currency'] : '-').''.htmlspecialchars($revenue['amountVat']['value'] ? $revenue['amountVat']['value'].' '.$revenue['amountVat']['currency'] : '-').''.htmlspecialchars($revenue['amountGross']['value'] ? $revenue['amountGross']['value'].' '.$revenue['amountGross']['currency'] : '-').'
      TOTAL' . htmlspecialchars($settlement->amount->value . " " . $settlement->amount->currency) . '
      TOTAL'.htmlspecialchars($settlement->amount->value.' '.$settlement->amount->currency).'
      '; echo '
    • '; } echo '
    '; } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/shipments/create-shipment-all.php b/examples/shipments/create-shipment-all.php deleted file mode 100644 index a1f126b4a..000000000 --- a/examples/shipments/create-shipment-all.php +++ /dev/null @@ -1,27 +0,0 @@ -orders->get('ord_8wmqcHMN4U'); - $shipment = $order->shipAll(); - - echo 'A shipment with ID ' . $shipment->id. ' has been created for your order with ID ' . $order->id . '.'; - foreach ($shipment->lines as $line) { - echo $line->name . ' - status: ' . $line->status . '.'; - } -} catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); -} diff --git a/examples/shipments/create-shipment-partial.php b/examples/shipments/create-shipment-partial.php deleted file mode 100644 index 8c15cf6e1..000000000 --- a/examples/shipments/create-shipment-partial.php +++ /dev/null @@ -1,42 +0,0 @@ -orders->get('ord_8wmqcHMN4U'); - $lineId1 = $order->lines()[0]->id; - $lineId2 = $order->lines()[1]->id; - $shipment = $order->createShipment( - [ - 'lines' => [ - [ - 'id' => $lineId1, - // assume all is shipped if no quantity is specified - ], - [ - 'id' => $lineId2, - 'quantity' => 1, // you can set the quantity if not all is shipped at once - ], - ], - ] - ); - - echo 'A shipment with ID ' . $shipment->id. ' has been created for your order with ID ' . $order->id . '.'; - foreach ($shipment->lines as $line) { - echo $line->name . '- status: ' . $line->status . '.'; - } -} catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); -} diff --git a/examples/shipments/get-shipment.php b/examples/shipments/get-shipment.php deleted file mode 100644 index fbdd21d85..000000000 --- a/examples/shipments/get-shipment.php +++ /dev/null @@ -1,27 +0,0 @@ -orders->get('ord_8wmqcHMN4U'); - $shipment = $order->getShipment("shp_3wmsgCJN4U"); - - echo 'Shipment with ID ' . $shipment->id. ' for order with ID ' . $order->id . '.'; - foreach ($shipment->lines as $line) { - echo $line->name . ' - status: ' . $line->status . '.'; - } -} catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); -} diff --git a/examples/shipments/list-shipments.php b/examples/shipments/list-shipments.php deleted file mode 100644 index 91cc0ff80..000000000 --- a/examples/shipments/list-shipments.php +++ /dev/null @@ -1,30 +0,0 @@ -orders->get('ord_8wmqcHMN4U'); - $shipments = $order->shipments(); - - echo 'Shipments for order with ID ' . $order->id . ':'; - foreach ($shipments as $shipment) { - echo 'Shipment ' . $shipment->id . '. Items:'; - foreach ($shipment->lines as $line) { - echo $line->name . ' - status: ' . $line->status . '.'; - } - } -} catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); -} diff --git a/examples/shipments/update-shipment.php b/examples/shipments/update-shipment.php deleted file mode 100644 index c77913889..000000000 --- a/examples/shipments/update-shipment.php +++ /dev/null @@ -1,40 +0,0 @@ -orders->get('ord_8wmqcHMN4U'); - $shipment = $order->getShipment("shp_3wmsgCJN4U"); - - $shipment->tracking = [ - 'carrier' => 'PostNL', - 'code' => '3SKABA000000000', - 'url' => 'http://postnl.nl/tracktrace/?B=3SKABA000000000&P=1016EE&D=NL&T=C', - ]; - $shipment = $shipment->update(); - - echo 'Shipment with ID ' . $shipment->id. ' for order with ID ' . $order->id . '.'; - echo 'Tracking information updated:'; - echo 'Carrier: ' . $shipment->tracking->carrier; - echo 'Code: ' . $shipment->tracking->code; - echo 'Url: ' . $shipment->tracking->url; - - foreach ($shipment->lines as $line) { - echo $line->name . ' - status: ' . $line->status . '.'; - } -} catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); -} diff --git a/examples/subscriptions/cancel-subscription.php b/examples/subscriptions/cancel-subscription.php index 0ef515256..872ee02e5 100644 --- a/examples/subscriptions/cancel-subscription.php +++ b/examples/subscriptions/cancel-subscription.php @@ -1,4 +1,5 @@ customers->page(null, 1)[0]; + $customer = $mollie->customers->collect(null, 1)[0]; /* * The subscription ID, starting with sub_ @@ -30,7 +31,7 @@ /* * The subscription status should now be canceled */ - echo "

    The subscription status is now: '" . htmlspecialchars($canceledSubscription->status) . "'.

    \n"; + echo "

    The subscription status is now: '".htmlspecialchars($canceledSubscription->status)."'.

    \n"; } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/subscriptions/create-subscription.php b/examples/subscriptions/create-subscription.php index 83ac4e886..150fa7c33 100644 --- a/examples/subscriptions/create-subscription.php +++ b/examples/subscriptions/create-subscription.php @@ -1,4 +1,5 @@ customers->page(null, 1)[0]; + $customer = $mollie->customers->collect(null, 1)[0]; /* * Generate a unique subscription id for this example. It is important to include this unique attribute @@ -34,16 +35,16 @@ * @See: https://docs.mollie.com/reference/v2/subscriptions-api/create-subscription */ $subscription = $customer->createSubscription([ - "amount" => [ - "value" => "10.00", // You must send the correct number of decimals, thus we enforce the use of strings - "currency" => "EUR", + 'amount' => [ + 'value' => '10.00', // You must send the correct number of decimals, thus we enforce the use of strings + 'currency' => 'EUR', ], - "times" => 12, - "interval" => "1 month", - "description" => "Subscription #{$subscriptionId}", - "webhookUrl" => "{$protocol}://{$hostname}{$path}/webhook.php", - "metadata" => [ - "subscription_id" => $subscriptionId, + 'times' => 12, + 'interval' => '1 month', + 'description' => "Subscription #{$subscriptionId}", + 'webhookUrl' => "{$protocol}://{$hostname}{$path}/webhook.php", + 'metadata' => [ + 'subscription_id' => $subscriptionId, ], ]); @@ -52,10 +53,10 @@ * a pending or valid mandate. If the customer has no mandates an error is returned. You * should then set up a "first payment" for the customer. */ - echo "

    The subscription status is '" . htmlspecialchars($subscription->status) . "'.

    \n"; - echo "

    "; - echo '18-cancel-subscription
    '; - echo "

    "; + echo "

    The subscription status is '".htmlspecialchars($subscription->status)."'.

    \n"; + echo '

    '; + echo '18-cancel-subscription
    '; + echo '

    '; } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/examples/subscriptions/update-subscription.php b/examples/subscriptions/update-subscription.php index 6efd54b58..a7b3fdabf 100644 --- a/examples/subscriptions/update-subscription.php +++ b/examples/subscriptions/update-subscription.php @@ -1,4 +1,5 @@ customers->get("cst_cUe8HjeBuz"); - $subscription = $customer->getSubscription("sub_DRjwaT5qHx"); + $customer = $mollie->customers->get('cst_cUe8HjeBuz'); + $subscription = $customer->getSubscription('sub_DRjwaT5qHx'); /** * Subscription fields that can be updated are described by the link: @@ -20,12 +21,12 @@ */ $subscription->times = 10; $subscription->startDate = '2018-12-02'; // Year-month-day - $subscription->amount = (object)['value' => '12.12', 'currency' => 'EUR']; + $subscription->amount = (object) ['value' => '12.12', 'currency' => 'EUR']; $subscription->webhookUrl = 'https://some-webhook-url.com/with/path'; $subscription->description = 'Monthly subscription'; $subscription->update(); - echo "

    Subscription updated: " . $subscription->id . "

    "; + echo '

    Subscription updated: '.$subscription->id.'

    '; } catch (\Mollie\Api\Exceptions\ApiException $e) { - echo "API call failed: " . htmlspecialchars($e->getMessage()); + echo 'API call failed: '.htmlspecialchars($e->getMessage()); } diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index a8db7218f..3147f0c35 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,291 +1,409 @@ parameters: ignoreErrors: - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 path: examples/captures/create-capture.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 path: examples/captures/get-capture.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 path: examples/captures/list-captures.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 path: examples/client-links/create-client-link.php - - message: "#^Variable \\$mollie might not be defined\\.$#" - count: 1 + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined + count: 2 path: examples/customers/create-customer-first-payment.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 path: examples/customers/create-customer-payment.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 path: examples/customers/create-customer-recurring-payment.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 path: examples/customers/create-customer.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 path: examples/customers/delete-customer.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 path: examples/customers/list-customer-payments.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 path: examples/customers/update-customer.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 path: examples/invoices/list-invoices.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 path: examples/mandates/create-mandate.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 path: examples/mandates/list-mandates.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 path: examples/mandates/revoke-mandate.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined + count: 2 + path: examples/pagination/backwards.php + + - + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 2 - path: examples/orders/cancel-order-lines.php + path: examples/pagination/basic_usage.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 - path: examples/orders/cancel-order.php + path: examples/payment-links/create-payment-link.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 - path: examples/orders/create-order.php + path: examples/payment-links/list-payment-links.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 - path: examples/orders/list-methods.php + path: examples/payments/create-capturable-payment.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined + count: 2 + path: examples/payments/create-ideal-payment.php + + - + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined + count: 2 + path: examples/payments/create-payment-oauth.php + + - + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 - path: examples/orders/list-orders.php + path: examples/payments/create-payment.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 - path: examples/orders/refund-order-completely.php + path: examples/payments/list-methods.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 - path: examples/orders/refund-order-partially.php + path: examples/payments/list-payments.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 - path: examples/orders/update-order-line.php + path: examples/payments/refund-payment.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 - path: examples/orders/update-order-lines-multiple.php + path: examples/payments/return.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 - path: examples/orders/update-order.php + path: examples/payments/update-payment.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 - path: examples/orders/webhook.php + path: examples/payments/webhook.php - - message: "#^Variable \\$mollie might not be defined\\.$#" - count: 2 - path: examples/pagination/backwards.php + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: examples/profiles/create-profile.php - - message: "#^Variable \\$mollie might not be defined\\.$#" - count: 2 - path: examples/pagination/basic_usage.php + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: examples/profiles/delete-profile.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 - path: examples/payment-links/create-payment-link.php + path: examples/profiles/list-profiles.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 - path: examples/payment-links/list-payment-links.php + path: examples/profiles/update-profile.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 - path: examples/payments/create-capturable-payment.php + path: examples/sales-invoices/create-sales-invoice.php - - message: "#^Variable \\$mollie might not be defined\\.$#" - count: 2 - path: examples/payments/create-ideal-payment.php + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: examples/sales-invoices/delete-sales-invoice.php - - message: "#^Variable \\$mollie might not be defined\\.$#" - count: 2 - path: examples/payments/create-payment-oauth.php + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: examples/sales-invoices/list-sales-invoices.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 - path: examples/payments/create-payment.php + path: examples/sales-invoices/update-sales-invoice.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 - path: examples/payments/list-methods.php + path: examples/sessions/cancel-session.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 - path: examples/payments/list-payments.php + path: examples/sessions/create-session.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 - path: examples/payments/refund-payment.php + path: examples/sessions/list-sessions.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 - path: examples/payments/return.php + path: examples/sessions/update-session.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 - path: examples/payments/update-payment.php + path: examples/settlements/list-settlements.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 - path: examples/payments/webhook.php + path: examples/subscriptions/cancel-subscription.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 - path: examples/profiles/create-profile.php + path: examples/subscriptions/create-subscription.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Variable \$mollie might not be defined\.$#' + identifier: variable.undefined count: 1 - path: examples/profiles/delete-profile.php + path: examples/subscriptions/update-subscription.php + + - + message: '#^Unsafe access to private property Mollie\\Api\\Fake\\MockMollieHttpAdapter\:\:\$factories through static\:\:\.$#' + identifier: staticClassAccess.privateProperty + count: 3 + path: src/Fake/MockMollieHttpAdapter.php + + - + message: '#^Unsafe access to private property Mollie\\Api\\Fake\\MockResponse\:\:\$factories through static\:\:\.$#' + identifier: staticClassAccess.privateProperty + count: 3 + path: src/Fake/MockResponse.php + + - + message: '#^Unsafe usage of new static\(\)\.$#' + identifier: new.static + count: 4 + path: src/Http/Data/DataCollection.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertTrue\(\) with true will always evaluate to true\.$#' + identifier: method.alreadyNarrowedType count: 1 - path: examples/profiles/list-profiles.php + path: tests/EndpointCollection/CustomerEndpointCollectionTest.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertTrue\(\) with true will always evaluate to true\.$#' + identifier: method.alreadyNarrowedType count: 1 - path: examples/profiles/update-profile.php + path: tests/EndpointCollection/MandateEndpointCollectionTest.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Access to an undefined property Mollie\\Api\\Resources\\Issuer\:\:\$_links\.$#' + identifier: property.notFound count: 1 - path: examples/sessions/cancel-session.php + path: tests/EndpointCollection/MethodIssuerEndpointCollectionTest.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Access to an undefined property Mollie\\Api\\Resources\\Issuer\:\:\$description\.$#' + identifier: property.notFound count: 1 - path: examples/sessions/create-session.php + path: tests/EndpointCollection/MethodIssuerEndpointCollectionTest.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Access to an undefined property Mollie\\Api\\Resources\\Issuer\:\:\$status\.$#' + identifier: property.notFound count: 1 - path: examples/sessions/list-sessions.php + path: tests/EndpointCollection/MethodIssuerEndpointCollectionTest.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertTrue\(\) with true will always evaluate to true\.$#' + identifier: method.alreadyNarrowedType count: 1 - path: examples/sessions/update-session.php + path: tests/EndpointCollection/MethodIssuerEndpointCollectionTest.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertTrue\(\) with true will always evaluate to true\.$#' + identifier: method.alreadyNarrowedType count: 1 - path: examples/settlements/list-settlements.php + path: tests/EndpointCollection/PaymentLinkEndpointCollectionTest.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertTrue\(\) with true will always evaluate to true\.$#' + identifier: method.alreadyNarrowedType count: 1 - path: examples/shipments/create-shipment-all.php + path: tests/EndpointCollection/PaymentRefundEndpointCollectionTest.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertTrue\(\) with true will always evaluate to true\.$#' + identifier: method.alreadyNarrowedType count: 1 - path: examples/shipments/create-shipment-partial.php + path: tests/EndpointCollection/ProfileEndpointCollectionTest.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertTrue\(\) with true will always evaluate to true\.$#' + identifier: method.alreadyNarrowedType + count: 2 + path: tests/EndpointCollection/ProfileMethodEndpointCollectionTest.php + + - + message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertTrue\(\) with true will always evaluate to true\.$#' + identifier: method.alreadyNarrowedType count: 1 - path: examples/shipments/get-shipment.php + path: tests/EndpointCollection/SalesInvoiceEndpointCollectionTest.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertTrue\(\) with true will always evaluate to true\.$#' + identifier: method.alreadyNarrowedType count: 1 - path: examples/shipments/list-shipments.php + path: tests/EndpointCollection/SessionEndpointCollectionTest.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertTrue\(\) with true will always evaluate to true\.$#' + identifier: method.alreadyNarrowedType count: 1 - path: examples/shipments/update-shipment.php + path: tests/EndpointCollection/SubscriptionEndpointCollectionTest.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Call to method PHPUnit\\Framework\\Assert\:\:assertTrue\(\) with true will always evaluate to true\.$#' + identifier: method.alreadyNarrowedType count: 1 - path: examples/subscriptions/cancel-subscription.php + path: tests/Http/Middleware/GuardResponseTest.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Access to an undefined property Mollie\\Api\\Resources\\AnyResource\:\:\$customField\.$#' + identifier: property.notFound count: 1 - path: examples/subscriptions/create-subscription.php + path: tests/Resources/ResourceFactoryTest.php - - message: "#^Variable \\$mollie might not be defined\\.$#" + message: '#^Access to an undefined property Mollie\\Api\\Resources\\AnyResource\:\:\$id\.$#' + identifier: property.notFound count: 1 - path: examples/subscriptions/update-subscription.php + path: tests/Resources/ResourceFactoryTest.php + + - + message: '#^Property Tests\\Utils\\TestPropertiesClass\:\:\$privateProp is unused\.$#' + identifier: property.unused + count: 1 + path: tests/Utils/UtilityTest.php + + - + message: '#^Trait Tests\\Utils\\TestTraitBase is used zero times and is not analysed\.$#' + identifier: trait.unused + count: 1 + path: tests/Utils/UtilityTest.php + + - + message: '#^Trait Tests\\Utils\\TestTraitMain is used zero times and is not analysed\.$#' + identifier: trait.unused + count: 1 + path: tests/Utils/UtilityTest.php - - message: "#^Result of method Mollie\\\\Api\\\\Endpoints\\\\PaymentLinkEndpoint\\:\\:delete\\(\\) \\(void\\) is used\\.$#" + message: '#^Trait Tests\\Utils\\TestTraitNested is used zero times and is not analysed\.$#' + identifier: trait.unused count: 1 - path: tests/Mollie/API/Endpoints/PaymentLinkEndpointTest.php \ No newline at end of file + path: tests/Utils/UtilityTest.php diff --git a/phpstan.neon b/phpstan.neon index ecd56da76..5d1ecaba6 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -6,12 +6,6 @@ parameters: - %currentWorkingDirectory%/examples excludePaths: - %currentWorkingDirectory%/vendor - ignoreErrors: - - '#Access to an undefined property Eloquent\\Liberator\\LiberatorProxyInterface::\$request#' - - '#Access to protected property Mollie\\Api\\MollieApiClient::\$apiKey#' - - '#Access to protected property Mollie\\Api\\MollieApiClient::\$httpClient#' - - '#Call to an undefined method Mollie\\Api\\HttpAdapter\\MollieHttpAdapterInterface::enableDebugging\(\)#' - - '#Call to an undefined method Mollie\\Api\\HttpAdapter\\MollieHttpAdapterInterface::disableDebugging\(\)#' treatPhpDocTypesAsCertain: false includes: - phpstan-baseline.neon diff --git a/scoper.inc.php b/scoper.inc.php deleted file mode 100644 index 88317a713..000000000 --- a/scoper.inc.php +++ /dev/null @@ -1,13 +0,0 @@ - [], // Finder[] - 'patchers' => [], // callable[] - 'whitelist' => [ - 'Mollie\\Api\\*', - ], -]; \ No newline at end of file diff --git a/src/CompatibilityChecker.php b/src/CompatibilityChecker.php index b754b2116..fc07f16b4 100644 --- a/src/CompatibilityChecker.php +++ b/src/CompatibilityChecker.php @@ -9,17 +9,23 @@ class CompatibilityChecker /** * @var string */ - public const MIN_PHP_VERSION = "7.2"; + public const MIN_PHP_VERSION = '7.4'; + + public static function make(): self + { + return new self; + } /** - * @throws IncompatiblePlatform * @return void + * + * @throws IncompatiblePlatform */ public function checkCompatibility() { if (! $this->satisfiesPhpVersion()) { throw new IncompatiblePlatform( - "The client requires PHP version >= " . self::MIN_PHP_VERSION . ", you have " . PHP_VERSION . ".", + 'The client requires PHP version >= '.self::MIN_PHP_VERSION.', you have '.PHP_VERSION.'.', IncompatiblePlatform::INCOMPATIBLE_PHP_VERSION ); } @@ -34,15 +40,17 @@ public function checkCompatibility() /** * @return bool + * * @codeCoverageIgnore */ public function satisfiesPhpVersion() { - return (bool)version_compare(PHP_VERSION, self::MIN_PHP_VERSION, ">="); + return (bool) version_compare(PHP_VERSION, self::MIN_PHP_VERSION, '>='); } /** * @return bool + * * @codeCoverageIgnore */ public function satisfiesJsonExtension() diff --git a/src/Contracts/ArrayRepository.php b/src/Contracts/ArrayRepository.php new file mode 100644 index 000000000..f330c4661 --- /dev/null +++ b/src/Contracts/ArrayRepository.php @@ -0,0 +1,26 @@ +send((new GetBalanceRequest($id))->test($testmode)); + } + + /** + * Retrieve the primary balance from Mollie. + * + * Will throw an ApiException if the balance id is invalid or the resource cannot be found. + * + * @throws ApiException + */ + public function primary(array $testmode = []): Balance + { + /** @var Balance */ + return $this->get('primary', $testmode); + } + + /** + * Get the balance endpoint. + */ + public function page(?string $from = null, ?int $limit = null, array $filters = []): BalanceCollection + { + $testmode = Utility::extractBool($filters, 'testmode', false); + + $query = GetPaginatedBalanceQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + return $this->send((new GetPaginatedBalanceRequest($query))->test($testmode)); + } + + /** + * Create an iterator for iterating over balances retrieved from Mollie. + * + * @param string $from The first Balance ID you want to include in your list. + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iterator(?string $from = null, ?int $limit = null, array $filters = [], bool $iterateBackwards = false): LazyCollection + { + $testmode = Utility::extractBool($filters, 'testmode', false); + + $query = GetPaginatedBalanceQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + return $this->send( + (new GetPaginatedBalanceRequest($query)) + ->useIterator() + ->setIterationDirection($iterateBackwards) + ->test($testmode) + ); + } +} diff --git a/src/EndpointCollection/BalanceReportEndpointCollection.php b/src/EndpointCollection/BalanceReportEndpointCollection.php new file mode 100644 index 000000000..7abe127e6 --- /dev/null +++ b/src/EndpointCollection/BalanceReportEndpointCollection.php @@ -0,0 +1,54 @@ +create(); + + /** @var BalanceReport */ + return $this->send((new GetBalanceReportRequest($balanceId, $query))->test($testmode)); + } + + /** + * Retrieve the primary balance. + * This is the balance of your account’s primary currency, where all payments are settled to by default. + * + * @param array|GetBalanceReportQuery $query + * + * @throws \Mollie\Api\Exceptions\ApiException + */ + public function getForPrimary($query = []): BalanceReport + { + return $this->getForId('primary', $query); + } + + /** + * Retrieve a balance report for the provided balance resource and parameters. + * + * @throws \Mollie\Api\Exceptions\ApiException + */ + public function getFor(Balance $balance, array $parameters = []): BalanceReport + { + return $this->getForId($balance->id, $parameters); + } +} diff --git a/src/EndpointCollection/BalanceTransactionEndpointCollection.php b/src/EndpointCollection/BalanceTransactionEndpointCollection.php new file mode 100644 index 000000000..bb6ff863e --- /dev/null +++ b/src/EndpointCollection/BalanceTransactionEndpointCollection.php @@ -0,0 +1,100 @@ +pageForId($balance->id, $query, $testmode); + } + + /** + * Create an iterator for iterating over balance transactions for the given balance retrieved from Mollie. + * + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iteratorFor(Balance $balance, array $parameters = [], bool $iterateBackwards = false, bool $testmode = false): LazyCollection + { + return $this->iteratorForId($balance->id, $parameters, $iterateBackwards, $testmode); + } + + /** + * List the transactions for the primary Balance. + * + * @param array|PaginatedQuery $query + * + * @throws \Mollie\Api\Exceptions\ApiException + */ + public function pageForPrimary($query = [], bool $testmode = false): BalanceTransactionCollection + { + /** @var BalanceTransactionCollection */ + return $this->pageForId('primary', $query, $testmode); + } + + /** + * Create an iterator for iterating over transactions for the primary balance retrieved from Mollie. + * + * @param array|PaginatedQuery $query + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iteratorForPrimary($query = [], bool $iterateBackwards = false, ?bool $testmode = null): LazyCollection + { + return $this->iteratorForId('primary', $query, $iterateBackwards); + } + + /** + * List the transactions for a specific Balance ID. + * + * @param array|PaginatedQuery $query + * + * @throws \Mollie\Api\Exceptions\ApiException + */ + public function pageForId(string $balanceId, $query = [], bool $testmode = false): BalanceTransactionCollection + { + if (! $query instanceof PaginatedQuery) { + $query = PaginatedQueryFactory::new($query) + ->create(); + } + + /** @var BalanceTransactionCollection */ + return $this->send((new GetPaginatedBalanceTransactionRequest($balanceId, $query))->test($testmode)); + } + + /** + * Create an iterator for iterating over balance transactions for the given balance id retrieved from Mollie. + * + * @param array|PaginatedQuery $query + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iteratorForId(string $balanceId, $query = [], bool $iterateBackwards = false, bool $testmode = false): LazyCollection + { + if (! $query instanceof PaginatedQuery) { + $query = PaginatedQueryFactory::new($query) + ->create(); + } + + return $this->send( + (new GetPaginatedBalanceTransactionRequest($balanceId, $query)) + ->useIterator() + ->setIterationDirection($iterateBackwards) + ->test($testmode) + ); + } +} diff --git a/src/EndpointCollection/ChargebackEndpointCollection.php b/src/EndpointCollection/ChargebackEndpointCollection.php new file mode 100644 index 000000000..4db3798bd --- /dev/null +++ b/src/EndpointCollection/ChargebackEndpointCollection.php @@ -0,0 +1,59 @@ + $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + /** @var ChargebackCollection */ + return $this->send((new GetPaginatedChargebacksRequest($query))->test($testmode)); + } + + /** + * Create an iterator for iterating over chargeback retrieved from Mollie. + * + * @param string $from The first chargevback ID you want to include in your list. + * @param array $filters + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iterator(?string $from = null, ?int $limit = null, $filters = [], bool $iterateBackwards = false): LazyCollection + { + $testmode = Utility::extractBool($filters, 'testmode', false); + + $query = GetPaginatedChargebackQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + return $this->send( + (new GetPaginatedChargebacksRequest($query)) + ->useIterator() + ->setIterationDirection($iterateBackwards) + ->test($testmode) + ); + } +} diff --git a/src/EndpointCollection/ClientEndpointCollection.php b/src/EndpointCollection/ClientEndpointCollection.php new file mode 100644 index 000000000..6664e4b1f --- /dev/null +++ b/src/EndpointCollection/ClientEndpointCollection.php @@ -0,0 +1,77 @@ +create(); + } + + /** @var Client */ + return $this->send(new GetClientRequest($id, $query)); + } + + /** + * Retrieves a page of clients from Mollie. + * + * @param string $from The first client ID you want to include in your list. + * + * @throws ApiException + */ + public function page(?string $from = null, ?int $limit = null, array $filters = []): ClientCollection + { + $query = GetPaginatedClientQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + /** @var ClientCollection */ + return $this->send(new GetPaginatedClientRequest($query)); + } + + /** + * Create an iterator for iterating over clients retrieved from Mollie. + * + * @param string $from The first client ID you want to include in your list. + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iterator(?string $from = null, ?int $limit = null, array $filters = [], bool $iterateBackwards = false): LazyCollection + { + $query = GetPaginatedClientQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + return $this->send( + (new GetPaginatedClientRequest($query)) + ->useIterator() + ->setIterationDirection($iterateBackwards) + ); + } +} diff --git a/src/EndpointCollection/ClientLinkEndpointCollection.php b/src/EndpointCollection/ClientLinkEndpointCollection.php new file mode 100644 index 000000000..389f45a60 --- /dev/null +++ b/src/EndpointCollection/ClientLinkEndpointCollection.php @@ -0,0 +1,30 @@ +create(); + } + + /** @var ClientLink */ + return $this->send(new CreateClientLinkRequest($payload)); + } +} diff --git a/src/EndpointCollection/CustomerEndpointCollection.php b/src/EndpointCollection/CustomerEndpointCollection.php new file mode 100644 index 000000000..cb6168f8b --- /dev/null +++ b/src/EndpointCollection/CustomerEndpointCollection.php @@ -0,0 +1,138 @@ +create(); + } + + /** @var Customer */ + return $this->send((new CreateCustomerRequest($data))->test($testmode)); + } + + /** + * Retrieve a single customer from Mollie. + * + * Will throw a ApiException if the customer id is invalid or the resource cannot be found. + * + * @param bool|array $testmode + * + * @throws ApiException + */ + public function get(string $id, $testmode = []): Customer + { + $testmode = Utility::extractBool($testmode, 'testmode', false); + + /** @var Customer */ + return $this->send((new GetCustomerRequest($id))->test($testmode)); + } + + /** + * Update a specific Customer resource. + * + * Will throw an ApiException if the customer id is invalid or the resource cannot be found. + * + * @throws ApiException + */ + public function update(string $id, $data = []): ?Customer + { + if (! $data instanceof UpdateCustomerPayload) { + $data = UpdateCustomerPayloadFactory::new($data)->create(); + } + + /** @var null|Customer */ + return $this->send(new UpdateCustomerRequest($id, $data)); + } + + /** + * Deletes the given Customer. + * + * Will throw a ApiException if the customer id is invalid or the resource cannot be found. + * Returns with HTTP status No Content (204) if successful. + * + * @param bool|array $testmode + * + * @throws ApiException + */ + public function delete(string $id, $testmode = []): void + { + $testmode = Utility::extractBool($testmode, 'testmode', false); + + $this->send((new DeleteCustomerRequest($id))->test($testmode)); + } + + /** + * Retrieves a collection of Customers from Mollie. + * + * @param string $from The first customer ID you want to include in your list. + * + * @throws ApiException + */ + public function page(?string $from = null, ?int $limit = null, array $filters = []): CustomerCollection + { + $testmode = Utility::extractBool($filters, 'testmode', false); + + $query = PaginatedQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + /** @var CustomerCollection */ + return $this->send((new GetPaginatedCustomerRequest($query))->test($testmode)); + } + + /** + * Create an iterator for iterating over customers retrieved from Mollie. + * + * @param string $from The first customer ID you want to include in your list. + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iterator(?string $from = null, ?int $limit = null, array $filters = [], bool $iterateBackwards = false): LazyCollection + { + $testmode = Utility::extractBool($filters, 'testmode', false); + + $query = PaginatedQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + return $this->send( + (new GetPaginatedCustomerRequest($query)) + ->useIterator() + ->setIterationDirection($iterateBackwards) + ->test($testmode) + ); + } +} diff --git a/src/EndpointCollection/CustomerPaymentsEndpointCollection.php b/src/EndpointCollection/CustomerPaymentsEndpointCollection.php new file mode 100644 index 000000000..a602c29eb --- /dev/null +++ b/src/EndpointCollection/CustomerPaymentsEndpointCollection.php @@ -0,0 +1,132 @@ +createForId($customer->id, $payload, $query, $testmode); + } + + /** + * Create a subscription for a Customer ID + * + * @param string $customerId + * @param array|CreatePaymentPayload $payload + * @param array|CreatePaymentQuery $query + * + * @throws ApiException + */ + public function createForId($customerId, $payload = [], $query = [], bool $testmode = false): Payment + { + if (! $payload instanceof CreatePaymentPayload) { + $testmode = Utility::extractBool($payload, 'testmode', $testmode); + $payload = CreatePaymentPayloadFactory::new($payload) + ->create(); + } + + if (! $query instanceof CreatePaymentQuery) { + $query = CreatePaymentQuery::fromArray(Arr::wrap($query)); + } + + /** @var Payment */ + return $this->send((new CreateCustomerPaymentRequest($customerId, $payload, $query))->test($testmode)); + } + + /** + * @param string $from The first resource ID you want to include in your list. + * + * @throws ApiException + */ + public function pageFor(Customer $customer, ?string $from = null, ?int $limit = null, array $filters = []): PaymentCollection + { + return $this->pageForId($customer->id, $from, $limit, $filters); + } + + /** + * @param string $from The first resource ID you want to include in your list. + * + * @throws ApiException + */ + public function pageForId(string $customerId, ?string $from = null, ?int $limit = null, array $filters = []): PaymentCollection + { + $testmode = Utility::extractBool($filters, 'testmode', false); + $query = GetPaginatedCustomerPaymentsQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + return $this->send((new GetPaginatedCustomerPaymentsRequest( + $customerId, + $query + ))->test($testmode)); + } + + /** + * Create an iterator for iterating over payments for the given customer, retrieved from Mollie. + * + * @param string $from The first resource ID you want to include in your list. + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iteratorFor( + Customer $customer, + ?string $from = null, + ?int $limit = null, + array $parameters = [], + bool $iterateBackwards = false + ): LazyCollection { + return $this->iteratorForId($customer->id, $from, $limit, $parameters, $iterateBackwards); + } + + /** + * Create an iterator for iterating over payments for the given customer id, retrieved from Mollie. + * + * @param string $from The first resource ID you want to include in your list. + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iteratorForId( + string $customerId, + ?string $from = null, + ?int $limit = null, + array $filters = [], + bool $iterateBackwards = false + ): LazyCollection { + $testmode = Utility::extractBool($filters, 'testmode', false); + $query = GetPaginatedCustomerPaymentsQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + return $this->send( + (new GetPaginatedCustomerPaymentsRequest($customerId, $query)) + ->useIterator() + ->setIterationDirection($iterateBackwards) + ->test($testmode) + ); + } +} diff --git a/src/EndpointCollection/EndpointCollection.php b/src/EndpointCollection/EndpointCollection.php new file mode 100644 index 000000000..1fd7ab8e7 --- /dev/null +++ b/src/EndpointCollection/EndpointCollection.php @@ -0,0 +1,24 @@ +connector = $connector; + } + + /** + * @return mixed + */ + protected function send(Request $request) + { + return $this->connector->send($request); + } +} diff --git a/src/EndpointCollection/InvoiceEndpointCollection.php b/src/EndpointCollection/InvoiceEndpointCollection.php new file mode 100644 index 000000000..b20cb61ae --- /dev/null +++ b/src/EndpointCollection/InvoiceEndpointCollection.php @@ -0,0 +1,68 @@ +send(new GetInvoiceRequest($invoiceId)); + } + + /** + * Retrieves a collection of Invoices from Mollie. + * + * @param string|null $from The first invoice ID you want to include in your list. + * + * @throws ApiException + */ + public function page(?string $from = null, ?int $limit = null, array $filters = []): InvoiceCollection + { + $query = GetPaginatedInvoiceQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + /** @var InvoiceCollection */ + return $this->send(new GetPaginatedInvoiceRequest($query)); + } + + /** + * Create an iterator for iterating over invoices retrieved from Mollie. + * + * @param string|null $from The first invoice ID you want to include in your list. + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iterator(?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection + { + $query = PaginatedQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $parameters, + ])->create(); + + return $this->send( + (new GetPaginatedInvoiceRequest($query)) + ->useIterator() + ->setIterationDirection($iterateBackwards) + ); + } +} diff --git a/src/EndpointCollection/MandateEndpointCollection.php b/src/EndpointCollection/MandateEndpointCollection.php new file mode 100644 index 000000000..89572be6f --- /dev/null +++ b/src/EndpointCollection/MandateEndpointCollection.php @@ -0,0 +1,177 @@ +createForId($customer->id, $payload, $testmode); + } + + /** + * Creates a mandate for a specific customer ID. + * + * @param array $payload + * + * @throws ApiException + */ + public function createForId(string $customerId, $payload = [], bool $testmode = false): Mandate + { + if (! $payload instanceof CreateMandatePayload) { + $testmode = Utility::extractBool($payload, 'testmode', $testmode); + $payload = CreateMandatePayloadFactory::new($payload)->create(); + } + + /** @var Mandate */ + return $this->send((new CreateMandateRequest($customerId, $payload))->test($testmode)); + } + + /** + * Retrieve a specific mandate for a customer. + * + * + * @throws ApiException + */ + public function getFor(Customer $customer, string $mandateId, array $parameters = []): Mandate + { + return $this->getForId($customer->id, $mandateId, $parameters); + } + + /** + * Retrieve a specific mandate for a customer ID. + * + * @param array $testmode + * + * @throws ApiException + */ + public function getForId(string $customerId, string $mandateId, $testmode = []): Mandate + { + $testmode = Utility::extractBool($testmode, 'testmode', false); + + /** @var Mandate */ + return $this->send((new GetMandateRequest($customerId, $mandateId))->test($testmode)); + } + + /** + * Revoke a mandate for a specific customer. + * + * + * @throws ApiException + */ + public function revokeFor(Customer $customer, string $mandateId, $data = []): void + { + $this->revokeForId($customer->id, $mandateId, $data); + } + + /** + * Revoke a mandate for a specific customer ID. + * + * @param array|bool $testmode + * + * @throws ApiException + */ + public function revokeForId(string $customerId, string $mandateId, $testmode = []): void + { + $testmode = Utility::extractBool($testmode, 'testmode', false); + + $this->send((new RevokeMandateRequest($customerId, $mandateId))->test($testmode)); + } + + /** + * Retrieves a collection of mandates for the given customer. + * + * @param string $from The first mandate ID you want to include in your list. + * + * @throws ApiException + */ + public function pageFor(Customer $customer, ?string $from = null, ?int $limit = null, array $parameters = []): MandateCollection + { + return $this->pageForId($customer->id, $from, $limit, $parameters); + } + + /** + * Retrieves a collection of mandates for the given customer ID. + * + * @param string $from The first mandate ID you want to include in your list. + * + * @throws ApiException + */ + public function pageForId(string $customerId, ?string $from = null, ?int $limit = null, array $filters = []): MandateCollection + { + $testmode = Utility::extractBool($filters, 'testmode', false); + $query = PaginatedQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + /** @var MandateCollection */ + return $this->send((new GetPaginatedMandateRequest($customerId, $query))->test($testmode)); + } + + /** + * Create an iterator for iterating over mandates for the given customer. + * + * @param string $from The first mandate ID you want to include in your list. + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iteratorFor( + Customer $customer, + ?string $from = null, + ?int $limit = null, + array $parameters = [], + bool $iterateBackwards = false + ): LazyCollection { + return $this->iteratorForId($customer->id, $from, $limit, $parameters, $iterateBackwards); + } + + /** + * Create an iterator for iterating over mandates for the given customer ID. + * + * @param string $from The first mandate ID you want to include in your list. + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iteratorForId( + string $customerId, + ?string $from = null, + ?int $limit = null, + array $filters = [], + bool $iterateBackwards = false + ): LazyCollection { + $testmode = Utility::extractBool($filters, 'testmode', false); + $query = PaginatedQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + return $this->send( + (new GetPaginatedMandateRequest($customerId, $query)) + ->useIterator() + ->setIterationDirection($iterateBackwards) + ->test($testmode) + ); + } +} diff --git a/src/EndpointCollection/MethodEndpointCollection.php b/src/EndpointCollection/MethodEndpointCollection.php new file mode 100644 index 000000000..41fb5de7d --- /dev/null +++ b/src/EndpointCollection/MethodEndpointCollection.php @@ -0,0 +1,87 @@ +create(); + } + + /** @var MethodCollection */ + return $this->send(new GetAllPaymentMethodsRequest($query)); + } + + /** + * Retrieve all enabled methods for the organization. + * In test mode, this includes pending methods. + * The results are not paginated. + * + * @throws ApiException + */ + public function allEnabled($query = [], bool $testmode = false): MethodCollection + { + if (! $query instanceof GetEnabledPaymentMethodsQuery) { + $testmode = Utility::extractBool($query, 'testmode', $testmode); + $query = GetEnabledPaymentMethodsQueryFactory::new($query) + ->create(); + } + + /** @var MethodCollection */ + return $this->send((new GetEnabledPaymentMethodsRequest($query))->test($testmode)); + } + + /** + * @deprecated Use allEnabled() instead + * + * @throws ApiException + */ + public function allActive($query = [], ?bool $testmode = null): MethodCollection + { + return $this->allEnabled($query, $testmode); + } + + /** + * Retrieve a payment method from Mollie. + * + * Will throw an ApiException if the method id is invalid or the resource cannot be found. + * + * @throws ApiException + */ + public function get(string $methodId, $query = [], bool $testmode = false): Method + { + if (! $query instanceof GetPaymentMethodQuery) { + $testmode = Utility::extractBool($query, 'testmode', $testmode); + $query = GetPaymentMethodQueryFactory::new($query) + ->create(); + } + + /** @var Method */ + return $this->send((new GetPaymentMethodRequest($methodId, $query))->test($testmode)); + } +} diff --git a/src/EndpointCollection/MethodIssuerEndpointCollection.php b/src/EndpointCollection/MethodIssuerEndpointCollection.php new file mode 100644 index 000000000..ee28f3bde --- /dev/null +++ b/src/EndpointCollection/MethodIssuerEndpointCollection.php @@ -0,0 +1,31 @@ +send(new EnableMethodIssuerRequest($profileId, $methodId, $issuerId, $contractId)); + } + + /** + * Disable an issuer for a specific payment method. + * + * @throws ApiException + */ + public function disable(string $profileId, string $methodId, string $issuerId): void + { + $this->send(new DisableMethodIssuerRequest($profileId, $methodId, $issuerId)); + } +} diff --git a/src/EndpointCollection/OnboardingEndpointCollection.php b/src/EndpointCollection/OnboardingEndpointCollection.php new file mode 100644 index 000000000..eabee6cd3 --- /dev/null +++ b/src/EndpointCollection/OnboardingEndpointCollection.php @@ -0,0 +1,14 @@ +send(new GetOnboardingStatusRequest); + } +} diff --git a/src/EndpointCollection/OrganizationEndpointCollection.php b/src/EndpointCollection/OrganizationEndpointCollection.php new file mode 100644 index 000000000..28432b713 --- /dev/null +++ b/src/EndpointCollection/OrganizationEndpointCollection.php @@ -0,0 +1,53 @@ +send((new GetOrganizationRequest($id))->test($testmode)); + } + + /** + * Retrieve the current organization from Mollie. + * + * @param array|bool $testmode + * + * @throws ApiException + */ + public function current($testmode = []): Organization + { + /** @var Organization */ + return $this->get('me', $testmode); + } + + /** + * Retrieve the partner status of the current organization. + * + * @throws ApiException + */ + public function partnerStatus(): Partner + { + return $this->send(new GetOrganizationPartnerStatusRequest); + } +} diff --git a/src/EndpointCollection/OrganizationPartnerEndpointCollection.php b/src/EndpointCollection/OrganizationPartnerEndpointCollection.php new file mode 100644 index 000000000..8d3ae173e --- /dev/null +++ b/src/EndpointCollection/OrganizationPartnerEndpointCollection.php @@ -0,0 +1,17 @@ +send(new GetOrganizationPartnerStatusRequest); + } +} diff --git a/src/EndpointCollection/PaymentCaptureEndpointCollection.php b/src/EndpointCollection/PaymentCaptureEndpointCollection.php new file mode 100644 index 000000000..613e90d7c --- /dev/null +++ b/src/EndpointCollection/PaymentCaptureEndpointCollection.php @@ -0,0 +1,148 @@ +createForId($payment->id, $payload, $testmode); + } + + /** + * Creates a payment capture in Mollie. + * + * @param array|CreatePaymentCapturePayload $payload An array containing details on the capture. + * + * @throws ApiException + */ + public function createForId(string $paymentId, $payload = [], bool $testmode = false): Capture + { + if (! $payload instanceof CreatePaymentCapturePayload) { + $testmode = Utility::extractBool($payload, 'testmode', $testmode); + $payload = CreatePaymentCapturePayloadFactory::new($payload)->create(); + } + + /** @var Capture */ + return $this->send((new CreatePaymentCaptureRequest($paymentId, $payload))->test($testmode)); + } + + /** + * @param array|GetPaymentCaptureQuery $query + * + * @throws ApiException + */ + public function getFor(Payment $payment, string $captureId, $query = [], ?bool $testmode = null): Capture + { + return $this->getForId($payment->id, $captureId, $query, $testmode); + } + + /** + * @param array|GetPaymentCaptureQuery $query + * + * @throws ApiException + */ + public function getForId(string $paymentId, string $captureId, $query = [], bool $testmode = false): Capture + { + if (! $query instanceof GetPaymentCaptureQuery) { + $testmode = Utility::extractBool($query, 'testmode', $testmode); + $query = GetPaymentCaptureQueryFactory::new($query)->create(); + } + + /** @var Capture */ + return $this->send((new GetPaymentCaptureRequest($paymentId, $captureId, $query))->test($testmode)); + } + + /** + * @param array|GetPaginatedPaymentCapturesQuery $query + * + * @throws ApiException + */ + public function pageFor(Payment $payment, $query = [], ?bool $testmode = null): CaptureCollection + { + return $this->pageForId($payment->id, $query, $testmode); + } + + /** + * @param array|GetPaginatedPaymentCapturesQuery $query + * + * @throws ApiException + */ + public function pageForId(string $paymentId, $query = [], bool $testmode = false): CaptureCollection + { + if (! $query instanceof GetPaginatedPaymentCapturesQuery) { + $testmode = Utility::extractBool($query, 'testmode', $testmode); + $query = GetPaginatedPaymentCapturesQueryFactory::new($query)->create(); + } + + /** @var CaptureCollection */ + return $this->send((new GetPaginatedPaymentCapturesRequest($paymentId, $query))->test($testmode)); + } + + /** + * Create an iterator for iterating over captures for the given payment, retrieved from Mollie. + * + * @param string $from The first resource ID you want to include in your list. + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iteratorFor( + Payment $payment, + ?string $from = null, + ?int $limit = null, + array $parameters = [], + bool $iterateBackwards = false + ): LazyCollection { + return $this->iteratorForId($payment->id, $from, $limit, $parameters, $iterateBackwards); + } + + /** + * Create an iterator for iterating over captures for the given payment id, retrieved from Mollie. + * + * @param string $from The first resource ID you want to include in your list. + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iteratorForId( + string $paymentId, + ?string $from = null, + ?int $limit = null, + array $filters = [], + bool $iterateBackwards = false + ): LazyCollection { + $testmode = Utility::extractBool($filters, 'testmode', false); + $query = GetPaginatedPaymentCapturesQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + return $this->send( + (new GetPaginatedPaymentCapturesRequest($paymentId, $query)) + ->useIterator() + ->setIterationDirection($iterateBackwards) + ->test($testmode) + ); + } +} diff --git a/src/EndpointCollection/PaymentChargebackEndpointCollection.php b/src/EndpointCollection/PaymentChargebackEndpointCollection.php new file mode 100644 index 000000000..fd6bbcd91 --- /dev/null +++ b/src/EndpointCollection/PaymentChargebackEndpointCollection.php @@ -0,0 +1,115 @@ +getForId($payment->id, $chargebackId, $query, $testmode); + } + + /** + * @param array|GetPaymentChargebackQuery $query + * + * @throws ApiException + */ + public function getForId(string $paymentId, string $chargebackId, $query = [], bool $testmode = false): Chargeback + { + if (! $query instanceof GetPaymentChargebackQuery) { + $testmode = Utility::extractBool($query, 'testmode', $testmode); + $query = GetPaymentChargebackQueryFactory::new($query)->create(); + } + + /** @var Chargeback */ + return $this->send((new GetPaymentChargebackRequest($paymentId, $chargebackId, $query))->test($testmode)); + } + + /** + * @param array|GetPaginatedPaymentChargebacksQuery $query + * + * @throws ApiException + */ + public function pageFor(Payment $payment, $query = []): ChargebackCollection + { + return $this->pageForId($payment->id, $query); + } + + /** + * @param array|GetPaginatedPaymentChargebacksQuery $query + * + * @throws ApiException + */ + public function pageForId(string $paymentId, $query = [], bool $testmode = false): ChargebackCollection + { + if (! $query instanceof GetPaginatedPaymentChargebacksQuery) { + $testmode = Utility::extractBool($query, 'testmode', $testmode); + $query = GetPaginatedPaymentChargebacksQueryFactory::new($query)->create(); + } + + /** @var ChargebackCollection */ + return $this->send((new GetPaginatedPaymentChargebacksRequest($paymentId, $query))->test($testmode)); + } + + /** + * Create an iterator for iterating over chargebacks for the given payment, retrieved from Mollie. + * + * @param string $from The first resource ID you want to include in your list. + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iteratorFor( + Payment $payment, + ?string $from = null, + ?int $limit = null, + array $parameters = [], + bool $iterateBackwards = false + ): LazyCollection { + return $this->iteratorForId($payment->id, $from, $limit, $parameters, $iterateBackwards); + } + + /** + * Create an iterator for iterating over chargebacks for the given payment id, retrieved from Mollie. + * + * @param string $from The first resource ID you want to include in your list. + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iteratorForId( + string $paymentId, + ?string $from = null, + ?int $limit = null, + array $filters = [], + bool $iterateBackwards = false + ): LazyCollection { + $testmode = Utility::extractBool($filters, 'testmode', false); + $query = GetPaginatedPaymentChargebacksQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + return $this->send( + (new GetPaginatedPaymentChargebacksRequest($paymentId, $query)) + ->useIterator() + ->setIterationDirection($iterateBackwards) + ->test($testmode) + ); + } +} diff --git a/src/EndpointCollection/PaymentEndpointCollection.php b/src/EndpointCollection/PaymentEndpointCollection.php new file mode 100644 index 000000000..9926833b8 --- /dev/null +++ b/src/EndpointCollection/PaymentEndpointCollection.php @@ -0,0 +1,189 @@ +create(); + } + + return $this->send((new GetPaymentRequest($id, $query))->test($testmode)); + } + + /** + * Creates a payment in Mollie. + * + * @param CreatePaymentPayload|array $payload An array containing details on the payment. + * @param CreatePaymentQuery|array|string $query An array of strings or a single string containing the details to include. + * + * @throws ApiException + */ + public function create($payload = [], $query = [], bool $testmode = false): Payment + { + if (! $payload instanceof CreatePaymentPayload) { + $testmode = Utility::extractBool($payload, 'testmode', $testmode); + $payload = CreatePaymentPayloadFactory::new($payload) + ->create(); + } + + if (! $query instanceof CreatePaymentQuery) { + $query = CreatePaymentQuery::fromArray(Arr::wrap($query)); + } + + /** @var Payment */ + return $this->send((new CreatePaymentRequest($payload, $query))->test($testmode)); + } + + /** + * Update the given Payment. + * + * Will throw a ApiException if the payment id is invalid or the resource cannot be found. + * + * @param string $id + * @param array|UpdatePaymentPayload $data + * + * @throws ApiException + */ + public function update($id, $data = [], bool $testmode = false): ?Payment + { + if (! $data instanceof UpdatePaymentPayload) { + $testmode = Utility::extractBool($data, 'testmode', $testmode); + $data = UpdatePaymentPayloadFactory::new($data) + ->create(); + } + + /** @var null|Payment */ + return $this->send((new UpdatePaymentRequest($id, $data))->test($testmode)); + } + + /** + * Deletes the given Payment. + * + * Will throw a ApiException if the payment id is invalid or the resource cannot be found. + * Returns with HTTP status No Content (204) if successful. + * + * + * @throws ApiException + */ + public function delete(string $id, $data = []): ?Payment + { + return $this->cancel($id, $data); + } + + /** + * Cancel the given Payment. This is just an alias of the 'delete' method. + * + * Will throw a ApiException if the payment id is invalid or the resource cannot be found. + * Returns with HTTP status No Content (204) if successful. + * + * @param array|bool $data + * + * @throws ApiException + */ + public function cancel(string $id, $data = []): ?Payment + { + $testmode = Utility::extractBool($data, 'testmode', false); + + /** @var null|Payment */ + return $this->send((new CancelPaymentRequest($id))->test($testmode)); + } + + /** + * Issue a refund for the given payment. + * + * The $data parameter may either be an array of endpoint + * parameters, or an instance of CreateRefundPaymentData. + * + * @param array|CreateRefundPaymentPayload $payload + * + * @throws ApiException + */ + public function refund(Payment $payment, $payload = [], bool $testmode = false): Refund + { + if (! $payload instanceof CreateRefundPaymentPayload) { + $testmode = Utility::extractBool($payload, 'testmode', $testmode); + $payload = CreateRefundPaymentPayloadFactory::new($payload) + ->create(); + } + + return $this->send((new CreatePaymentRefundRequest( + $payment->id, + $payload + ))->test($testmode)); + } + + /** + * Get the balance endpoint. + */ + public function page(?string $from = null, ?int $limit = null, array $filters = []): PaymentCollection + { + $testmode = Utility::extractBool($filters, 'testmode', false); + $query = SortablePaginatedQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + return $this->send((new GetPaginatedPaymentsRequest($query))->test($testmode)); + } + + /** + * Create an iterator for iterating over payments retrieved from Mollie. + * + * @param string $from The first resource ID you want to include in your list. + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iterator(?string $from = null, ?int $limit = null, array $filters = [], bool $iterateBackwards = false): LazyCollection + { + $testmode = Utility::extractBool($filters, 'testmode', false); + $query = SortablePaginatedQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + return $this->send( + (new GetPaginatedPaymentsRequest($query)) + ->useIterator() + ->setIterationDirection($iterateBackwards) + ->test($testmode) + ); + } +} diff --git a/src/EndpointCollection/PaymentLinkEndpointCollection.php b/src/EndpointCollection/PaymentLinkEndpointCollection.php new file mode 100644 index 000000000..a6afb5248 --- /dev/null +++ b/src/EndpointCollection/PaymentLinkEndpointCollection.php @@ -0,0 +1,131 @@ +create(); + } + + /** @var PaymentLink */ + return $this->send(new CreatePaymentLinkRequest($payload)); + } + + /** + * Retrieve a payment link from Mollie. + * + * Will throw an ApiException if the payment link id is invalid or the resource cannot be found. + * + * @param array $testmode + * + * @throws ApiException + */ + public function get(string $paymentLinkId, $testmode = []): PaymentLink + { + $testmode = Utility::extractBool($testmode, 'testmode', false); + + /** @var PaymentLink */ + return $this->send((new GetPaymentLinkRequest($paymentLinkId))->test($testmode)); + } + + /** + * Update a Payment Link. + * + * @param array|UpdatePaymentLinkPayload $payload + * + * @throws ApiException + */ + public function update(string $paymentLinkId, $payload = [], bool $testmode = false): PaymentLink + { + if (! $payload instanceof UpdatePaymentLinkPayload) { + $payload = UpdatePaymentLinkPayloadFactory::new($payload)->create(); + } + + /** @var PaymentLink */ + return $this->send((new UpdatePaymentLinkRequest($paymentLinkId, $payload))->test($testmode)); + } + + /** + * Delete a Payment Link. + * + * + * @throws ApiException + */ + public function delete(string $paymentLinkId, bool $testmode = false): void + { + $this->send((new DeletePaymentLinkRequest($paymentLinkId))->test($testmode)); + } + + /** + * Retrieves a collection of Payment Links from Mollie. + * + * @param string|null $from The first payment link ID you want to include in your list. + * @param array|bool $testmode + * + * @throws ApiException + */ + public function page(?string $from = null, ?int $limit = null, $testmode = []): PaymentLinkCollection + { + $testmode = Utility::extractBool($testmode, 'testmode', false); + + $query = PaginatedQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + ])->create(); + + /** @var PaymentLinkCollection */ + return $this->send((new GetPaginatedPaymentLinksRequest($query))->test($testmode)); + } + + /** + * Create an iterator for iterating over payment links retrieved from Mollie. + * + * @param string|null $from The first resource ID you want to include in your list. + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iterator( + ?string $from = null, + ?int $limit = null, + bool $testmode = false, + bool $iterateBackwards = false + ): LazyCollection { + $testmode = Utility::extractBool($testmode, 'testmode', false); + $query = PaginatedQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + ])->create(); + + return $this->send( + (new GetPaginatedPaymentLinksRequest($query)) + ->useIterator() + ->setIterationDirection($iterateBackwards) + ->test($testmode) + ); + } +} diff --git a/src/EndpointCollection/PaymentLinkPaymentEndpointCollection.php b/src/EndpointCollection/PaymentLinkPaymentEndpointCollection.php new file mode 100644 index 000000000..dbe1c4c76 --- /dev/null +++ b/src/EndpointCollection/PaymentLinkPaymentEndpointCollection.php @@ -0,0 +1,97 @@ +pageForId($paymentLink->id, $from, $limit, $filters); + } + + /** + * Retrieves a collection of Payments from Mollie for the given Payment Link ID. + * + * @param string|null $from The first payment ID you want to include in your list. + * + * @throws ApiException + */ + public function pageForId(string $paymentLinkId, ?string $from = null, ?int $limit = null, array $filters = []): PaymentCollection + { + $testmode = Utility::extractBool($filters, 'testmode', false); + $query = SortablePaginatedQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + /** @var PaymentCollection */ + return $this->send((new GetPaginatedPaymentLinkPaymentsRequest($paymentLinkId, $query))->test($testmode)); + } + + /** + * Create an iterator for iterating over payments associated with the provided Payment Link object, retrieved from Mollie. + * + * @param string|null $from The first resource ID you want to include in your list. + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iteratorFor( + PaymentLink $paymentLink, + ?string $from = null, + ?int $limit = null, + array $filters = [], + bool $iterateBackwards = false + ): LazyCollection { + return $this->iteratorForId( + $paymentLink->id, + $from, + $limit, + $filters, + $iterateBackwards + ); + } + + /** + * Create an iterator for iterating over payments associated with the provided Payment Link id, retrieved from Mollie. + * + * @param string|null $from The first resource ID you want to include in your list. + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iteratorForId( + string $paymentLinkId, + ?string $from = null, + ?int $limit = null, + array $filters = [], + bool $iterateBackwards = false + ): LazyCollection { + $testmode = Utility::extractBool($filters, 'testmode', false); + $query = SortablePaginatedQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + return $this->send( + (new GetPaginatedPaymentLinkPaymentsRequest($paymentLinkId, $query)) + ->useIterator() + ->setIterationDirection($iterateBackwards) + ->test($testmode) + ); + } +} diff --git a/src/EndpointCollection/PaymentRefundEndpointCollection.php b/src/EndpointCollection/PaymentRefundEndpointCollection.php new file mode 100644 index 000000000..75ac14e45 --- /dev/null +++ b/src/EndpointCollection/PaymentRefundEndpointCollection.php @@ -0,0 +1,169 @@ +createForId($payment->id, $data, $testmode); + } + + /** + * Creates a refund for a specific payment. + * + * @param array $payload + * + * @throws \Mollie\Api\Exceptions\ApiException + */ + public function createForId(string $paymentId, $payload = [], $testmode = []): Refund + { + $testmode = Utility::extractBool($testmode, 'testmode', false); + if (! $payload instanceof CreateRefundPaymentPayload) { + $testmode = Utility::extractBool($payload, 'testmode', $testmode); + $payload = CreateRefundPaymentPayloadFactory::new($payload) + ->create(); + } + + /** @var Refund */ + return $this->send((new CreatePaymentRefundRequest($paymentId, $payload))->test($testmode)); + } + + /** + * @throws \Mollie\Api\Exceptions\ApiException + */ + public function getFor(Payment $payment, string $refundId, array $parameters = [], bool $testmode = false): Refund + { + return $this->getForId($payment->id, $refundId, $parameters, $testmode); + } + + /** + * @param array|GetPaymentRefundQuery $query + * + * @throws \Mollie\Api\Exceptions\ApiException + */ + public function getForId(string $paymentId, string $refundId, $query = [], bool $testmode = false): Refund + { + if (! $query instanceof GetPaymentRefundQuery) { + $testmode = Utility::extractBool($query, 'testmode', $testmode); + $query = GetPaymentRefundQueryFactory::new($query) + ->create(); + } + + /** @var Refund */ + return $this->send((new GetPaymentRefundRequest($paymentId, $refundId, $query))->test($testmode)); + } + + /** + * @param array|bool $testmode + * @return null + * + * @throws \Mollie\Api\Exceptions\ApiException + */ + public function cancelForPayment(Payment $payment, string $refundId, $testmode = []) + { + return $this->cancelForId($payment->id, $refundId, $testmode); + } + + /** + * @param array|bool $testmode + * @return null + * + * @throws \Mollie\Api\Exceptions\ApiException + */ + public function cancelForId(string $paymentId, string $refundId, $testmode = []) + { + $testmode = Utility::extractBool($testmode, 'testmode', false); + + return $this->send((new CancelPaymentRefundRequest($paymentId, $refundId))->test($testmode)); + } + + /** + * @throws \Mollie\Api\Exceptions\ApiException + */ + public function pageForId(string $paymentId, ?string $from = null, ?int $limit = null, array $filters = []): RefundCollection + { + $testmode = Utility::extractBool($filters, 'testmode', false); + $query = GetPaginatedPaymentRefundQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + return $this->send((new GetPaginatedPaymentRefundsRequest($paymentId, $query))->test($testmode)); + } + + /** + * @throws \Mollie\Api\Exceptions\ApiException + */ + public function pageFor(Payment $payment, ?string $from = null, ?int $limit = null, array $filters = []): RefundCollection + { + return $this->pageForId($payment->id, $from, $limit, $filters); + } + + /** + * Create an iterator for iterating over refunds for the given payment, retrieved from Mollie. + * + * @param string|null $from The first resource ID you want to include in your list. + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iteratorFor( + Payment $payment, + ?string $from = null, + ?int $limit = null, + array $parameters = [], + bool $iterateBackwards = false + ): LazyCollection { + return $this->iteratorForId($payment->id, $from, $limit, $parameters, $iterateBackwards); + } + + /** + * Create an iterator for iterating over refunds for the given payment id, retrieved from Mollie. + * + * @param string|null $from The first resource ID you want to include in your list. + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iteratorForId( + string $paymentId, + ?string $from = null, + ?int $limit = null, + array $filters = [], + bool $iterateBackwards = false + ): LazyCollection { + $testmode = Utility::extractBool($filters, 'testmode', false); + $query = GetPaginatedPaymentRefundQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + return $this->send( + (new GetPaginatedPaymentRefundsRequest($paymentId, $query)) + ->useIterator() + ->setIterationDirection($iterateBackwards) + ->test($testmode) + ); + } +} diff --git a/src/EndpointCollection/PaymentRouteEndpointCollection.php b/src/EndpointCollection/PaymentRouteEndpointCollection.php new file mode 100644 index 000000000..20522e3f5 --- /dev/null +++ b/src/EndpointCollection/PaymentRouteEndpointCollection.php @@ -0,0 +1,41 @@ +updateReleaseDateForId($payment->id, $routeId, $releaseDate, $testmode); + } + + /** + * Update the release date for a payment route using payment ID. + * + * @param string $releaseDate UTC datetime when the funds will become available + * + * @throws ApiException + */ + public function updateReleaseDateForId(string $paymentId, string $routeId, string $releaseDate, bool $testmode = false): Route + { + $payload = UpdatePaymentRoutePayloadFactory::new([ + 'releaseDate' => $releaseDate, + ])->create(); + + /** @var Route */ + return $this->send((new UpdatePaymentRouteRequest($paymentId, $routeId, $payload))->test($testmode)); + } +} diff --git a/src/EndpointCollection/PermissionEndpointCollection.php b/src/EndpointCollection/PermissionEndpointCollection.php new file mode 100644 index 000000000..c3672ae31 --- /dev/null +++ b/src/EndpointCollection/PermissionEndpointCollection.php @@ -0,0 +1,41 @@ +send((new GetPermissionRequest($permissionId))->test($testmode)); + } + + /** + * Retrieve all permissions from Mollie. + * + * @throws ApiException + */ + public function list(): PermissionCollection + { + /** @var PermissionCollection */ + return $this->send(new ListPermissionsRequest); + } +} diff --git a/src/EndpointCollection/ProfileEndpointCollection.php b/src/EndpointCollection/ProfileEndpointCollection.php new file mode 100644 index 000000000..6687fdb5a --- /dev/null +++ b/src/EndpointCollection/ProfileEndpointCollection.php @@ -0,0 +1,152 @@ +create(); + } + + /** @var Profile */ + return $this->send(new CreateProfileRequest($payload)); + } + + /** + * Retrieve a Profile from Mollie. + * + * Will throw an ApiException if the profile id is invalid or the resource cannot be found. + * + * @param array|bool $testmode + * @return Profile|CurrentProfile + * + * @throws ApiException + */ + public function get(string $profileId, $testmode = []): Profile + { + $testmode = Utility::extractBool($testmode, 'testmode', false); + + /** @var Profile */ + return $this->send((new GetProfileRequest($profileId))->test($testmode)); + } + + /** + * Retrieve the current Profile from Mollie. + * + * @param array|bool $testmode + * + * @throws ApiException + */ + public function getCurrent($testmode = []): CurrentProfile + { + $testmode = Utility::extractBool($testmode, 'testmode', false); + + /** @var CurrentProfile */ + return $this->send( + (new GetProfileRequest('me')) + ->setHydratableResource(CurrentProfile::class) + ->test($testmode) + ); + } + + /** + * Update a specific Profile resource. + * + * Will throw an ApiException if the profile id is invalid or the resource cannot be found. + * + * @param array|UpdateProfilePayload $payload + * + * @throws ApiException + */ + public function update(string $profileId, $payload = []): ?Profile + { + if (! $payload instanceof UpdateProfilePayload) { + $payload = UpdateProfilePayloadFactory::new($payload) + ->create(); + } + + /** @var Profile|null */ + return $this->send(new UpdateProfileRequest($profileId, $payload)); + } + + /** + * Delete a Profile from Mollie. + * + * Will throw a ApiException if the profile id is invalid or the resource cannot be found. + * Returns with HTTP status No Content (204) if successful. + * + * @throws ApiException + */ + public function delete(string $profileId): void + { + $this->send(new DeleteProfileRequest($profileId)); + } + + /** + * Retrieves a collection of Profiles from Mollie. + * + * @param string|null $from The first profile ID you want to include in your list. + * + * @throws ApiException + */ + public function page(?string $from = null, ?int $limit = null): ProfileCollection + { + $query = PaginatedQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + ])->create(); + + /** @var ProfileCollection */ + return $this->send(new GetPaginatedProfilesRequest($query)); + } + + /** + * Create an iterator for iterating over profiles retrieved from Mollie. + * + * @param string|null $from The first resource ID you want to include in your list. + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iterator( + ?string $from = null, + ?int $limit = null, + bool $iterateBackwards = false + ): LazyCollection { + $query = PaginatedQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + ])->create(); + + return $this->send( + (new GetPaginatedProfilesRequest($query)) + ->useIterator() + ->setIterationDirection($iterateBackwards) + ); + } +} diff --git a/src/EndpointCollection/ProfileMethodEndpointCollection.php b/src/EndpointCollection/ProfileMethodEndpointCollection.php new file mode 100644 index 000000000..bf27872d3 --- /dev/null +++ b/src/EndpointCollection/ProfileMethodEndpointCollection.php @@ -0,0 +1,153 @@ +enableForId($profileId, $id); + } + + /** + * Enable a method for the provided Profile object. + * Alias of enableFor for backwards compatibility. + * + * @throws ApiException + */ + public function createFor(Profile $profile, string $id): Method + { + return $this->enableFor($profile, $id); + } + + /** + * Enable a method for the current profile. + * Alias of enable for backwards compatibility. + * + * @throws ApiException + */ + public function createForCurrentProfile(string $id): Method + { + return $this->enable($id); + } + + /** + * Enable a payment method for a specific profile. + * + * @param string $profileId The profile's ID or 'me' for the current profile + * @param string $id The payment method ID + * + * @throws ApiException + */ + public function enableForId(string $profileId, string $id): Method + { + /** @var Method */ + return $this->send(new EnableProfileMethodRequest($profileId, $id)); + } + + /** + * Enable a payment method for the provided Profile object. + * + * @param string $id The payment method ID + * + * @throws ApiException + */ + public function enableFor(Profile $profile, string $id): Method + { + return $this->enableForId($profile->id, $id); + } + + /** + * Enable a payment method for the current profile. + * + * @param string $id The payment method ID + * + * @throws ApiException + */ + public function enable(string $id): Method + { + return $this->enableForId('me', $id); + } + + /** + * Disable a method for the provided Profile ID. + * Alias of disableForId for backwards compatibility. + * + * @throws ApiException + */ + public function deleteForId(string $profileId, string $id): void + { + $this->disableForId($profileId, $id); + } + + /** + * Disable a method for the provided Profile object. + * Alias of disableFor for backwards compatibility. + * + * @throws ApiException + */ + public function deleteFor(Profile $profile, string $id): void + { + $this->disableFor($profile, $id); + } + + /** + * Disable a method for the current profile. + * Alias of disable for backwards compatibility. + * + * @throws ApiException + */ + public function deleteForCurrentProfile(string $id): void + { + $this->disable($id); + } + + /** + * Disable a payment method for a specific profile. + * + * @param string $profileId The profile's ID or 'me' for the current profile + * @param string $id The payment method ID + * + * @throws ApiException + */ + public function disableForId(string $profileId, string $id): void + { + $this->send(new DisableProfileMethodRequest($profileId, $id)); + } + + /** + * Disable a payment method for the provided Profile object. + * + * @param string $id The payment method ID + * + * @throws ApiException + */ + public function disableFor(Profile $profile, string $id): void + { + $this->disableForId($profile->id, $id); + } + + /** + * Disable a payment method for the current profile. + * + * @param string $id The payment method ID + * + * @throws ApiException + */ + public function disable(string $id): void + { + $this->disableForId('me', $id); + } +} diff --git a/src/EndpointCollection/RefundEndpointCollection.php b/src/EndpointCollection/RefundEndpointCollection.php new file mode 100644 index 000000000..2cfa43a28 --- /dev/null +++ b/src/EndpointCollection/RefundEndpointCollection.php @@ -0,0 +1,60 @@ + $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + /** @var RefundCollection */ + return $this->send((new GetPaginatedRefundsRequest($query))->test($testmode)); + } + + /** + * Create an iterator for iterating over refunds retrieved from Mollie. + * + * @param string|null $from The first resource ID you want to include in your list. + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iterator( + ?string $from = null, + ?int $limit = null, + array $filters = [], + bool $iterateBackwards = false + ): LazyCollection { + $testmode = Utility::extractBool($filters, 'testmode', false); + $query = GetPaginatedRefundsQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + return $this->send( + (new GetPaginatedRefundsRequest($query)) + ->useIterator() + ->setIterationDirection($iterateBackwards) + ->test($testmode) + ); + } +} diff --git a/src/EndpointCollection/SalesInvoiceEndpointCollection.php b/src/EndpointCollection/SalesInvoiceEndpointCollection.php new file mode 100644 index 000000000..d2e12134f --- /dev/null +++ b/src/EndpointCollection/SalesInvoiceEndpointCollection.php @@ -0,0 +1,109 @@ +send(new GetSalesInvoiceRequest($id)); + } + + /** + * Creates a SalesInvoice in Mollie. + * + * @param array|CreateSalesInvoicePayload $payload + * + * @throws ApiException + */ + public function create($payload = []): SalesInvoice + { + if (! $payload instanceof CreateSalesInvoicePayload) { + $payload = CreateSalesInvoicePayloadFactory::new($payload)->create(); + } + + return $this->send(new CreateSalesInvoiceRequest($payload)); + } + + /** + * Update a specific SalesInvoice resource. + * + * @throws ApiException + */ + public function update(string $id, $payload = []): ?SalesInvoice + { + if (! $payload instanceof UpdateSalesInvoicePayload) { + $payload = UpdateSalesInvoicePayloadFactory::new($payload)->create(); + } + + return $this->send(new UpdateSalesInvoiceRequest($id, $payload)); + } + + /** + * Delete a SalesInvoice from Mollie. + * + * @throws ApiException + */ + public function delete(string $id): void + { + $this->send(new DeleteSalesInvoiceRequest($id)); + } + + /** + * Retrieves a collection of SalesInvoices from Mollie. + * + * @throws ApiException + */ + public function page(?string $from = null, ?int $limit = null): SalesInvoiceCollection + { + $query = PaginatedQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + ])->create(); + + return $this->send(new GetPaginatedSalesInvoicesRequest($query)); + } + + /** + * Create an iterator for iterating over sales invoices retrieved from Mollie. + * + * @param string|null $from The first resource ID you want to include in your list. + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iterator( + ?string $from = null, + ?int $limit = null, + bool $iterateBackwards = false + ): LazyCollection { + $query = PaginatedQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + ])->create(); + + return $this->send( + (new GetPaginatedSalesInvoicesRequest($query)) + ->useIterator() + ->setIterationDirection($iterateBackwards) + ); + } +} diff --git a/src/EndpointCollection/SessionEndpointCollection.php b/src/EndpointCollection/SessionEndpointCollection.php new file mode 100644 index 000000000..1dd47cf1e --- /dev/null +++ b/src/EndpointCollection/SessionEndpointCollection.php @@ -0,0 +1,134 @@ +send(new GetSessionRequest($sessionId, $query)); + } + + /** + * Creates a session in Mollie. + * + * @param array|AnyData $payload + * @param array|AnyData $query + * + * @throws ApiException + */ + public function create($payload = [], $query = []): Session + { + if (! $payload instanceof AnyData) { + $payload = AnyData::fromArray($payload); + } + + if (! $query instanceof AnyData) { + $query = AnyData::fromArray($query); + } + + /** @var Session */ + return $this->send(new CreateSessionRequest($payload, $query)); + } + + /** + * Update the given Session. + * + * Will throw a ApiException if the session id is invalid or the resource cannot be found. + * + * @param array|AnyData $payload + * + * @throws ApiException + */ + public function update(string $id, $payload = []): Session + { + if (! $payload instanceof AnyData) { + $payload = AnyData::fromArray($payload); + } + + /** @var Session */ + return $this->send(new UpdateSessionRequest($id, $payload)); + } + + /** + * Cancel the given Session. + * + * Will throw a ApiException if the session id is invalid or the resource cannot be found. + * + * @throws ApiException + */ + public function cancel(string $id): void + { + $this->send(new CancelSessionRequest($id)); + } + + /** + * Get the sessions endpoint. + * + * @param string|null $from The first session ID you want to include in your list. + * + * @throws ApiException + */ + public function page(?string $from = null, ?int $limit = null, array $filters = []): SessionCollection + { + $query = SortablePaginatedQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + /** @var SessionCollection */ + return $this->send(new GetPaginatedSessionsRequest($query)); + } + + /** + * Create an iterator for iterating over sessions retrieved from Mollie. + * + * @param string|null $from The first resource ID you want to include in your list. + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iterator( + ?string $from = null, + ?int $limit = null, + array $filters = [], + bool $iterateBackwards = false + ): LazyCollection { + $query = SortablePaginatedQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + return $this->send( + (new GetPaginatedSessionsRequest($query)) + ->useIterator() + ->setIterationDirection($iterateBackwards) + ); + } +} diff --git a/src/EndpointCollection/SettlementCaptureEndpointCollection.php b/src/EndpointCollection/SettlementCaptureEndpointCollection.php new file mode 100644 index 000000000..aea502dbf --- /dev/null +++ b/src/EndpointCollection/SettlementCaptureEndpointCollection.php @@ -0,0 +1,89 @@ +pageForId($settlement->id, $query, $testmode); + } + + /** + * Retrieves a collection of Settlement Captures from Mollie. + * + * @param array|GetPaginatedSettlementCapturesQuery $query + * + * @throws ApiException + */ + public function pageForId(string $settlementId, $query = [], bool $testmode = false): CaptureCollection + { + if (! $query instanceof GetPaginatedSettlementCapturesQuery) { + $testmode = Utility::extractBool($query, 'testmode', $testmode); + $query = GetPaginatedSettlementCapturesQueryFactory::new($query)->create(); + } + + /** @var CaptureCollection */ + return $this->send((new GetPaginatedSettlementCapturesRequest($settlementId, $query))->test($testmode)); + } + + /** + * Create an iterator for iterating over captures for the given settlement, retrieved from Mollie. + * + * @param string|null $from The first resource ID you want to include in your list. + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iteratorFor( + Settlement $settlement, + ?string $from = null, + ?int $limit = null, + array $parameters = [], + bool $iterateBackwards = false + ): LazyCollection { + return $this->iteratorForId($settlement->id, $from, $limit, $parameters, $iterateBackwards); + } + + /** + * Create an iterator for iterating over captures for the given settlement id, retrieved from Mollie. + * + * @param string|null $from The first resource ID you want to include in your list. + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iteratorForId( + string $settlementId, + ?string $from = null, + ?int $limit = null, + array $filters = [], + bool $iterateBackwards = false + ): LazyCollection { + $testmode = Utility::extractBool($filters, 'testmode', false); + $query = GetPaginatedSettlementCapturesQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + return $this->send( + (new GetPaginatedSettlementCapturesRequest($settlementId, $query)) + ->useIterator() + ->setIterationDirection($iterateBackwards) + ->test($testmode) + ); + } +} diff --git a/src/EndpointCollection/SettlementChargebackEndpointCollection.php b/src/EndpointCollection/SettlementChargebackEndpointCollection.php new file mode 100644 index 000000000..78651f22b --- /dev/null +++ b/src/EndpointCollection/SettlementChargebackEndpointCollection.php @@ -0,0 +1,89 @@ +pageForId($settlement->id, $query, $testmode); + } + + /** + * Retrieves a collection of Settlement Chargebacks from Mollie. + * + * @param array|GetPaginatedSettlementChargebacksQuery $query + * + * @throws ApiException + */ + public function pageForId(string $settlementId, $query = [], bool $testmode = false): ChargebackCollection + { + if (! $query instanceof GetPaginatedSettlementChargebacksQuery) { + $testmode = Utility::extractBool($query, 'testmode', $testmode); + $query = GetPaginatedSettlementChargebacksQueryFactory::new($query)->create(); + } + + /** @var ChargebackCollection */ + return $this->send((new GetPaginatedSettlementChargebacksRequest($settlementId, $query))->test($testmode)); + } + + /** + * Create an iterator for iterating over chargebacks for the given settlement, retrieved from Mollie. + * + * @param string|null $from The first resource ID you want to include in your list. + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iteratorFor( + Settlement $settlement, + ?string $from = null, + ?int $limit = null, + array $parameters = [], + bool $iterateBackwards = false + ): LazyCollection { + return $this->iteratorForId($settlement->id, $from, $limit, $parameters, $iterateBackwards); + } + + /** + * Create an iterator for iterating over chargebacks for the given settlement id, retrieved from Mollie. + * + * @param string|null $from The first resource ID you want to include in your list. + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iteratorForId( + string $settlementId, + ?string $from = null, + ?int $limit = null, + array $filters = [], + bool $iterateBackwards = false + ): LazyCollection { + $testmode = Utility::extractBool($filters, 'testmode', false); + $query = GetPaginatedSettlementChargebacksQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + return $this->send( + (new GetPaginatedSettlementChargebacksRequest($settlementId, $query)) + ->useIterator() + ->setIterationDirection($iterateBackwards) + ->test($testmode) + ); + } +} diff --git a/src/EndpointCollection/SettlementEndpointCollection.php b/src/EndpointCollection/SettlementEndpointCollection.php new file mode 100644 index 000000000..c24f96e64 --- /dev/null +++ b/src/EndpointCollection/SettlementEndpointCollection.php @@ -0,0 +1,80 @@ +send(new GetSettlementRequest($settlementId)); + } + + /** + * Retrieve the details of the current settlement that has not yet been paid out. + * + * @throws ApiException + */ + public function next(): Settlement + { + return $this->send(new GetSettlementRequest('next')); + } + + /** + * Retrieve the details of the open balance of the organization. + * + * @throws ApiException + */ + public function open(): Settlement + { + return $this->send(new GetSettlementRequest('open')); + } + + /** + * Retrieves a collection of Settlements from Mollie. + * + * @throws ApiException + */ + public function page(?string $from = null, ?int $limit = null, array $filters = []): SettlementCollection + { + $query = GetPaginatedSettlementsQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + return $this->send(new GetPaginatedSettlementsRequest($query)); + } + + /** + * Create an iterator for iterating over settlements retrieved from Mollie. + */ + public function iterator(?string $from = null, ?int $limit = null, array $filters = [], bool $iterateBackwards = false): LazyCollection + { + $query = GetPaginatedSettlementsQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + return $this->send( + (new GetPaginatedSettlementsRequest($query)) + ->useIterator() + ->setIterationDirection($iterateBackwards) + ); + } +} diff --git a/src/EndpointCollection/SettlementPaymentEndpointCollection.php b/src/EndpointCollection/SettlementPaymentEndpointCollection.php new file mode 100644 index 000000000..f5866b2fa --- /dev/null +++ b/src/EndpointCollection/SettlementPaymentEndpointCollection.php @@ -0,0 +1,79 @@ +pageForId($settlement->id, $query, $testmode); + } + + /** + * Retrieves a collection of Settlement Payments from Mollie. + * + * @param array|SortablePaginatedQuery $query + * + * @throws ApiException + */ + public function pageForId(string $settlementId, $query = [], bool $testmode = false): PaymentCollection + { + if (! $query instanceof SortablePaginatedQuery) { + $testmode = Utility::extractBool($query, 'testmode', $testmode); + $query = SortablePaginatedQueryFactory::new($query)->create(); + } + + return $this->send((new GetPaginatedSettlementPaymentsRequest($settlementId, $query))->test($testmode)); + } + + /** + * Create an iterator for iterating over payments for the given settlement, retrieved from Mollie. + */ + public function iteratorFor( + Settlement $settlement, + ?string $from = null, + ?int $limit = null, + array $parameters = [], + bool $iterateBackwards = false + ): LazyCollection { + return $this->iteratorForId($settlement->id, $from, $limit, $parameters, $iterateBackwards); + } + + public function iteratorForId( + string $settlementId, + ?string $from = null, + ?int $limit = null, + array $parameters = [], + bool $iterateBackwards = false + ): LazyCollection { + $testmode = Utility::extractBool($parameters, 'testmode', false); + $query = SortablePaginatedQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $parameters, + ])->create(); + + return $this->send( + (new GetPaginatedSettlementPaymentsRequest($settlementId, $query)) + ->useIterator() + ->setIterationDirection($iterateBackwards) + ->test($testmode) + ); + } +} diff --git a/src/EndpointCollection/SettlementRefundEndpointCollection.php b/src/EndpointCollection/SettlementRefundEndpointCollection.php new file mode 100644 index 000000000..26368fa82 --- /dev/null +++ b/src/EndpointCollection/SettlementRefundEndpointCollection.php @@ -0,0 +1,82 @@ +pageForId($settlement->id, $query, $testmode); + } + + /** + * Retrieves a collection of Settlement Refunds from Mollie. + * + * @param array|GetPaginatedSettlementRefundsQuery $query + * + * @throws ApiException + */ + public function pageForId(string $settlementId, $query = [], bool $testmode = false): RefundCollection + { + if (! $query instanceof GetPaginatedSettlementRefundsQuery) { + $testmode = Utility::extractBool($query, 'testmode', $testmode); + $query = GetPaginatedSettlementRefundsQueryFactory::new($query)->create(); + } + + return $this->send((new GetPaginatedSettlementRefundsRequest($settlementId, $query))->test($testmode)); + } + + /** + * Create an iterator for iterating over refunds for the given settlement, retrieved from Mollie. + */ + public function iteratorFor( + Settlement $settlement, + ?string $from = null, + ?int $limit = null, + array $parameters = [], + bool $iterateBackwards = false + ): LazyCollection { + return $this->iteratorForId($settlement->id, $from, $limit, $parameters, $iterateBackwards); + } + + /** + * Create an iterator for iterating over refunds for the given settlement id, retrieved from Mollie. + */ + public function iteratorForId( + string $settlementId, + ?string $from = null, + ?int $limit = null, + array $filters = [], + bool $iterateBackwards = false + ): LazyCollection { + $testmode = Utility::extractBool($filters, 'testmode', false); + $query = GetPaginatedSettlementRefundsQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + return $this->send( + (new GetPaginatedSettlementRefundsRequest($settlementId, $query)) + ->useIterator() + ->setIterationDirection($iterateBackwards) + ->test($testmode) + ); + } +} diff --git a/src/EndpointCollection/SubscriptionEndpointCollection.php b/src/EndpointCollection/SubscriptionEndpointCollection.php new file mode 100644 index 000000000..c73d19a97 --- /dev/null +++ b/src/EndpointCollection/SubscriptionEndpointCollection.php @@ -0,0 +1,219 @@ +getForId($customer->id, $subscriptionId, $testmode); + } + + /** + * Retrieve a single subscription from Mollie. + * + * @throws ApiException + */ + public function getForId(string $customerId, string $subscriptionId, $testmode = []): Subscription + { + $testmode = Utility::extractBool($testmode, 'testmode'); + + return $this->send((new GetSubscriptionRequest($customerId, $subscriptionId))->test($testmode)); + } + + /** + * Creates a subscription for a Customer in Mollie. + * + * @param array|CreateSubscriptionPayload $data An array containing details on the subscription. + * + * @throws ApiException + */ + public function createFor(Customer $customer, $data = [], bool $testmode = false): Subscription + { + return $this->createForId($customer->id, $data, $testmode); + } + + /** + * Creates a subscription for a Customer in Mollie. + * + * @param array|CreateSubscriptionPayload $data An array containing details on the subscription. + * + * @throws ApiException + */ + public function createForId(string $customerId, $data = [], bool $testmode = false): Subscription + { + if (! $data instanceof CreateSubscriptionPayload) { + $testmode = Utility::extractBool($data, 'testmode', $testmode); + $data = CreateSubscriptionPayloadFactory::new($data)->create(); + } + + return $this->send((new CreateSubscriptionRequest($customerId, $data))->test($testmode)); + } + + /** + * Update the given Subscription. + * + * @param array|UpdateSubscriptionPayload $data + * + * @throws ApiException + */ + public function update(string $customerId, string $subscriptionId, $data = [], bool $testmode = false): ?Subscription + { + if (! $data instanceof UpdateSubscriptionPayload) { + $testmode = Utility::extractBool($data, 'testmode', $testmode); + $data = UpdateSubscriptionPayloadFactory::new($data)->create(); + } + + return $this->send((new UpdateSubscriptionRequest($customerId, $subscriptionId, $data))->test($testmode)); + } + + /** + * Cancel the given Subscription. + * + * @throws ApiException + */ + public function cancelFor(Customer $customer, string $subscriptionId, bool $testmode = false): ?Subscription + { + return $this->cancelForId($customer->id, $subscriptionId, $testmode); + } + + /** + * Cancel the given Subscription. + * + * @throws ApiException + */ + public function cancelForId(string $customerId, string $subscriptionId, bool $testmode = false): ?Subscription + { + return $this->send((new CancelSubscriptionRequest($customerId, $subscriptionId))->test($testmode)); + } + + /** + * Retrieve a page of subscriptions from Mollie. + * + * @throws ApiException + */ + public function pageFor(Customer $customer, ?string $from = null, ?int $limit = null, array $filters = []): SubscriptionCollection + { + return $this->pageForId($customer->id, $from, $limit, $filters); + } + + /** + * Retrieve a page of subscriptions from Mollie. + * + * @throws ApiException + */ + public function pageForId(string $customerId, ?string $from = null, ?int $limit = null, array $filters = []): SubscriptionCollection + { + $testmode = Utility::extractBool($filters, 'testmode', false); + $query = PaginatedQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + ])->create(); + + return $this->send((new GetPaginatedSubscriptionsRequest($customerId, $query))->test($testmode)); + } + + /** + * Create an iterator for iterating over subscriptions for the given customer, retrieved from Mollie. + */ + public function iteratorFor( + Customer $customer, + ?string $from = null, + ?int $limit = null, + array $filters = [], + bool $iterateBackwards = false + ): LazyCollection { + return $this->iteratorForId($customer->id, $from, $limit, $filters, $iterateBackwards); + } + + /** + * Create an iterator for iterating over subscriptions for the given customer id, retrieved from Mollie. + */ + public function iteratorForId( + string $customerId, + ?string $from = null, + ?int $limit = null, + array $filters = [], + bool $iterateBackwards = false + ): LazyCollection { + $testmode = Utility::extractBool($filters, 'testmode', false); + $query = PaginatedQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + ])->create(); + + return $this->send( + (new GetPaginatedSubscriptionsRequest($customerId, $query)) + ->useIterator() + ->setIterationDirection($iterateBackwards) + ->test($testmode) + ); + } + + public function allFor(?string $from = null, ?int $limit = null, array $filters = []): SubscriptionCollection + { + return $this->allForId($from, $limit, $filters); + } + + public function allForId( + ?string $from = null, + ?int $limit = null, + array $filters = [] + ): SubscriptionCollection { + $testmode = Utility::extractBool($filters, 'testmode', false); + $query = GetAllPaginatedSubscriptionsQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + return $this->send((new GetAllPaginatedSubscriptionsRequest($query))->test($testmode)); + } + + public function iteratorForAll( + ?string $from = null, + ?int $limit = null, + array $filters = [], + bool $iterateBackwards = true + ): LazyCollection { + $testmode = Utility::extractBool($filters, 'testmode', false); + $query = GetAllPaginatedSubscriptionsQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + 'filters' => $filters, + ])->create(); + + return $this->send( + (new GetAllPaginatedSubscriptionsRequest($query)) + ->useIterator() + ->setIterationDirection($iterateBackwards) + ->test($testmode) + ); + } +} diff --git a/src/EndpointCollection/SubscriptionPaymentEndpointCollection.php b/src/EndpointCollection/SubscriptionPaymentEndpointCollection.php new file mode 100644 index 000000000..d6bfd1e01 --- /dev/null +++ b/src/EndpointCollection/SubscriptionPaymentEndpointCollection.php @@ -0,0 +1,91 @@ +pageForIds($subscription->customerId, $subscription->id, $from, $limit, $testmode); + } + + /** + * Retrieves a paginated collection of Subscription Payments from Mollie. + * + * @param string|null $from The first payment ID you want to include in your list. + * @param int|null $limit The maximum amount of results you want to retrieve per page. + * @param bool|array $testmode + * + * @throws ApiException + */ + public function pageForIds( + string $customerId, + string $subscriptionId, + ?string $from = null, + ?int $limit = null, + $testmode = [] + ): PaymentCollection { + $testmode = Utility::extractBool($testmode, 'testmode', false); + $query = PaginatedQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + ])->create(); + + return $this->send((new GetPaginatedSubscriptionPaymentsRequest($customerId, $subscriptionId, $query))->test($testmode)); + } + + /** + * Create an iterator for iterating over payments for the given subscription, retrieved from Mollie. + */ + public function iteratorFor( + Subscription $subscription, + ?string $from = null, + ?int $limit = null, + $testmode = [], + bool $iterateBackwards = false + ): LazyCollection { + return $this->iteratorForIds($subscription->customerId, $subscription->id, $from, $limit, $testmode, $iterateBackwards); + } + + /** + * Create an iterator for iterating over payments for the given subscription ID, retrieved from Mollie. + */ + public function iteratorForIds( + string $customerId, + string $subscriptionId, + ?string $from = null, + ?int $limit = null, + $testmode = [], + bool $iterateBackwards = false + ): LazyCollection { + $testmode = Utility::extractBool($testmode, 'testmode', false); + $query = PaginatedQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + ])->create(); + + return $this->send( + (new GetPaginatedSubscriptionPaymentsRequest($customerId, $subscriptionId, $query)) + ->useIterator() + ->setIterationDirection($iterateBackwards) + ->test($testmode) + ); + } +} diff --git a/src/EndpointCollection/TerminalEndpointCollection.php b/src/EndpointCollection/TerminalEndpointCollection.php new file mode 100644 index 000000000..fd3fdad2d --- /dev/null +++ b/src/EndpointCollection/TerminalEndpointCollection.php @@ -0,0 +1,77 @@ +send((new GetTerminalRequest($id))->test($testmode)); + } + + /** + * Retrieves a collection of Terminals from Mollie for the current organization / profile, ordered from newest to oldest. + * + * @param string|null $from The first terminal ID you want to include in your list. + * + * @throws ApiException + */ + public function page(?string $from = null, ?int $limit = null, $testmode = []): TerminalCollection + { + $testmode = Utility::extractBool($testmode, 'testmode', false); + $query = PaginatedQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + ])->create(); + + /** @var TerminalCollection */ + return $this->send((new GetPaginatedTerminalsRequest($query))->test($testmode)); + } + + /** + * Create an iterator for iterating over terminals retrieved from Mollie. + * + * @param string|null $from The first resource ID you want to include in your list. + * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). + */ + public function iterator( + ?string $from = null, + ?int $limit = null, + $testmode = [], + bool $iterateBackwards = false + ): LazyCollection { + $testmode = Utility::extractBool($testmode, 'testmode', false); + $query = PaginatedQueryFactory::new([ + 'from' => $from, + 'limit' => $limit, + ])->create(); + + return $this->send( + (new GetPaginatedTerminalsRequest($query)) + ->useIterator() + ->setIterationDirection($iterateBackwards) + ->test($testmode) + ); + } +} diff --git a/src/EndpointCollection/WalletEndpointCollection.php b/src/EndpointCollection/WalletEndpointCollection.php new file mode 100644 index 000000000..32f064dd4 --- /dev/null +++ b/src/EndpointCollection/WalletEndpointCollection.php @@ -0,0 +1,29 @@ + $domain, + 'validationUrl' => $validationUrl, + ], $parameters))->create(); + + return $this->send(new ApplePayPaymentSessionRequest($payload)); + } +} diff --git a/src/Endpoints/BalanceEndpoint.php b/src/Endpoints/BalanceEndpoint.php deleted file mode 100644 index 5f44e41af..000000000 --- a/src/Endpoints/BalanceEndpoint.php +++ /dev/null @@ -1,98 +0,0 @@ -client, $count, $_links); - } - - /** - * @inheritDoc - */ - protected function getResourceObject() - { - return new Balance($this->client); - } - - /** - * Retrieve a single balance from Mollie. - * - * Will throw an ApiException if the balance id is invalid or the resource cannot be found. - * - * @param string $balanceId - * @param array $parameters - * @return \Mollie\Api\Resources\Balance|\Mollie\Api\Resources\BaseResource - * @throws ApiException - */ - public function get(string $balanceId, array $parameters = []) - { - if (empty($balanceId) || strpos($balanceId, self::RESOURCE_ID_PREFIX) !== 0) { - throw new ApiException("Invalid balance ID: '{$balanceId}'. A balance ID should start with '" . self::RESOURCE_ID_PREFIX . "'."); - } - - return parent::rest_read($balanceId, $parameters); - } - - /** - * Retrieve the primary balance from Mollie. - * - * Will throw an ApiException if the balance id is invalid or the resource cannot be found. - * - * @param array $parameters - * @return \Mollie\Api\Resources\Balance|\Mollie\Api\Resources\BaseResource - * @throws ApiException - */ - public function primary(array $parameters = []) - { - return parent::rest_read("primary", $parameters); - } - - /** - * Retrieves a collection of Balances from Mollie. - * - * @param string|null $from The first Balance ID you want to include in your list. - * @param int|null $limit - * @param array $parameters - * - * @return BaseCollection|BalanceCollection - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function page(?string $from = null, ?int $limit = null, array $parameters = []) - { - return $this->rest_list($from, $limit, $parameters); - } - - /** - * Create an iterator for iterating over balances retrieved from Mollie. - * - * @param string $from The first Balance ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iterator(?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - return $this->rest_iterator($from, $limit, $parameters, $iterateBackwards); - } -} diff --git a/src/Endpoints/BalanceReportEndpoint.php b/src/Endpoints/BalanceReportEndpoint.php deleted file mode 100644 index 86effa9cc..000000000 --- a/src/Endpoints/BalanceReportEndpoint.php +++ /dev/null @@ -1,69 +0,0 @@ -client); - } - - /** - * Retrieve a balance report for the provided balance id and parameters. - * - * @param string $balanceId - * @param array $parameters - * @return \Mollie\Api\Resources\BalanceReport|\Mollie\Api\Resources\BaseResource - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function getForId(string $balanceId, array $parameters = []) - { - $this->parentId = $balanceId; - - $result = $this->client->performHttpCall( - self::REST_READ, - $this->getResourcePath() . $this->buildQueryString($parameters) - ); - - return ResourceFactory::createFromApiResult($result, $this->getResourceObject()); - } - - /** - * Retrieve the primary balance. - * This is the balance of your account’s primary currency, where all payments are settled to by default. - * - * @param array $parameters - * @return \Mollie\Api\Resources\BalanceReport|\Mollie\Api\Resources\BaseResource - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function getForPrimary(array $parameters = []) - { - return $this->getForId("primary", $parameters); - } - - - /** - * Retrieve a balance report for the provided balance resource and parameters. - * - * @param \Mollie\Api\Resources\Balance $balance - * @param array $parameters - * @return \Mollie\Api\Resources\BalanceReport|\Mollie\Api\Resources\BaseResource - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function getFor(Balance $balance, array $parameters = []) - { - return $this->getForId($balance->id, $parameters); - } -} diff --git a/src/Endpoints/BalanceTransactionEndpoint.php b/src/Endpoints/BalanceTransactionEndpoint.php deleted file mode 100644 index 4f2447139..000000000 --- a/src/Endpoints/BalanceTransactionEndpoint.php +++ /dev/null @@ -1,129 +0,0 @@ -client, $count, $_links); - } - - /** - * @inheritDoc - */ - protected function getResourceObject() - { - return new BalanceTransaction($this->client); - } - - /** - * List the transactions for a specific Balance. - * - * @param Balance $balance - * @param array $parameters - * @return BalanceTransactionCollection|\Mollie\Api\Resources\BaseCollection - * - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function listFor(Balance $balance, array $parameters = []) - { - return $this->listForId($balance->id, $parameters); - } - - /** - * Create an iterator for iterating over balance transactions for the given balance retrieved from Mollie. - * - * @param Balance $balance - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iteratorFor(Balance $balance, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - return $this->iteratorForId($balance->id, $parameters, $iterateBackwards); - } - - /** - * List the transactions for a specific Balance ID. - * - * @param string $balanceId - * @param array $parameters - * @return BalanceTransactionCollection|\Mollie\Api\Resources\BaseCollection - * - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function listForId(string $balanceId, array $parameters = []) - { - $this->parentId = $balanceId; - - return parent::rest_list(null, null, $parameters); - } - - /** - * Create an iterator for iterating over balance transactions for the given balance id retrieved from Mollie. - * - * @param string $balanceId - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iteratorForId(string $balanceId, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - $this->parentId = $balanceId; - - return $this->rest_iterator(null, null, $parameters, $iterateBackwards); - } - - /** - * List the transactions for the primary Balance. - * - * @param array $parameters - * @return BalanceTransactionCollection|\Mollie\Api\Resources\BaseCollection - * - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function listForPrimary(array $parameters = []) - { - $this->parentId = "primary"; - - return parent::rest_list(null, null, $parameters); - } - - /** - * Create an iterator for iterating over transactions for the primary balance retrieved from Mollie. - * - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iteratorForPrimary(array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - $this->parentId = "primary"; - - return $this->rest_iterator(null, null, $parameters, $iterateBackwards); - } -} diff --git a/src/Endpoints/ChargebackEndpoint.php b/src/Endpoints/ChargebackEndpoint.php deleted file mode 100644 index c40c179c0..000000000 --- a/src/Endpoints/ChargebackEndpoint.php +++ /dev/null @@ -1,66 +0,0 @@ -client); - } - - /** - * Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return ChargebackCollection - */ - protected function getResourceCollectionObject($count, $_links) - { - return new ChargebackCollection($this->client, $count, $_links); - } - - /** - * Retrieves a collection of Chargebacks from Mollie. - * - * @param string $from The first chargeback ID you want to include in your list. - * @param int $limit - * @param array $parameters - * - * @return ChargebackCollection - * @throws ApiException - */ - public function page(?string $from = null, ?int $limit = null, array $parameters = []) - { - return $this->rest_list($from, $limit, $parameters); - } - - /** - * Create an iterator for iterating over chargeback retrieved from Mollie. - * - * @param string $from The first chargevback ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iterator(?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - return $this->rest_iterator($from, $limit, $parameters, $iterateBackwards); - } -} diff --git a/src/Endpoints/ClientEndpoint.php b/src/Endpoints/ClientEndpoint.php deleted file mode 100644 index 9d7ba66b1..000000000 --- a/src/Endpoints/ClientEndpoint.php +++ /dev/null @@ -1,85 +0,0 @@ -client); - } - - /** - * Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return ClientCollection - */ - protected function getResourceCollectionObject($count, $_links) - { - return new ClientCollection($this->client, $count, $_links); - } - - /** - * Retrieve a client from Mollie. - * - * Will throw an ApiException if the client id is invalid or the resource cannot be found. - * The client id corresponds to the organization id, for example "org_1337". - * - * @param string $clientId - * @param array $parameters - * - * @return Client - * @throws ApiException - */ - public function get($clientId, array $parameters = []) - { - if (empty($clientId)) { - throw new ApiException("Client ID is empty."); - } - - return parent::rest_read($clientId, $parameters); - } - - /** - * Retrieves a page of clients from Mollie. - * - * @param string $from The first client ID you want to include in your list. - * @param int $limit - * @param array $parameters - * - * @return ClientCollection - * @throws ApiException - */ - public function page(?string $from = null, ?int $limit = null, array $parameters = []) - { - return $this->rest_list($from, $limit, $parameters); - } - - /** - * Create an iterator for iterating over clients retrieved from Mollie. - * - * @param string $from The first client ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iterator(?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - return $this->rest_iterator($from, $limit, $parameters, $iterateBackwards); - } -} diff --git a/src/Endpoints/ClientLinkEndpoint.php b/src/Endpoints/ClientLinkEndpoint.php deleted file mode 100644 index 5641cc0d7..000000000 --- a/src/Endpoints/ClientLinkEndpoint.php +++ /dev/null @@ -1,40 +0,0 @@ -client); - } - - /** - * Creates a client link in Mollie. - * - * @param array $data An array containing details on the client link. - * - * @return ClientLink - * @throws ApiException - */ - public function create(array $data = []): ClientLink - { - return $this->rest_create($data, []); - } -} diff --git a/src/Endpoints/CollectionEndpointAbstract.php b/src/Endpoints/CollectionEndpointAbstract.php deleted file mode 100644 index 06b1dec21..000000000 --- a/src/Endpoints/CollectionEndpointAbstract.php +++ /dev/null @@ -1,71 +0,0 @@ - $from, "limit" => $limit], $filters); - - $apiPath = $this->getResourcePath() . $this->buildQueryString($filters); - - $result = $this->client->performHttpCall(self::REST_LIST, $apiPath); - - /** @var BaseCollection $collection */ - $collection = $this->getResourceCollectionObject($result->count, $result->_links); - - foreach ($result->_embedded->{$collection->getCollectionResourceName()} as $dataResult) { - $collection[] = ResourceFactory::createFromApiResult($dataResult, $this->getResourceObject()); - } - - return $collection; - } - - /** - * Create a generator for iterating over a resource's collection using REST API calls. - * - * This function fetches paginated data from a RESTful resource endpoint and returns a generator - * that allows you to iterate through the items in the collection one by one. It supports forward - * and backward iteration, pagination, and filtering. - * - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $filters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * @return LazyCollection - */ - protected function rest_iterator(?string $from = null, ?int $limit = null, array $filters = [], bool $iterateBackwards = false): LazyCollection - { - /** @var CursorCollection $page */ - $page = $this->rest_list($from, $limit, $filters); - - return $page->getAutoIterator($iterateBackwards); - } - - /** - * Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return BaseCollection - */ - abstract protected function getResourceCollectionObject($count, $_links); -} diff --git a/src/Endpoints/CustomerEndpoint.php b/src/Endpoints/CustomerEndpoint.php deleted file mode 100644 index 61c8e6895..000000000 --- a/src/Endpoints/CustomerEndpoint.php +++ /dev/null @@ -1,137 +0,0 @@ -client); - } - - /** - * Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return CustomerCollection - */ - protected function getResourceCollectionObject($count, $_links) - { - return new CustomerCollection($this->client, $count, $_links); - } - - /** - * Creates a customer in Mollie. - * - * @param array $data An array containing details on the customer. - * @param array $filters - * - * @return Customer - * @throws ApiException - */ - public function create(array $data = [], array $filters = []) - { - return $this->rest_create($data, $filters); - } - - /** - * Retrieve a single customer from Mollie. - * - * Will throw a ApiException if the customer id is invalid or the resource cannot be found. - * - * @param string $customerId - * @param array $parameters - * @return Customer - * @throws ApiException - */ - public function get($customerId, array $parameters = []) - { - return $this->rest_read($customerId, $parameters); - } - - /** - * Update a specific Customer resource. - * - * Will throw an ApiException if the customer id is invalid or the resource cannot be found. - * - * @param string $customerId - * - * @param array $data - * @return Customer - * @throws ApiException - */ - public function update($customerId, array $data = []) - { - if (empty($customerId) || strpos($customerId, self::RESOURCE_ID_PREFIX) !== 0) { - throw new ApiException("Invalid order ID: '{$customerId}'. An order ID should start with '" . self::RESOURCE_ID_PREFIX . "'."); - } - - return parent::rest_update($customerId, $data); - } - - /** - * Deletes the given Customer. - * - * Will throw a ApiException if the customer id is invalid or the resource cannot be found. - * Returns with HTTP status No Content (204) if successful. - * - * @param string $customerId - * - * @param array $data - * @return null - * @throws ApiException - */ - public function delete($customerId, array $data = []) - { - return $this->rest_delete($customerId, $data); - } - - /** - * Retrieves a collection of Customers from Mollie. - * - * @param string $from The first customer ID you want to include in your list. - * @param int $limit - * @param array $parameters - * - * @return CustomerCollection - * @throws ApiException - */ - public function page(?string $from = null, ?int $limit = null, array $parameters = []) - { - return $this->rest_list($from, $limit, $parameters); - } - - /** - * Create an iterator for iterating over customers retrieved from Mollie. - * - * @param string $from The first customer ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iterator(?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - return $this->rest_iterator($from, $limit, $parameters, $iterateBackwards); - } -} diff --git a/src/Endpoints/CustomerPaymentsEndpoint.php b/src/Endpoints/CustomerPaymentsEndpoint.php deleted file mode 100644 index 1730cb245..000000000 --- a/src/Endpoints/CustomerPaymentsEndpoint.php +++ /dev/null @@ -1,132 +0,0 @@ -client); - } - - /** - * Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return PaymentCollection - */ - protected function getResourceCollectionObject($count, $_links) - { - return new PaymentCollection($this->client, $count, $_links); - } - - /** - * Create a subscription for a Customer - * - * @param Customer $customer - * @param array $options - * @param array $filters - * - * @return Payment - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function createFor(Customer $customer, array $options = [], array $filters = []) - { - return $this->createForId($customer->id, $options, $filters); - } - - /** - * Create a subscription for a Customer ID - * - * @param string $customerId - * @param array $options - * @param array $filters - * - * @return \Mollie\Api\Resources\Payment - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function createForId($customerId, array $options = [], array $filters = []) - { - $this->parentId = $customerId; - - return parent::rest_create($options, $filters); - } - - /** - * @param Customer $customer - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * - * @return PaymentCollection - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function listFor(Customer $customer, ?string $from = null, ?int $limit = null, array $parameters = []) - { - return $this->listForId($customer->id, $from, $limit, $parameters); - } - - /** - * Create an iterator for iterating over payments for the given customer, retrieved from Mollie. - * - * @param Customer $customer - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iteratorFor(Customer $customer, ?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - return $this->iteratorForId($customer->id, $from, $limit, $parameters, $iterateBackwards); - } - - /** - * @param string $customerId - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * - * @return \Mollie\Api\Resources\PaymentCollection - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function listForId($customerId, ?string $from = null, ?int $limit = null, array $parameters = []) - { - $this->parentId = $customerId; - - return parent::rest_list($from, $limit, $parameters); - } - - /** - * Create an iterator for iterating over payments for the given customer id, retrieved from Mollie. - * - * @param string $customerId - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iteratorForId(string $customerId, ?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - $this->parentId = $customerId; - - return $this->rest_iterator($from, $limit, $parameters, $iterateBackwards); - } -} diff --git a/src/Endpoints/EndpointAbstract.php b/src/Endpoints/EndpointAbstract.php deleted file mode 100644 index 7c34c0a2d..000000000 --- a/src/Endpoints/EndpointAbstract.php +++ /dev/null @@ -1,210 +0,0 @@ -client = $api; - } - - /** - * @param array $filters - * @return string - */ - protected function buildQueryString(array $filters) - { - if (empty($filters)) { - return ""; - } - - foreach ($filters as $key => $value) { - if ($value === true) { - $filters[$key] = "true"; - } - - if ($value === false) { - $filters[$key] = "false"; - } - } - - return "?" . http_build_query($filters, "", "&"); - } - - /** - * @param array $body - * @param array $filters - * @return mixed - * @throws ApiException - */ - protected function rest_create(array $body, array $filters) - { - $result = $this->client->performHttpCall( - self::REST_CREATE, - $this->getResourcePath() . $this->buildQueryString($filters), - $this->parseRequestBody($body) - ); - - return ResourceFactory::createFromApiResult($result, $this->getResourceObject()); - } - - /** - * Sends a PATCH request to a single Mollie API object. - * - * @param string $id - * @param array $body - * - * @return mixed - * @throws ApiException - */ - protected function rest_update($id, array $body = []) - { - if (empty($id)) { - throw new ApiException("Invalid resource id."); - } - - $id = urlencode($id); - $result = $this->client->performHttpCall( - self::REST_UPDATE, - "{$this->getResourcePath()}/{$id}", - $this->parseRequestBody($body) - ); - - if ($result == null) { - return null; - } - - return ResourceFactory::createFromApiResult($result, $this->getResourceObject()); - } - - /** - * Retrieves a single object from the REST API. - * - * @param string $id Id of the object to retrieve. - * @param array $filters - * @return mixed - * @throws ApiException - */ - protected function rest_read($id, array $filters) - { - if (empty($id)) { - throw new ApiException("Invalid resource id."); - } - - $id = urlencode($id); - $result = $this->client->performHttpCall( - self::REST_READ, - "{$this->getResourcePath()}/{$id}" . $this->buildQueryString($filters) - ); - - return ResourceFactory::createFromApiResult($result, $this->getResourceObject()); - } - - /** - * Sends a DELETE request to a single Mollie API object. - * - * @param string $id - * @param array $body - * - * @return mixed - * @throws ApiException - */ - protected function rest_delete($id, array $body = []) - { - if (empty($id)) { - throw new ApiException("Invalid resource id."); - } - - $id = urlencode($id); - $result = $this->client->performHttpCall( - self::REST_DELETE, - "{$this->getResourcePath()}/{$id}", - $this->parseRequestBody($body) - ); - - if ($result == null) { - return null; - } - - return ResourceFactory::createFromApiResult($result, $this->getResourceObject()); - } - - - - /** - * Get the object that is used by this API endpoint. Every API endpoint uses one type of object. - * - * @return BaseResource - */ - abstract protected function getResourceObject(); - - /** - * @param string $resourcePath - */ - public function setResourcePath($resourcePath) - { - $this->resourcePath = strtolower($resourcePath); - } - - /** - * @return string - * @throws ApiException - */ - public function getResourcePath() - { - if (strpos($this->resourcePath, "_") !== false) { - [$parentResource, $childResource] = explode("_", $this->resourcePath, 2); - - if (empty($this->parentId)) { - throw new ApiException("Subresource '{$this->resourcePath}' used without parent '$parentResource' ID."); - } - - return "$parentResource/{$this->parentId}/$childResource"; - } - - return $this->resourcePath; - } - - /** - * @param array $body - * @return null|string - */ - protected function parseRequestBody(array $body) - { - if (empty($body)) { - return null; - } - - return @json_encode($body); - } -} diff --git a/src/Endpoints/InvoiceEndpoint.php b/src/Endpoints/InvoiceEndpoint.php deleted file mode 100644 index e577abd93..000000000 --- a/src/Endpoints/InvoiceEndpoint.php +++ /dev/null @@ -1,95 +0,0 @@ -client); - } - - /** - * Get the collection object that is used by this API. Every API uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return \Mollie\Api\Resources\BaseCollection - */ - protected function getResourceCollectionObject($count, $_links) - { - return new InvoiceCollection($this->client, $count, $_links); - } - - /** - * Retrieve an Invoice from Mollie. - * - * Will throw a ApiException if the invoice id is invalid or the resource cannot be found. - * - * @param string $invoiceId - * @param array $parameters - * - * @return Invoice - * @throws ApiException - */ - public function get($invoiceId, array $parameters = []) - { - return $this->rest_read($invoiceId, $parameters); - } - - /** - * Retrieves a collection of Invoices from Mollie. - * - * @param string $from The first invoice ID you want to include in your list. - * @param int $limit - * @param array $parameters - * - * @return InvoiceCollection - * @throws ApiException - */ - public function page($from = null, $limit = null, array $parameters = []) - { - return $this->rest_list($from, $limit, $parameters); - } - - /** - * This is a wrapper method for page - * - * @param array $parameters - * - * @return \Mollie\Api\Resources\BaseCollection - * @throws ApiException - */ - public function all(array $parameters = []) - { - return $this->page(null, null, $parameters); - } - - /** - * Create an iterator for iterating over invoices retrieved from Mollie. - * - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iterator(?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - return $this->rest_iterator($from, $limit, $parameters, $iterateBackwards); - } -} diff --git a/src/Endpoints/MandateEndpoint.php b/src/Endpoints/MandateEndpoint.php deleted file mode 100644 index 7e77c167a..000000000 --- a/src/Endpoints/MandateEndpoint.php +++ /dev/null @@ -1,184 +0,0 @@ -client); - } - - /** - * Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return MandateCollection - */ - protected function getResourceCollectionObject($count, $_links) - { - return new MandateCollection($this->client, $count, $_links); - } - - /** - * @param Customer $customer - * @param array $options - * @param array $filters - * - * @return \Mollie\Api\Resources\Mandate - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function createFor(Customer $customer, array $options = [], array $filters = []) - { - return $this->createForId($customer->id, $options, $filters); - } - - /** - * @param string $customerId - * @param array $options - * @param array $filters - * - * @return \Mollie\Api\Resources\Mandate - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function createForId($customerId, array $options = [], array $filters = []) - { - $this->parentId = $customerId; - - return parent::rest_create($options, $filters); - } - - /** - * @param Customer $customer - * @param string $mandateId - * @param array $parameters - * - * @return \Mollie\Api\Resources\Mandate - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function getFor(Customer $customer, $mandateId, array $parameters = []) - { - return $this->getForId($customer->id, $mandateId, $parameters); - } - - /** - * @param string $customerId - * @param string $mandateId - * @param array $parameters - * - * @return \Mollie\Api\Resources\Mandate - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function getForId($customerId, $mandateId, array $parameters = []) - { - $this->parentId = $customerId; - - return parent::rest_read($mandateId, $parameters); - } - - /** - * @param Customer $customer - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * - * @return \Mollie\Api\Resources\MandateCollection - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function listFor(Customer $customer, $from = null, $limit = null, array $parameters = []) - { - return $this->listForId($customer->id, $from, $limit, $parameters); - } - - /** - * Create an iterator for iterating over mandates for the given customer, retrieved from Mollie. - * - * @param Customer $customer - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iteratorFor(Customer $customer, ?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - return $this->iteratorForId($customer->id, $from, $limit, $parameters, $iterateBackwards); - } - - /** - * @param string $customerId - * @param string|null $from - * @param int|null $limit - * @param array $parameters - * - * @return \Mollie\Api\Resources\MandateCollection - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function listForId($customerId, $from = null, $limit = null, array $parameters = []) - { - $this->parentId = $customerId; - - return parent::rest_list($from, $limit, $parameters); - } - - /** - * Create an iterator for iterating over mandates for the given customer id, retrieved from Mollie. - * - * @param string $customerId - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iteratorForId(string $customerId, ?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - $this->parentId = $customerId; - - return $this->rest_iterator($from, $limit, $parameters, $iterateBackwards); - } - - /** - * @param Customer $customer - * @param string $mandateId - * @param array $data - * - * @return null - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function revokeFor(Customer $customer, $mandateId, $data = []) - { - return $this->revokeForId($customer->id, $mandateId, $data); - } - - /** - * @param string $customerId - * @param string $mandateId - * @param array $data - * - * @return null - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function revokeForId($customerId, $mandateId, $data = []) - { - $this->parentId = $customerId; - - return parent::rest_delete($mandateId, $data); - } -} diff --git a/src/Endpoints/MethodEndpoint.php b/src/Endpoints/MethodEndpoint.php deleted file mode 100644 index 934a27a84..000000000 --- a/src/Endpoints/MethodEndpoint.php +++ /dev/null @@ -1,103 +0,0 @@ -client); - } - - /** - * Retrieve all active methods. In test mode, this includes pending methods. The results are not paginated. - * - * @deprecated Use allActive() instead - * @param array $parameters - * - * @return \Mollie\Api\Resources\BaseCollection|\Mollie\Api\Resources\MethodCollection - * @throws ApiException - */ - public function all(array $parameters = []) - { - return $this->allActive($parameters); - } - - /** - * Retrieve all active methods for the organization. In test mode, this includes pending methods. - * The results are not paginated. - * - * @param array $parameters - * - * @return \Mollie\Api\Resources\BaseCollection|\Mollie\Api\Resources\MethodCollection - * @throws ApiException - */ - public function allActive(array $parameters = []) - { - return parent::rest_list(null, null, $parameters); - } - - /** - * Retrieve all available methods for the organization, including activated and not yet activated methods. The - * results are not paginated. Make sure to include the profileId parameter if using an OAuth Access Token. - * - * @param array $parameters Query string parameters. - * @return \Mollie\Api\Resources\BaseCollection|\Mollie\Api\Resources\MethodCollection - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function allAvailable(array $parameters = []) - { - $url = 'methods/all' . $this->buildQueryString($parameters); - - $result = $this->client->performHttpCall('GET', $url); - - return ResourceFactory::createBaseResourceCollection( - $this->client, - Method::class, - $result->_embedded->methods, - $result->_links - ); - } - - /** - * Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return MethodCollection - */ - protected function getResourceCollectionObject($count, $_links) - { - return new MethodCollection($count, $_links); - } - - /** - * Retrieve a payment method from Mollie. - * - * Will throw a ApiException if the method id is invalid or the resource cannot be found. - * - * @param string $methodId - * @param array $parameters - * @return \Mollie\Api\Resources\Method - * @throws ApiException - */ - public function get($methodId, array $parameters = []) - { - if (empty($methodId)) { - throw new ApiException("Method ID is empty."); - } - - return parent::rest_read($methodId, $parameters); - } -} diff --git a/src/Endpoints/MethodIssuerEndpoint.php b/src/Endpoints/MethodIssuerEndpoint.php deleted file mode 100644 index 2cb661b91..000000000 --- a/src/Endpoints/MethodIssuerEndpoint.php +++ /dev/null @@ -1,85 +0,0 @@ -profileId = $profileId; - $this->methodId = $methodId; - $this->issuerId = $issuerId; - - $response = $this->rest_create([], []); - - $this->resetResourceIds(); - - return $response; - } - - public function disable(string $profileId, string $methodId, string $issuerId) - { - $this->profileId = $profileId; - $this->methodId = $methodId; - - return $this->rest_delete($issuerId); - } - - protected function resetResourceIds() - { - $this->profileId = null; - $this->methodId = null; - $this->issuerId = null; - } - - /** - * @return string - * @throws ApiException - */ - public function getResourcePath() - { - if (! $this->profileId) { - throw new ApiException("No profileId provided."); - } - - if (! $this->methodId) { - throw new ApiException("No methodId provided."); - } - - $path = "profiles/{$this->profileId}/methods/{$this->methodId}/issuers"; - - if ($this->issuerId) { - $path .= "/$this->issuerId"; - } - - return $path; - } - - /** - * Get the object that is used by this API endpoint. Every API endpoint uses one type of object. - * - * @return Issuer - */ - protected function getResourceObject() - { - return new Issuer($this->client); - } -} diff --git a/src/Endpoints/OnboardingEndpoint.php b/src/Endpoints/OnboardingEndpoint.php deleted file mode 100644 index c8cb9a364..000000000 --- a/src/Endpoints/OnboardingEndpoint.php +++ /dev/null @@ -1,89 +0,0 @@ -client); - } - - /** - * Retrieve the organization's onboarding status from Mollie. - * - * Will throw a ApiException if the resource cannot be found. - * - * @return Onboarding - * @throws ApiException - */ - public function get() - { - return $this->rest_read('', []); - } - - /** - * @deprecated 2023-05-01 For an alternative, see https://docs.mollie.com/reference/create-client-link . - * Submit data that will be prefilled in the merchant’s onboarding. - * Please note that the data you submit will only be processed when the onboarding status is needs-data. - * - * Information that the merchant has entered in their dashboard will not be overwritten. - * - * Will throw an ApiException if the resource cannot be found. - * @throws ApiException - */ - public function submit(array $parameters = []) - { - return $this->rest_create($parameters, []); - } - - /** - * @param string $id - * @param array $filters - * - * @return mixed - * @throws \Mollie\Api\Exceptions\ApiException - */ - protected function rest_read($id, array $filters) - { - $result = $this->client->performHttpCall( - self::REST_READ, - $this->getResourcePath() . $this->buildQueryString($filters) - ); - - return ResourceFactory::createFromApiResult($result, $this->getResourceObject()); - } - - /** - * @param array $body - * @param array $filters - * - * @return mixed - * @throws \Mollie\Api\Exceptions\ApiException - */ - protected function rest_create(array $body, array $filters) - { - $this->client->performHttpCall( - self::REST_CREATE, - $this->getResourcePath() . $this->buildQueryString($filters), - $this->parseRequestBody($body) - ); - } -} diff --git a/src/Endpoints/OrderEndpoint.php b/src/Endpoints/OrderEndpoint.php deleted file mode 100644 index 91f7bc347..000000000 --- a/src/Endpoints/OrderEndpoint.php +++ /dev/null @@ -1,146 +0,0 @@ -client); - } - - /** - * Get the collection object that is used by this API endpoint. Every API - * endpoint uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return OrderCollection - */ - protected function getResourceCollectionObject($count, $_links) - { - return new OrderCollection($this->client, $count, $_links); - } - - /** - * Creates a order in Mollie. - * - * @param array $data An array containing details on the order. - * @param array $filters - * - * @return Order - * @throws ApiException - */ - public function create(array $data = [], array $filters = []) - { - return $this->rest_create($data, $filters); - } - - /** - * Update a specific Order resource - * - * Will throw a ApiException if the order id is invalid or the resource cannot be found. - * - * @param string $orderId - * - * @param array $data - * @return Order - * @throws ApiException - */ - public function update($orderId, array $data = []) - { - if (empty($orderId) || strpos($orderId, self::RESOURCE_ID_PREFIX) !== 0) { - throw new ApiException("Invalid order ID: '{$orderId}'. An order ID should start with '" . self::RESOURCE_ID_PREFIX . "'."); - } - - return parent::rest_update($orderId, $data); - } - - /** - * Retrieve a single order from Mollie. - * - * Will throw a ApiException if the order id is invalid or the resource cannot - * be found. - * - * @param array $parameters - * @return Order - * @throws ApiException - */ - public function get($orderId, array $parameters = []) - { - if (empty($orderId) || strpos($orderId, self::RESOURCE_ID_PREFIX) !== 0) { - throw new ApiException("Invalid order ID: '{$orderId}'. An order ID should start with '" . self::RESOURCE_ID_PREFIX . "'."); - } - - return parent::rest_read($orderId, $parameters); - } - - /** - * Cancel the given Order. - * - * If the order was partially shipped, the status will be "completed" instead of - * "canceled". - * Will throw a ApiException if the order id is invalid or the resource cannot - * be found. - * Returns the canceled order with HTTP status 200. - * - * @param string $orderId - * - * @param array $parameters - * @return Order - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function cancel($orderId, $parameters = []) - { - return $this->rest_delete($orderId, $parameters); - } - - /** - * Retrieves a collection of Orders from Mollie. - * - * @param string $from The first order ID you want to include in your list. - * @param int $limit - * @param array $parameters - * - * @return OrderCollection - * @throws ApiException - */ - public function page(?string $from = null, ?int $limit = null, array $parameters = []) - { - return $this->rest_list($from, $limit, $parameters); - } - - /** - * Create an iterator for iterating over orders retrieved from Mollie. - * - * @param string $from The first order ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iterator(?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - return $this->rest_iterator($from, $limit, $parameters, $iterateBackwards); - } -} diff --git a/src/Endpoints/OrderLineEndpoint.php b/src/Endpoints/OrderLineEndpoint.php deleted file mode 100644 index 2f16f0dad..000000000 --- a/src/Endpoints/OrderLineEndpoint.php +++ /dev/null @@ -1,139 +0,0 @@ -client); - } - - /** - * Get the collection object that is used by this API endpoint. Every API - * endpoint uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return OrderLineCollection - */ - protected function getResourceCollectionObject($count, $_links) - { - return new OrderLineCollection($count, $_links); - } - - /** - * Update a specific OrderLine resource. - * - * Will throw an ApiException if the order line id is invalid or the resource cannot be found. - * - * @param string|null $orderId - * @param string $orderlineId - * - * @param array $data - * - * @return \Mollie\Api\Resources\BaseResource|null - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function update($orderId, $orderlineId, array $data = []) - { - $this->parentId = $orderId; - - if (empty($orderlineId) || strpos($orderlineId, self::RESOURCE_ID_PREFIX) !== 0) { - throw new ApiException("Invalid order line ID: '{$orderlineId}'. An order line ID should start with '".self::RESOURCE_ID_PREFIX."'."); - } - - return parent::rest_update($orderlineId, $data); - } - - /** - * @param string $orderId - * @param array $operations - * @param array $parameters - * @return Order|\Mollie\Api\Resources\BaseResource - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function updateMultiple(string $orderId, array $operations, array $parameters = []) - { - if (empty($orderId)) { - throw new ApiException("Invalid resource id."); - } - - $this->parentId = $orderId; - - $parameters['operations'] = $operations; - - $result = $this->client->performHttpCall( - self::REST_UPDATE, - "{$this->getResourcePath()}", - $this->parseRequestBody($parameters) - ); - - return ResourceFactory::createFromApiResult($result, new Order($this->client)); - } - - /** - * Cancel lines for the provided order. - * The data array must contain a lines array. - * You can pass an empty lines array if you want to cancel all eligible lines. - * Returns null if successful. - * - * @param Order $order - * @param array $data - * - * @return null - * @throws ApiException - */ - public function cancelFor(Order $order, array $data) - { - return $this->cancelForId($order->id, $data); - } - - /** - * Cancel lines for the provided order id. - * The data array must contain a lines array. - * You can pass an empty lines array if you want to cancel all eligible lines. - * Returns null if successful. - * - * @param string $orderId - * @param array $data - * - * @return null - * @throws ApiException - */ - public function cancelForId($orderId, array $data) - { - if (! isset($data['lines']) || ! is_array($data['lines'])) { - throw new ApiException("A lines array is required."); - } - $this->parentId = $orderId; - - $this->client->performHttpCall( - self::REST_DELETE, - "{$this->getResourcePath()}", - $this->parseRequestBody($data) - ); - - return null; - } -} diff --git a/src/Endpoints/OrderPaymentEndpoint.php b/src/Endpoints/OrderPaymentEndpoint.php deleted file mode 100644 index 6bedacf3e..000000000 --- a/src/Endpoints/OrderPaymentEndpoint.php +++ /dev/null @@ -1,74 +0,0 @@ -client); - } - - /** - * Get the collection object that is used by this API endpoint. Every API - * endpoint uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return \Mollie\Api\Resources\PaymentCollection - */ - protected function getResourceCollectionObject($count, $_links) - { - return new PaymentCollection($this->client, $count, $_links); - } - - /** - * Creates a payment in Mollie for a specific order. - * - * @param \Mollie\Api\Resources\Order $order - * @param array $data An array containing details on the order payment. - * @param array $filters - * - * @return \Mollie\Api\Resources\Payment - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function createFor(Order $order, array $data, array $filters = []) - { - return $this->createForId($order->id, $data, $filters); - } - - /** - * Creates a payment in Mollie for a specific order ID. - * - * @param string $orderId - * @param array $data An array containing details on the order payment. - * @param array $filters - * - * @return \Mollie\Api\Resources\Payment - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function createForId($orderId, array $data, array $filters = []) - { - $this->parentId = $orderId; - - return $this->rest_create($data, $filters); - } -} diff --git a/src/Endpoints/OrderRefundEndpoint.php b/src/Endpoints/OrderRefundEndpoint.php deleted file mode 100644 index ac4edf3dc..000000000 --- a/src/Endpoints/OrderRefundEndpoint.php +++ /dev/null @@ -1,93 +0,0 @@ -client); - } - - /** - * Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return RefundCollection - */ - protected function getResourceCollectionObject($count, $_links) - { - return new RefundCollection($this->client, $count, $_links); - } - - /** - * Refund some order lines. You can provide an empty array for the - * "lines" data to refund all eligible lines for this order. - * - * @param Order $order - * @param array $data - * @param array $filters - * - * @return Refund - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function createFor(Order $order, array $data, array $filters = []) - { - return $this->createForId($order->id, $data, $filters); - } - - /** - * Refund some order lines. You can provide an empty array for the - * "lines" data to refund all eligible lines for this order. - * - * @param string $orderId - * @param array $data - * @param array $filters - * - * @return \Mollie\Api\Resources\Refund - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function createForId($orderId, array $data, array $filters = []) - { - $this->parentId = $orderId; - - return parent::rest_create($data, $filters); - } - - /** - * @param $orderId - * @param array $parameters - * @return RefundCollection - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function pageForId($orderId, array $parameters = []) - { - $this->parentId = $orderId; - - return parent::rest_list(null, null, $parameters); - } - - /** - * @param \Mollie\Api\Resources\Order $order - * @param array $parameters - * @return \Mollie\Api\Resources\RefundCollection - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function pageFor(Order $order, array $parameters = []) - { - return $this->pageForId($order->id, $parameters); - } -} diff --git a/src/Endpoints/OrganizationEndpoint.php b/src/Endpoints/OrganizationEndpoint.php deleted file mode 100644 index 10a7d7b95..000000000 --- a/src/Endpoints/OrganizationEndpoint.php +++ /dev/null @@ -1,64 +0,0 @@ -client); - } - - /** - * Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return OrganizationCollection - */ - protected function getResourceCollectionObject($count, $_links) - { - return new OrganizationCollection($this->client, $count, $_links); - } - - /** - * Retrieve an organization from Mollie. - * - * Will throw a ApiException if the organization id is invalid or the resource cannot be found. - * - * @param string $organizationId - * @param array $parameters - * @return Organization - * @throws ApiException - */ - public function get($organizationId, array $parameters = []) - { - if (empty($organizationId)) { - throw new ApiException("Organization ID is empty."); - } - - return parent::rest_read($organizationId, $parameters); - } - - /** - * Retrieve the current organization from Mollie. - * - * @param array $parameters - * @return Organization - * @throws ApiException - */ - public function current(array $parameters = []) - { - return parent::rest_read('me', $parameters); - } -} diff --git a/src/Endpoints/OrganizationPartnerEndpoint.php b/src/Endpoints/OrganizationPartnerEndpoint.php deleted file mode 100644 index 06a677b04..000000000 --- a/src/Endpoints/OrganizationPartnerEndpoint.php +++ /dev/null @@ -1,58 +0,0 @@ -client); - } - - /** - * Retrieve details about the partner status of the currently authenticated organization. - * - * Will throw an ApiException if the resource cannot be found. - * - * @return Partner - * @throws ApiException - */ - public function get() - { - return $this->rest_read('', []); - } - - /** - * @param string $id - * @param array $filters - * - * @return mixed - * @throws \Mollie\Api\Exceptions\ApiException - */ - protected function rest_read($id, array $filters) - { - $result = $this->client->performHttpCall( - self::REST_READ, - $this->getResourcePath() . $this->buildQueryString($filters) - ); - - return ResourceFactory::createFromApiResult($result, $this->getResourceObject()); - } -} diff --git a/src/Endpoints/PaymentCaptureEndpoint.php b/src/Endpoints/PaymentCaptureEndpoint.php deleted file mode 100644 index 61b2a6d24..000000000 --- a/src/Endpoints/PaymentCaptureEndpoint.php +++ /dev/null @@ -1,156 +0,0 @@ -client); - } - - /** - * Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return \Mollie\Api\Resources\CaptureCollection - */ - protected function getResourceCollectionObject($count, $_links) - { - return new CaptureCollection($this->client, $count, $_links); - } - - /** - * Creates a payment capture in Mollie. - * - * @param Payment $payment. - * @param array $data An array containing details on the capture. - * @param array $filters - * - * @return Capture - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function createFor(Payment $payment, array $data = [], array $filters = []) - { - return $this->createForId($payment->id, $data, $filters); - } - - /** - * Creates a payment capture in Mollie. - * - * @param string $paymentId The payment's ID. - * @param array $data An array containing details on the capture. - * @param array $filters - * - * @return Capture - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function createForId($paymentId, array $data = [], array $filters = []) - { - $this->parentId = $paymentId; - - return $this->rest_create($data, $filters); - } - - /** - * @param Payment $payment - * @param string $captureId - * @param array $parameters - * - * @return Capture - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function getFor(Payment $payment, $captureId, array $parameters = []) - { - return $this->getForId($payment->id, $captureId, $parameters); - } - - /** - * @param string $paymentId - * @param string $captureId - * @param array $parameters - * - * @return \Mollie\Api\Resources\Capture - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function getForId($paymentId, $captureId, array $parameters = []) - { - $this->parentId = $paymentId; - - return parent::rest_read($captureId, $parameters); - } - - /** - * @param Payment $payment - * @param array $parameters - * - * @return Capture - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function listFor(Payment $payment, array $parameters = []) - { - return $this->listForId($payment->id, $parameters); - } - - /** - * Create an iterator for iterating over captures for the given payment, retrieved from Mollie. - * - * @param Payment $payment - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iteratorFor(Payment $payment, ?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - return $this->iteratorForId($payment->id, $from, $limit, $parameters, $iterateBackwards); - } - - /** - * @param string $paymentId - * @param array $parameters - * - * @return \Mollie\Api\Resources\BaseCollection|\Mollie\Api\Resources\Capture - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function listForId($paymentId, array $parameters = []) - { - $this->parentId = $paymentId; - - return parent::rest_list(null, null, $parameters); - } - - /** - * Create an iterator for iterating over captures for the given payment id, retrieved from Mollie. - * - * @param string $paymentId - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iteratorForId(string $paymentId, ?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - $this->parentId = $paymentId; - - return $this->rest_iterator($from, $limit, $parameters, $iterateBackwards); - } -} diff --git a/src/Endpoints/PaymentChargebackEndpoint.php b/src/Endpoints/PaymentChargebackEndpoint.php deleted file mode 100644 index 5a232f889..000000000 --- a/src/Endpoints/PaymentChargebackEndpoint.php +++ /dev/null @@ -1,124 +0,0 @@ -client); - } - - /** - * Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return ChargebackCollection - */ - protected function getResourceCollectionObject($count, $_links) - { - return new ChargebackCollection($this->client, $count, $_links); - } - - /** - * @param Payment $payment - * @param string $chargebackId - * @param array $parameters - * - * @return Chargeback - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function getFor(Payment $payment, $chargebackId, array $parameters = []) - { - return $this->getForId($payment->id, $chargebackId, $parameters); - } - - /** - * @param string $paymentId - * @param string $chargebackId - * @param array $parameters - * - * @return Chargeback - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function getForId($paymentId, $chargebackId, array $parameters = []) - { - $this->parentId = $paymentId; - - return parent::rest_read($chargebackId, $parameters); - } - - /** - * @param Payment $payment - * @param array $parameters - * - * @return Chargeback - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function listFor(Payment $payment, array $parameters = []) - { - return $this->listForId($payment->id, $parameters); - } - - /** - * Create an iterator for iterating over chargebacks for the given payment, retrieved from Mollie. - * - * @param Payment $payment - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iteratorFor(Payment $payment, ?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - return $this->iteratorForId($payment->id, $from, $limit, $parameters, $iterateBackwards); - } - - /** - * @param string $paymentId - * @param array $parameters - * - * @return \Mollie\Api\Resources\BaseCollection|\Mollie\Api\Resources\Chargeback - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function listForId($paymentId, array $parameters = []) - { - $this->parentId = $paymentId; - - return parent::rest_list(null, null, $parameters); - } - - /** - * Create an iterator for iterating over chargebacks for the given payment id, retrieved from Mollie. - * - * @param string $paymentId - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iteratorForId(string $paymentId, ?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - $this->parentId = $paymentId; - - return $this->rest_iterator($from, $limit, $parameters, $iterateBackwards); - } -} diff --git a/src/Endpoints/PaymentEndpoint.php b/src/Endpoints/PaymentEndpoint.php deleted file mode 100644 index 79b1c6b6e..000000000 --- a/src/Endpoints/PaymentEndpoint.php +++ /dev/null @@ -1,184 +0,0 @@ -client); - } - - /** - * Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return PaymentCollection - */ - protected function getResourceCollectionObject($count, $_links) - { - return new PaymentCollection($this->client, $count, $_links); - } - - /** - * Creates a payment in Mollie. - * - * @param array $data An array containing details on the payment. - * @param array $filters - * - * @return Payment - * @throws ApiException - */ - public function create(array $data = [], array $filters = []) - { - return $this->rest_create($data, $filters); - } - - /** - * Update the given Payment. - * - * Will throw a ApiException if the payment id is invalid or the resource cannot be found. - * - * @param string $paymentId - * - * @param array $data - * @return Payment - * @throws ApiException - */ - public function update($paymentId, array $data = []) - { - if (empty($paymentId) || strpos($paymentId, self::RESOURCE_ID_PREFIX) !== 0) { - throw new ApiException("Invalid payment ID: '{$paymentId}'. A payment ID should start with '" . self::RESOURCE_ID_PREFIX . "'."); - } - - return parent::rest_update($paymentId, $data); - } - - /** - * Retrieve a single payment from Mollie. - * - * Will throw a ApiException if the payment id is invalid or the resource cannot be found. - * - * @param string $paymentId - * @param array $parameters - * @return Payment - * @throws ApiException - */ - public function get($paymentId, array $parameters = []) - { - if (empty($paymentId) || strpos($paymentId, self::RESOURCE_ID_PREFIX) !== 0) { - throw new ApiException("Invalid payment ID: '{$paymentId}'. A payment ID should start with '" . self::RESOURCE_ID_PREFIX . "'."); - } - - return parent::rest_read($paymentId, $parameters); - } - - /** - * Deletes the given Payment. - * - * Will throw a ApiException if the payment id is invalid or the resource cannot be found. - * Returns with HTTP status No Content (204) if successful. - * - * @param string $paymentId - * - * @param array $data - * @return Payment - * @throws ApiException - */ - public function delete($paymentId, array $data = []) - { - return $this->rest_delete($paymentId, $data); - } - - /** - * Cancel the given Payment. This is just an alias of the 'delete' method. - * - * Will throw a ApiException if the payment id is invalid or the resource cannot be found. - * Returns with HTTP status No Content (204) if successful. - * - * @param string $paymentId - * - * @param array $data - * @return Payment - * @throws ApiException - */ - public function cancel($paymentId, array $data = []) - { - return $this->rest_delete($paymentId, $data); - } - - /** - * Retrieves a collection of Payments from Mollie. - * - * @param string $from The first payment ID you want to include in your list. - * @param int $limit - * @param array $parameters - * - * @return PaymentCollection - * @throws ApiException - */ - public function page($from = null, $limit = null, array $parameters = []) - { - return $this->rest_list($from, $limit, $parameters); - } - - /** - * Create an iterator for iterating over payments retrieved from Mollie. - * - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iterator(?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - return $this->rest_iterator($from, $limit, $parameters, $iterateBackwards); - } - - /** - * Issue a refund for the given payment. - * - * The $data parameter may either be an array of endpoint parameters, a float value to - * initiate a partial refund, or empty to do a full refund. - * - * @param Payment $payment - * @param array|float|null $data - * - * @return Refund - * @throws ApiException - */ - public function refund(Payment $payment, $data = []) - { - $resource = "{$this->getResourcePath()}/" . urlencode($payment->id) . "/refunds"; - - $body = null; - if (($data === null ? 0 : count($data)) > 0) { - $body = json_encode($data); - } - - $result = $this->client->performHttpCall(self::REST_CREATE, $resource, $body); - - return ResourceFactory::createFromApiResult($result, new Refund($this->client)); - } -} diff --git a/src/Endpoints/PaymentLinkEndpoint.php b/src/Endpoints/PaymentLinkEndpoint.php deleted file mode 100644 index 9a19e0dcb..000000000 --- a/src/Endpoints/PaymentLinkEndpoint.php +++ /dev/null @@ -1,136 +0,0 @@ -rest_update($paymentLinkId, $data); - } - - /** - * Delete a Payment Link. - * - * @param string $paymentLinkId - * @param array $data - * @return void - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function delete(string $paymentLinkId, array $data = []) - { - if (empty($paymentLinkId) || strpos($paymentLinkId, self::RESOURCE_ID_PREFIX) !== 0) { - throw new ApiException("Invalid payment ID: '{$paymentLinkId}'. A Payment Link ID should start with '" . self::RESOURCE_ID_PREFIX . "'."); - } - - $this->rest_delete($paymentLinkId, $data); - } - - /** - * @return PaymentLink - */ - protected function getResourceObject() - { - return new PaymentLink($this->client); - } - - /** - * Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return PaymentLinkCollection - */ - protected function getResourceCollectionObject($count, $_links) - { - return new PaymentLinkCollection($this->client, $count, $_links); - } - - /** - * Creates a payment link in Mollie. - * - * @param array $data An array containing details on the payment link. - * @param array $filters - * - * @return PaymentLink - * @throws ApiException - */ - public function create(array $data = [], array $filters = []) - { - return $this->rest_create($data, $filters); - } - - /** - * Retrieve payment link from Mollie. - * - * Will throw a ApiException if the payment link id is invalid or the resource cannot be found. - * - * @param string $paymentLinkId - * @param array $parameters - * @return PaymentLink - * @throws ApiException - */ - public function get($paymentLinkId, array $parameters = []) - { - if (empty($paymentLinkId) || strpos($paymentLinkId, self::RESOURCE_ID_PREFIX) !== 0) { - throw new ApiException("Invalid payment link ID: '{$paymentLinkId}'. A payment link ID should start with '" . self::RESOURCE_ID_PREFIX . "'."); - } - - return parent::rest_read($paymentLinkId, $parameters); - } - - /** - * Retrieves a collection of Payment Links from Mollie. - * - * @param string $from The first payment link ID you want to include in your list. - * @param int $limit - * @param array $parameters - * - * @return PaymentLinkCollection - * @throws ApiException - */ - public function page($from = null, $limit = null, array $parameters = []) - { - return $this->rest_list($from, $limit, $parameters); - } - - /** - * Create an iterator for iterating over payment links retrieved from Mollie. - * - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iterator(?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - return $this->rest_iterator($from, $limit, $parameters, $iterateBackwards); - } -} diff --git a/src/Endpoints/PaymentLinkPaymentEndpoint.php b/src/Endpoints/PaymentLinkPaymentEndpoint.php deleted file mode 100644 index 034664393..000000000 --- a/src/Endpoints/PaymentLinkPaymentEndpoint.php +++ /dev/null @@ -1,93 +0,0 @@ -client, $count, $_links); - } - - /** - * @inheritDoc - */ - protected function getResourceObject() - { - return new Payment($this->client); - } - - public function pageForId(string $paymentLinkId, ?string $from = null, ?int $limit = null, array $filters = []) - { - $this->parentId = $paymentLinkId; - - return $this->rest_list($from, $limit, $filters); - } - - public function pageFor(PaymentLink $paymentLink, ?string $from = null, ?int $limit = null, array $filters = []) - { - return $this->pageForId($paymentLink->id, $from, $limit, $filters); - } - - /** - * Create an iterator for iterating over payments associated with the provided Payment Link id, retrieved from Mollie. - * - * @param string $paymentLinkId - * @param string|null $from The first resource ID you want to include in your list. - * @param int|null $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iteratorForId( - string $paymentLinkId, - ?string $from = null, - ?int $limit = null, - array $parameters = [], - bool $iterateBackwards = false - ): LazyCollection { - $this->parentId = $paymentLinkId; - - return $this->rest_iterator($from, $limit, $parameters, $iterateBackwards); - } - - /** - * Create an iterator for iterating over payments associated with the provided Payment Link object, retrieved from Mollie. - * - * @param PaymentLink $paymentLink - * @param string|null $from The first resource ID you want to include in your list. - * @param int|null $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iteratorFor( - PaymentLink $paymentLink, - ?string $from = null, - ?int $limit = null, - array $parameters = [], - bool $iterateBackwards = false - ): LazyCollection { - return $this->iteratorForId( - $paymentLink->id, - $from, - $limit, - $parameters, - $iterateBackwards - ); - } -} diff --git a/src/Endpoints/PaymentRefundEndpoint.php b/src/Endpoints/PaymentRefundEndpoint.php deleted file mode 100644 index 844330b7e..000000000 --- a/src/Endpoints/PaymentRefundEndpoint.php +++ /dev/null @@ -1,200 +0,0 @@ -client); - } - - /** - * Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return RefundCollection - */ - protected function getResourceCollectionObject($count, $_links) - { - return new RefundCollection($this->client, $count, $_links); - } - - /** - * @param Payment $payment - * @param string $refundId - * @param array $parameters - * - * @return Refund - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function getFor(Payment $payment, $refundId, array $parameters = []) - { - return $this->getForId($payment->id, $refundId, $parameters); - } - - /** - * @param string $paymentId - * @param string $refundId - * @param array $parameters - * - * @return \Mollie\Api\Resources\Refund - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function getForId($paymentId, $refundId, array $parameters = []) - { - $this->parentId = $paymentId; - - return parent::rest_read($refundId, $parameters); - } - - /** - * @param Payment $payment - * @param array $parameters - * - * @return Refund - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function listFor(Payment $payment, array $parameters = []) - { - return $this->listForId($payment->id, $parameters); - } - - /** - * Create an iterator for iterating over refunds for the given payment, retrieved from Mollie. - * - * @param Payment $payment - * @param string|null $from The first resource ID you want to include in your list. - * @param int|null $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iteratorFor(Payment $payment, ?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - return $this->iteratorForId($payment->id, $from, $limit, $parameters, $iterateBackwards); - } - - /** - * @param string $paymentId - * @param array $parameters - * - * @return \Mollie\Api\Resources\BaseCollection|\Mollie\Api\Resources\Refund - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function listForId($paymentId, array $parameters = []) - { - $this->parentId = $paymentId; - - return parent::rest_list(null, null, $parameters); - } - - /** - * Create an iterator for iterating over refunds for the given payment id, retrieved from Mollie. - * - * @param string $paymentId - * @param string|null $from The first resource ID you want to include in your list. - * @param int|null $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iteratorForId(string $paymentId, ?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - $this->parentId = $paymentId; - - return $this->rest_iterator($from, $limit, $parameters, $iterateBackwards); - } - - - /** - * Creates a refund for a specific payment. - * - * @param Payment $payment - * @param array $data - * @param array $filters - * - * @return Refund - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function createFor(Payment $payment, array $data, array $filters = []) - { - return $this->createForId($payment->id, $data, $filters); - } - - /** - * Creates a refund for a specific payment. - * - * @param string $paymentId - * @param array $data - * @param array $filters - * - * @return \Mollie\Api\Resources\Refund - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function createForId(string $paymentId, array $data, array $filters = []) - { - $this->parentId = $paymentId; - - return parent::rest_create($data, $filters); - } - - /** - * @param \Mollie\Api\Resources\Payment $payment - * @param string $refundId - * @param array $parameters - * @return null - * - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function cancelForPayment(Payment $payment, string $refundId, array $parameters = []) - { - $this->parentId = $payment->id; - - return $this->cancelForId($payment->id, $refundId, $parameters); - } - - /** - * @param string $paymentId - * @param string $refundId - * @param array $parameters - * @return null - * - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function cancelForId(string $paymentId, string $refundId, array $parameters = []) - { - $this->parentId = $paymentId; - - $body = null; - if (count($parameters) > 0) { - $body = json_encode($parameters); - } - - $this->client->performHttpCall( - EndpointAbstract::REST_DELETE, - $this->getResourcePath() . '/' . $refundId, - $body - ); - - $this->getResourcePath(); - - return null; - } -} diff --git a/src/Endpoints/PaymentRouteEndpoint.php b/src/Endpoints/PaymentRouteEndpoint.php deleted file mode 100644 index fc5c654cb..000000000 --- a/src/Endpoints/PaymentRouteEndpoint.php +++ /dev/null @@ -1,70 +0,0 @@ -client); - } - - /** - * Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return \Mollie\Api\Resources\RouteCollection - */ - protected function getResourceCollectionObject($count, $_links) - { - return new RouteCollection($this->client, $count, $_links); - } - - /** - * @param Payment $payment - * @param string $routeId - * @param string $releaseDate - UTC datetime in ISO-8601 format when the funds for the following payment will become available on - * the balance of the connected account - * - * @return Route - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function updateReleaseDateFor(Payment $payment, $routeId, $releaseDate) - { - return $this->updateReleaseDateForPaymentId($payment->id, $routeId, $releaseDate); - } - - /** - * @param string $paymentId - * @param string $routeId - * @param string $releaseDate - UTC datetime in ISO-8601 format when the funds for the following payment will become available on - * the balance of the connected account - * - * @return \Mollie\Api\Resources\Route - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function updateReleaseDateForPaymentId($paymentId, $routeId, $releaseDate, $testmode = false) - { - $this->parentId = $paymentId; - - $params = [ - 'releaseDate' => $releaseDate, - 'testmode' => $testmode, - ]; - - return parent::rest_update($routeId, $params); - } -} diff --git a/src/Endpoints/PermissionEndpoint.php b/src/Endpoints/PermissionEndpoint.php deleted file mode 100644 index fbe038204..000000000 --- a/src/Endpoints/PermissionEndpoint.php +++ /dev/null @@ -1,65 +0,0 @@ -client); - } - - /** - * Get the collection object that is used by this API endpoint. Every API - * endpoint uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return PermissionCollection - */ - protected function getResourceCollectionObject($count, $_links) - { - return new PermissionCollection($count, $_links); - } - - /** - * Retrieve a single Permission from Mollie. - * - * Will throw an ApiException if the permission id is invalid. - * - * @param string $permissionId - * @param array $parameters - * @return Permission - * @throws ApiException - */ - public function get($permissionId, array $parameters = []) - { - return $this->rest_read($permissionId, $parameters); - } - - /** - * Retrieve all permissions. - * - * @param array $parameters - * - * @return PermissionCollection - * @throws ApiException - */ - public function all(array $parameters = []) - { - return parent::rest_list(null, null, $parameters); - } -} diff --git a/src/Endpoints/ProfileEndpoint.php b/src/Endpoints/ProfileEndpoint.php deleted file mode 100644 index d430275c9..000000000 --- a/src/Endpoints/ProfileEndpoint.php +++ /dev/null @@ -1,159 +0,0 @@ -resourceClass($this->client); - } - - /** - * Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return ProfileCollection - */ - protected function getResourceCollectionObject($count, $_links) - { - return new ProfileCollection($this->client, $count, $_links); - } - - /** - * Creates a Profile in Mollie. - * - * @param array $data An array containing details on the profile. - * @param array $filters - * - * @return Profile - * @throws ApiException - */ - public function create(array $data = [], array $filters = []) - { - return $this->rest_create($data, $filters); - } - - /** - * Retrieve a Profile from Mollie. - * - * Will throw an ApiException if the profile id is invalid or the resource cannot be found. - * - * @param string $profileId - * @param array $parameters - * - * @return Profile - * @throws ApiException - */ - public function get($profileId, array $parameters = []) - { - if ($profileId === 'me') { - return $this->getCurrent($parameters); - } - - return $this->rest_read($profileId, $parameters); - } - - /** - * Update a specific Profile resource. - * - * Will throw an ApiException if the profile id is invalid or the resource cannot be found. - * - * @param string $profileId - * - * @param array $data - * @return Profile - * @throws ApiException - */ - public function update($profileId, array $data = []) - { - if (empty($profileId) || strpos($profileId, self::RESOURCE_ID_PREFIX) !== 0) { - throw new ApiException("Invalid profile id: '{$profileId}'. An profile id should start with '" . self::RESOURCE_ID_PREFIX . "'."); - } - - return parent::rest_update($profileId, $data); - } - - /** - * Retrieve the current Profile from Mollie. - * - * @param array $parameters - * - * @return CurrentProfile - * @throws ApiException - */ - public function getCurrent(array $parameters = []) - { - $this->resourceClass = CurrentProfile::class; - - return $this->rest_read('me', $parameters); - } - - /** - * Delete a Profile from Mollie. - * - * Will throw a ApiException if the profile id is invalid or the resource cannot be found. - * Returns with HTTP status No Content (204) if successful. - * - * @param string $profileId - * - * @param array $data - * @return Profile - * @throws ApiException - */ - public function delete($profileId, array $data = []) - { - return $this->rest_delete($profileId, $data); - } - - /** - * Retrieves a collection of Profiles from Mollie. - * - * @param string $from The first profile ID you want to include in your list. - * @param int $limit - * @param array $parameters - * - * @return ProfileCollection - * @throws ApiException - */ - public function page($from = null, $limit = null, array $parameters = []) - { - return $this->rest_list($from, $limit, $parameters); - } - - /** - * Create an iterator for iterating over profiles retrieved from Mollie. - * - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iterator(?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - return $this->rest_iterator($from, $limit, $parameters, $iterateBackwards); - } -} diff --git a/src/Endpoints/ProfileMethodEndpoint.php b/src/Endpoints/ProfileMethodEndpoint.php deleted file mode 100644 index 606d6141c..000000000 --- a/src/Endpoints/ProfileMethodEndpoint.php +++ /dev/null @@ -1,129 +0,0 @@ -client); - } - - /** - * Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return MethodCollection() - */ - protected function getResourceCollectionObject($count, $_links) - { - return new MethodCollection($count, $_links); - } - - /** - * Enable a method for the provided Profile ID. - * - * @param string $profileId - * @param string $methodId - * @param array $data - * @return \Mollie\Api\Resources\Method - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function createForId($profileId, $methodId, array $data = []) - { - $this->parentId = $profileId; - $resource = $this->getResourcePath() . '/' . urlencode($methodId); - - $body = null; - if (count($data) > 0) { - $body = json_encode($data); - } - - $result = $this->client->performHttpCall(self::REST_CREATE, $resource, $body); - - return ResourceFactory::createFromApiResult($result, new Method($this->client)); - } - - /** - * Enable a method for the provided Profile object. - * - * @param Profile $profile - * @param string $methodId - * @param array $data - * @return Method - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function createFor($profile, $methodId, array $data = []) - { - return $this->createForId($profile->id, $methodId, $data); - } - - /** - * Enable a method for the current profile. - * - * @param string $methodId - * @param array $data - * @return \Mollie\Api\Resources\Method - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function createForCurrentProfile($methodId, array $data = []) - { - return $this->createForId('me', $methodId, $data); - } - - /** - * Disable a method for the provided Profile ID. - * - * @param string $profileId - * @param string $methodId - * @param array $data - * @return mixed - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function deleteForId($profileId, $methodId, array $data = []) - { - $this->parentId = $profileId; - - return $this->rest_delete($methodId, $data); - } - - /** - * Disable a method for the provided Profile object. - * - * @param Profile $profile - * @param string $methodId - * @param array $data - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function deleteFor($profile, $methodId, array $data = []) - { - return $this->deleteForId($profile->id, $methodId, $data); - } - - /** - * Disable a method for the current profile. - * - * @param string $methodId - * @param array $data - * @return \Mollie\Api\Resources\Method - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function deleteForCurrentProfile($methodId, array $data) - { - return $this->deleteForId('me', $methodId, $data); - } -} diff --git a/src/Endpoints/RefundEndpoint.php b/src/Endpoints/RefundEndpoint.php deleted file mode 100644 index de03c477a..000000000 --- a/src/Endpoints/RefundEndpoint.php +++ /dev/null @@ -1,66 +0,0 @@ -client); - } - - /** - * Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return RefundCollection - */ - protected function getResourceCollectionObject($count, $_links) - { - return new RefundCollection($this->client, $count, $_links); - } - - /** - * Retrieves a collection of Refunds from Mollie. - * - * @param string $from The first refund ID you want to include in your list. - * @param int $limit - * @param array $parameters - * - * @return RefundCollection - * @throws ApiException - */ - public function page($from = null, $limit = null, array $parameters = []) - { - return $this->rest_list($from, $limit, $parameters); - } - - /** - * Create an iterator for iterating over refunds retrieved from Mollie. - * - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iterator(?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - return $this->rest_iterator($from, $limit, $parameters, $iterateBackwards); - } -} diff --git a/src/Endpoints/SessionEndpoint.php b/src/Endpoints/SessionEndpoint.php deleted file mode 100644 index 8f2d72ee8..000000000 --- a/src/Endpoints/SessionEndpoint.php +++ /dev/null @@ -1,139 +0,0 @@ -client); - } - - /** - * Get the collection object that is used by this API endpoint. Every API - * endpoint uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return SessionCollection - */ - protected function getResourceCollectionObject($count, $_links) - { - return new SessionCollection($this->client, $count, $_links); - } - - /** - * Creates a session in Mollie. - * - * @param array $data An array containing details on the session. - * @param array $filters - * - * @return Session - * @throws ApiException - */ - public function create(array $data = [], array $filters = []) - { - return $this->rest_create($data, $filters); - } - - /** - * Update a specific Session resource - * - * Will throw a ApiException if the resource id is invalid or the resource cannot be found. - * - * @param string $resourceId - * - * @param array $data - * @return Session - * @throws ApiException - */ - public function update($resourceId, array $data = []) - { - if (empty($resourceId) || strpos($resourceId, self::RESOURCE_ID_PREFIX) !== 0) { - throw new ApiException("Invalid session ID: '{$resourceId}'. A session ID should start with '" . self::RESOURCE_ID_PREFIX . "'."); - } - - return parent::rest_update($resourceId, $data); - } - - /** - * Retrieve a single session from Mollie. - * - * Will throw a ApiException if the resource id is invalid or the resource cannot - * be found. - * - * @param array $parameters - * @return Session - * @throws ApiException - */ - public function get($resourceId, array $parameters = []) - { - if (empty($resourceId) || strpos($resourceId, self::RESOURCE_ID_PREFIX) !== 0) { - throw new ApiException("Invalid session ID: '{$resourceId}'. A session ID should start with '" . self::RESOURCE_ID_PREFIX . "'."); - } - - return parent::rest_read($resourceId, $parameters); - } - - /** - * Cancel the given Session. - * - * @param string $resourceId - * @param array $parameters - * @return Session - * @throws ApiException - */ - public function cancel($resourceId, $parameters = []) - { - return $this->rest_delete($resourceId, $parameters); - } - - /** - * Retrieves a collection of Sessions from Mollie. - * - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * - * @return SessionCollection - * @throws ApiException - */ - public function page(?string $from = null, ?int $limit = null, array $parameters = []) - { - return $this->rest_list($from, $limit, $parameters); - } - - /** - * Create an iterator for iterating over sessions retrieved from Mollie. - * - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse resource iteration (default is false). - * - * @return LazyCollection - */ - public function iterator(?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - return $this->rest_iterator($from, $limit, $parameters, $iterateBackwards); - } -} diff --git a/src/Endpoints/SettlementCaptureEndpoint.php b/src/Endpoints/SettlementCaptureEndpoint.php deleted file mode 100644 index 553f7499b..000000000 --- a/src/Endpoints/SettlementCaptureEndpoint.php +++ /dev/null @@ -1,63 +0,0 @@ -client); - } - - protected function getResourceCollectionObject($count, $_links) - { - return new CaptureCollection($this->client, $count, $_links); - } - - /** - * Retrieves a collection of Settlement Captures from Mollie. - * - * @param string $settlementId - * @param string|null $from The first capture ID you want to include in your list. - * @param int|null $limit - * @param array $parameters - * - * @return mixed - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function pageForId(string $settlementId, ?string $from = null, ?int $limit = null, array $parameters = []) - { - $this->parentId = $settlementId; - - return $this->rest_list($from, $limit, $parameters); - } - - /** - * Create an iterator for iterating over captures for the given settlement id, retrieved from Mollie. - * - * @param string $settlementId - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iteratorForId(string $settlementId, ?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - $this->parentId = $settlementId; - - return $this->rest_iterator($from, $limit, $parameters, $iterateBackwards); - } -} diff --git a/src/Endpoints/SettlementChargebackEndpoint.php b/src/Endpoints/SettlementChargebackEndpoint.php deleted file mode 100644 index 3dd7b19fa..000000000 --- a/src/Endpoints/SettlementChargebackEndpoint.php +++ /dev/null @@ -1,66 +0,0 @@ -client); - } - - /** - * @inheritDoc - */ - protected function getResourceCollectionObject($count, $_links) - { - return new ChargebackCollection($this->client, $count, $_links); - } - - /** - * Retrieves a collection of Settlement Chargebacks from Mollie. - * - * @param string $settlementId - * @param string|null $from The first chargeback ID you want to include in your list. - * @param int|null $limit - * @param array $parameters - * - * @return mixed - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function pageForId(string $settlementId, ?string $from = null, ?int $limit = null, array $parameters = []) - { - $this->parentId = $settlementId; - - return $this->rest_list($from, $limit, $parameters); - } - - /** - * Create an iterator for iterating over chargeback for the given settlement id, retrieved from Mollie. - * - * @param string $settlementId - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iteratorForId(string $settlementId, ?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - $this->parentId = $settlementId; - - return $this->rest_iterator($from, $limit, $parameters, $iterateBackwards); - } -} diff --git a/src/Endpoints/SettlementPaymentEndpoint.php b/src/Endpoints/SettlementPaymentEndpoint.php deleted file mode 100644 index ed9b10b5f..000000000 --- a/src/Endpoints/SettlementPaymentEndpoint.php +++ /dev/null @@ -1,64 +0,0 @@ -client); - } - - /** - * @inheritDoc - */ - protected function getResourceCollectionObject($count, $_links) - { - return new PaymentCollection($this->client, $count, $_links); - } - - /** - * Retrieves a collection of Payments from Mollie. - * - * @param string $settlementId - * @param string $from The first payment ID you want to include in your list. - * @param int $limit - * @param array $parameters - * - * @return mixed - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function pageForId($settlementId, $from = null, $limit = null, array $parameters = []) - { - $this->parentId = $settlementId; - - return $this->rest_list($from, $limit, $parameters); - } - - /** - * Create an iterator for iterating over payments for the given settlement id, retrieved from Mollie. - * - * @param string $settlementId - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iteratorForId(string $settlementId, ?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - $this->parentId = $settlementId; - - return $this->rest_iterator($from, $limit, $parameters, $iterateBackwards); - } -} diff --git a/src/Endpoints/SettlementRefundEndpoint.php b/src/Endpoints/SettlementRefundEndpoint.php deleted file mode 100644 index 53d36d79a..000000000 --- a/src/Endpoints/SettlementRefundEndpoint.php +++ /dev/null @@ -1,66 +0,0 @@ -client, $count, $_links); - } - - /** - * @inheritDoc - */ - protected function getResourceObject() - { - return new Refund($this->client); - } - - /** - * Retrieves a collection of Settlement Refunds from Mollie. - * - * @param string $settlementId - * @param string|null $from The first refund ID you want to include in your list. - * @param int|null $limit - * @param array $parameters - * - * @return mixed - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function pageForId(string $settlementId, ?string $from = null, ?int $limit = null, array $parameters = []) - { - $this->parentId = $settlementId; - - return $this->rest_list($from, $limit, $parameters); - } - - /** - * Create an iterator for iterating over refunds for the given settlement id, retrieved from Mollie. - * - * @param string $settlementId - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iteratorForId(string $settlementId, ?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - $this->parentId = $settlementId; - - return $this->rest_iterator($from, $limit, $parameters, $iterateBackwards); - } -} diff --git a/src/Endpoints/SettlementsEndpoint.php b/src/Endpoints/SettlementsEndpoint.php deleted file mode 100644 index 76c7cad84..000000000 --- a/src/Endpoints/SettlementsEndpoint.php +++ /dev/null @@ -1,103 +0,0 @@ -client); - } - - /** - * Get the collection object that is used by this API. Every API uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return \Mollie\Api\Resources\BaseCollection - */ - protected function getResourceCollectionObject($count, $_links) - { - return new SettlementCollection($this->client, $count, $_links); - } - - /** - * Retrieve a single settlement from Mollie. - * - * Will throw a ApiException if the settlement id is invalid or the resource cannot be found. - * - * @param string $settlementId - * @param array $parameters - * @return Settlement - * @throws ApiException - */ - public function get($settlementId, array $parameters = []) - { - return parent::rest_read($settlementId, $parameters); - } - - /** - * Retrieve the details of the current settlement that has not yet been paid out. - * - * @return Settlement - * @throws ApiException - */ - public function next() - { - return parent::rest_read("next", []); - } - - /** - * Retrieve the details of the open balance of the organization. - * - * @return Settlement - * @throws ApiException - */ - public function open() - { - return parent::rest_read("open", []); - } - - /** - * Retrieves a collection of Settlements from Mollie. - * - * @param string $from The first settlement ID you want to include in your list. - * @param int $limit - * @param array $parameters - * - * @return SettlementCollection - * @throws ApiException - */ - public function page($from = null, $limit = null, array $parameters = []) - { - return $this->rest_list($from, $limit, $parameters); - } - - /** - * Create an iterator for iterating over settlements retrieved from Mollie. - * - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iterator(?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - return $this->rest_iterator($from, $limit, $parameters, $iterateBackwards); - } -} diff --git a/src/Endpoints/ShipmentEndpoint.php b/src/Endpoints/ShipmentEndpoint.php deleted file mode 100644 index c62bcb361..000000000 --- a/src/Endpoints/ShipmentEndpoint.php +++ /dev/null @@ -1,161 +0,0 @@ -client); - } - - /** - * Get the collection object that is used by this API endpoint. Every API - * endpoint uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return ShipmentCollection - */ - protected function getResourceCollectionObject($count, $_links) - { - return new ShipmentCollection($count, $_links); - } - - /** - * Create a shipment for some order lines. You can provide an empty array for the - * "lines" option to include all unshipped lines for this order. - * - * @param Order $order - * @param array $options - * @param array $filters - * - * @return Shipment - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function createFor(Order $order, array $options = [], array $filters = []) - { - return $this->createForId($order->id, $options, $filters); - } - - /** - * Create a shipment for some order lines. You can provide an empty array for the - * "lines" option to include all unshipped lines for this order. - * - * @param string $orderId - * @param array $options - * @param array $filters - * - * @return Shipment - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function createForId($orderId, array $options = [], array $filters = []) - { - $this->parentId = $orderId; - - return parent::rest_create($options, $filters); - } - - /** - * Retrieve a single shipment and the order lines shipped by a shipment’s ID. - * - * @param Order $order - * @param string $shipmentId - * @param array $parameters - * - * @return Shipment - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function getFor(Order $order, $shipmentId, array $parameters = []) - { - return $this->getForId($order->id, $shipmentId, $parameters); - } - - /** - * Retrieve a single shipment and the order lines shipped by a shipment’s ID. - * - * @param string $orderId - * @param string $shipmentId - * @param array $parameters - * - * @return \Mollie\Api\Resources\Shipment - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function getForId($orderId, $shipmentId, array $parameters = []) - { - $this->parentId = $orderId; - - return parent::rest_read($shipmentId, $parameters); - } - - /** - * Update a specific Order Shipment resource. - * - * Will throw an ApiException if the shipment id is invalid or the resource cannot be found. - * - * @param string $shipmentId - * @param string $orderId - * - * @param array $data - * @return Shipment - * @throws ApiException - */ - public function update($orderId, $shipmentId, array $data = []) - { - if (empty($shipmentId) || strpos($shipmentId, self::RESOURCE_ID_PREFIX) !== 0) { - throw new ApiException("Invalid subscription ID: '{$shipmentId}'. An subscription ID should start with '" . self::RESOURCE_ID_PREFIX . "'."); - } - - $this->parentId = $orderId; - - return parent::rest_update($shipmentId, $data); - } - - /** - * Return all shipments for the Order provided. - * - * @param Order $order - * @param array $parameters - * - * @return ShipmentCollection - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function listFor(Order $order, array $parameters = []) - { - return $this->listForId($order->id, $parameters); - } - - /** - * Return all shipments for the provided Order id. - * - * @param string $orderId - * @param array $parameters - * - * @return \Mollie\Api\Resources\ShipmentCollection - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function listForId($orderId, array $parameters = []) - { - $this->parentId = $orderId; - - return parent::rest_list(null, null, $parameters); - } -} diff --git a/src/Endpoints/SubscriptionEndpoint.php b/src/Endpoints/SubscriptionEndpoint.php deleted file mode 100644 index 4e6c4d9a0..000000000 --- a/src/Endpoints/SubscriptionEndpoint.php +++ /dev/null @@ -1,264 +0,0 @@ -client); - } - - /** - * Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return SubscriptionCollection - */ - protected function getResourceCollectionObject($count, $_links) - { - return new SubscriptionCollection($this->client, $count, $_links); - } - - /** - * Create a subscription for a Customer - * - * @param Customer $customer - * @param array $options - * @param array $filters - * - * @return Subscription - * @throws ApiException - */ - public function createFor(Customer $customer, array $options = [], array $filters = []) - { - return $this->createForId($customer->id, $options, $filters); - } - - /** - * Create a subscription for a Customer - * - * @param string $customerId - * @param array $options - * @param array $filters - * - * @return Subscription - * @throws ApiException - */ - public function createForId($customerId, array $options = [], array $filters = []) - { - $this->parentId = $customerId; - - return parent::rest_create($options, $filters); - } - - /** - * Update a specific Subscription resource. - * - * Will throw an ApiException if the subscription id is invalid or the resource cannot be found. - * - * @param string $subscriptionId - * @param string $customerId - * - * @param array $data - * - * @return Subscription - * @throws ApiException - */ - public function update($customerId, $subscriptionId, array $data = []) - { - if (empty($subscriptionId) || strpos($subscriptionId, self::RESOURCE_ID_PREFIX) !== 0) { - throw new ApiException("Invalid subscription ID: '{$subscriptionId}'. An subscription ID should start with '" . self::RESOURCE_ID_PREFIX . "'."); - } - - $this->parentId = $customerId; - - return parent::rest_update($subscriptionId, $data); - } - - /** - * @param Customer $customer - * @param string $subscriptionId - * @param array $parameters - * - * @return Subscription - * @throws ApiException - */ - public function getFor(Customer $customer, $subscriptionId, array $parameters = []) - { - return $this->getForId($customer->id, $subscriptionId, $parameters); - } - - /** - * @param string $customerId - * @param string $subscriptionId - * @param array $parameters - * - * @return Subscription - * @throws ApiException - */ - public function getForId($customerId, $subscriptionId, array $parameters = []) - { - $this->parentId = $customerId; - - return parent::rest_read($subscriptionId, $parameters); - } - - /** - * @param Customer $customer - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * - * @return SubscriptionCollection - * @throws ApiException - */ - public function listFor(Customer $customer, $from = null, $limit = null, array $parameters = []) - { - return $this->listForId($customer->id, $from, $limit, $parameters); - } - - /** - * Create an iterator for iterating over subscriptions for the given customer, retrieved from Mollie. - * - * @param Customer $customer - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iteratorFor(Customer $customer, ?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - return $this->iteratorForId($customer->id, $from, $limit, $parameters, $iterateBackwards); - } - - /** - * @param string $customerId - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * - * @return SubscriptionCollection - * @throws ApiException - */ - public function listForId($customerId, $from = null, $limit = null, array $parameters = []) - { - $this->parentId = $customerId; - - return parent::rest_list($from, $limit, $parameters); - } - - /** - * Create an iterator for iterating over subscriptions for the given customer id, retrieved from Mollie. - * - * @param string $customerId - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iteratorForId(string $customerId, ?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - $this->parentId = $customerId; - - return $this->rest_iterator($from, $limit, $parameters, $iterateBackwards); - } - - /** - * @param Customer $customer - * @param string $subscriptionId - * @param array $data - * - * @return Subscription - * @throws ApiException - */ - public function cancelFor(Customer $customer, $subscriptionId, array $data = []) - { - return $this->cancelForId($customer->id, $subscriptionId, $data); - } - - /** - * @param string $customerId - * @param string $subscriptionId - * @param array $data - * - * @return Subscription - * @throws ApiException - */ - public function cancelForId($customerId, $subscriptionId, array $data = []) - { - $this->parentId = $customerId; - - return parent::rest_delete($subscriptionId, $data); - } - - /** - * Retrieves a collection of Subscriptions from Mollie. - * - * @param string $from The first payment ID you want to include in your list. - * @param int $limit - * @param array $parameters - * - * @return SubscriptionCollection - * @throws ApiException - */ - public function page($from = null, $limit = null, array $parameters = []) - { - $filters = array_merge(["from" => $from, "limit" => $limit], $parameters); - - $apiPath = 'subscriptions' . $this->buildQueryString($filters); - - $result = $this->client->performHttpCall(self::REST_LIST, $apiPath); - - /** @var SubscriptionCollection $collection */ - $collection = $this->getResourceCollectionObject($result->count, $result->_links); - - foreach ($result->_embedded->{$collection->getCollectionResourceName()} as $dataResult) { - $collection[] = ResourceFactory::createFromApiResult($dataResult, $this->getResourceObject()); - } - - return $collection; - } - - /** - * Create an iterator for iterating over subscriptions retrieved from Mollie. - * - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iterator(?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - $page = $this->page($from, $limit, $parameters); - - return $page->getAutoIterator($iterateBackwards); - } -} diff --git a/src/Endpoints/SubscriptionPaymentEndpoint.php b/src/Endpoints/SubscriptionPaymentEndpoint.php deleted file mode 100644 index b65e0682a..000000000 --- a/src/Endpoints/SubscriptionPaymentEndpoint.php +++ /dev/null @@ -1,79 +0,0 @@ -customerId = $customerId; - $this->subscriptionId = $subscriptionId; - - return $this->rest_list($from, $limit, $parameters); - } - - /** - * Get the object that is used by this API endpoint. Every API endpoint uses one type of object. - * - * @return Payment - */ - protected function getResourceObject() - { - return new Payment($this->client); - } - - /** - * Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return PaymentCollection - */ - protected function getResourceCollectionObject($count, $_links) - { - return new PaymentCollection($this->client, $count, $_links); - } - - public function getResourcePath() - { - if (is_null($this->customerId)) { - throw new ApiException('No customerId provided.'); - } - - if (is_null($this->subscriptionId)) { - throw new ApiException('No subscriptionId provided.'); - } - - return "customers/{$this->customerId}/subscriptions/{$this->subscriptionId}/payments"; - } -} diff --git a/src/Endpoints/TerminalEndpoint.php b/src/Endpoints/TerminalEndpoint.php deleted file mode 100644 index 4f7a65c62..000000000 --- a/src/Endpoints/TerminalEndpoint.php +++ /dev/null @@ -1,88 +0,0 @@ -client); - } - - /** - * Get the collection object that is used by this API endpoint. Every API endpoint uses one type of collection object. - * - * @param int $count - * @param \stdClass $_links - * - * @return TerminalCollection - */ - protected function getResourceCollectionObject($count, $_links) - { - return new TerminalCollection($this->client, $count, $_links); - } - - /** - * Retrieve terminal from Mollie. - * - * Will throw a ApiException if the terminal id is invalid or the resource cannot be found. - * - * @param string $terminalId - * @param array $parameters - * @return Terminal - * @throws ApiException - */ - public function get($terminalId, array $parameters = []) - { - if (empty($terminalId) || strpos($terminalId, self::RESOURCE_ID_PREFIX) !== 0) { - throw new ApiException("Invalid terminal ID: '{$terminalId}'. A terminal ID should start with '" . self::RESOURCE_ID_PREFIX . "'."); - } - - return parent::rest_read($terminalId, $parameters); - } - - /** - * Retrieves a collection of Terminals from Mollie for the current organization / profile, ordered from newest to oldest. - * - * @param string $from The first terminal ID you want to include in your list. - * @param int $limit - * @param array $parameters - * - * @return TerminalCollection - * @throws ApiException - */ - public function page($from = null, $limit = null, array $parameters = []) - { - return $this->rest_list($from, $limit, $parameters); - } - - /** - * Create an iterator for iterating over terminals retrieved from Mollie. - * - * @param string $from The first resource ID you want to include in your list. - * @param int $limit - * @param array $parameters - * @param bool $iterateBackwards Set to true for reverse order iteration (default is false). - * - * @return LazyCollection - */ - public function iterator(?string $from = null, ?int $limit = null, array $parameters = [], bool $iterateBackwards = false): LazyCollection - { - return $this->rest_iterator($from, $limit, $parameters, $iterateBackwards); - } -} diff --git a/src/Endpoints/WalletEndpoint.php b/src/Endpoints/WalletEndpoint.php deleted file mode 100644 index 628aaebde..000000000 --- a/src/Endpoints/WalletEndpoint.php +++ /dev/null @@ -1,44 +0,0 @@ -parseRequestBody(array_merge([ - 'domain' => $domain, - 'validationUrl' => $validationUrl, - ], $parameters)); - - $response = $this->client->performHttpCall( - self::REST_CREATE, - 'wallets/applepay/sessions', - $body - ); - - return json_encode($response); - } -} diff --git a/src/Exceptions/ApiException.php b/src/Exceptions/ApiException.php index dc619db6e..6b4bbdb49 100644 --- a/src/Exceptions/ApiException.php +++ b/src/Exceptions/ApiException.php @@ -2,68 +2,48 @@ namespace Mollie\Api\Exceptions; -use DateTime; +use DateTimeImmutable; +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; +use Throwable; class ApiException extends \Exception { - /** - * @var string - */ - protected $field; + protected ?string $field = null; - /** - * @var string - */ - protected $plainMessage; + protected string $plainMessage; - /** - * @var \Psr\Http\Message\RequestInterface|null - */ - protected $request; + protected ?RequestInterface $request; - /** - * @var \Psr\Http\Message\ResponseInterface|null - */ - protected $response; + protected ?ResponseInterface $response; /** * ISO8601 representation of the moment this exception was thrown - * - * @var \DateTimeImmutable */ - protected $raisedAt; + protected \DateTimeImmutable $raisedAt; - /** - * @var array - */ - protected $links = []; + protected array $links = []; /** - * @param string $message - * @param int $code - * @param string|null $field - * @param \Psr\Http\Message\RequestInterface|null $request - * @param \Psr\Http\Message\ResponseInterface|null $response - * @param \Throwable|null $previous - * @throws \Mollie\Api\Exceptions\ApiException + * @throws ApiException */ public function __construct( - $message = "", - $code = 0, - $field = null, - $request = null, - $response = null, - $previous = null + string $message = '', + int $code = 0, + ?string $field = null, + ?RequestInterface $request = null, + ?ResponseInterface $response = null, + ?Throwable $previous = null ) { $this->plainMessage = $message; - $this->raisedAt = new \DateTimeImmutable(); + $this->raisedAt = new DateTimeImmutable; - $formattedRaisedAt = $this->raisedAt->format(DateTime::ISO8601); - $message = "[{$formattedRaisedAt}] " . $message; + $formattedRaisedAt = $this->raisedAt->format(DateTimeImmutable::ATOM); + $message = "[{$formattedRaisedAt}] ".$message; if (! empty($field)) { - $this->field = (string)$field; + $this->field = (string) $field; $message .= ". Field: {$this->field}"; } @@ -95,86 +75,43 @@ public function __construct( parent::__construct($message, $code, $previous); } - /** - * @param \Psr\Http\Message\ResponseInterface $response - * @param \Psr\Http\Message\RequestInterface $request - * @param \Throwable|null $previous - * @return \Mollie\Api\Exceptions\ApiException - * @throws \Mollie\Api\Exceptions\ApiException - */ - public static function createFromResponse($response, $request = null, $previous = null) - { - $object = static::parseResponseBody($response); - - $field = null; - if (! empty($object->field)) { - $field = $object->field; - } - - return new self( - "Error executing API call ({$object->status}: {$object->title}): {$object->detail}", - $response->getStatusCode(), - $field, - $request, - $response, - $previous - ); - } - - /** - * @return string|null - */ - public function getField() + public function getField(): ?string { return $this->field; } - /** - * @return string|null - */ - public function getDocumentationUrl() + public function getDocumentationUrl(): ?string { return $this->getUrl('documentation'); } - /** - * @return string|null - */ - public function getDashboardUrl() + public function getDashboardUrl(): ?string { return $this->getUrl('dashboard'); } - /** - * @return \Psr\Http\Message\ResponseInterface|null - */ - public function getResponse() + public function getResponse(): ?ResponseInterface { return $this->response; } - /** - * @return bool - */ - public function hasResponse() + public function hasResponse(): bool { - return $this->response !== null; + return (bool) $this->response; } /** - * @param string $key - * @return bool + * @param string $key */ - public function hasLink($key) + public function hasLink($key): bool { return array_key_exists($key, $this->links); } /** - * @param string $key - * @return mixed|null + * @param string $key */ - public function getLink($key) + public function getLink($key): ?\stdClass { if ($this->hasLink($key)) { return $this->links[$key]; @@ -184,10 +121,9 @@ public function getLink($key) } /** - * @param string $key - * @return null + * @param string $key */ - public function getUrl($key) + public function getUrl($key): ?string { if ($this->hasLink($key)) { return $this->getLink($key)->href; @@ -196,30 +132,25 @@ public function getUrl($key) return null; } - /** - * @return \Psr\Http\Message\RequestInterface - */ - public function getRequest() + public function getRequest(): ?RequestInterface { return $this->request; } /** * Get the ISO8601 representation of the moment this exception was thrown - * - * @return \DateTimeImmutable */ - public function getRaisedAt() + public function getRaisedAt(): DateTimeImmutable { return $this->raisedAt; } /** - * @param \Psr\Http\Message\ResponseInterface $response - * @return \stdClass - * @throws \Mollie\Api\Exceptions\ApiException + * @param ResponseInterface $response + * + * @throws ApiException */ - protected static function parseResponseBody($response) + protected static function parseResponseBody($response): \stdClass { $body = (string) $response->getBody(); @@ -234,10 +165,8 @@ protected static function parseResponseBody($response) /** * Retrieve the plain exception message. - * - * @return string */ - public function getPlainMessage() + public function getPlainMessage(): string { return $this->plainMessage; } diff --git a/src/Exceptions/CurlConnectTimeoutException.php b/src/Exceptions/CurlConnectTimeoutException.php index ab40ca1bc..8b011d5c1 100644 --- a/src/Exceptions/CurlConnectTimeoutException.php +++ b/src/Exceptions/CurlConnectTimeoutException.php @@ -2,6 +2,4 @@ namespace Mollie\Api\Exceptions; -class CurlConnectTimeoutException extends ApiException -{ -} +class CurlConnectTimeoutException extends ApiException {} diff --git a/src/Exceptions/EmbeddedResourcesNotParseableException.php b/src/Exceptions/EmbeddedResourcesNotParseableException.php new file mode 100644 index 000000000..611d7fccf --- /dev/null +++ b/src/Exceptions/EmbeddedResourcesNotParseableException.php @@ -0,0 +1,5 @@ +get('domain'), + $this->get('validationUrl'), + $this->get('profileId'), + ); + } +} diff --git a/src/Factories/ApplicationFeeFactory.php b/src/Factories/ApplicationFeeFactory.php new file mode 100644 index 000000000..2abf7b9fd --- /dev/null +++ b/src/Factories/ApplicationFeeFactory.php @@ -0,0 +1,16 @@ +data['amount'])->create(), + $this->data['description'], + ); + } +} diff --git a/src/Factories/CreateClientLinkPayloadFactory.php b/src/Factories/CreateClientLinkPayloadFactory.php new file mode 100644 index 000000000..c8058b452 --- /dev/null +++ b/src/Factories/CreateClientLinkPayloadFactory.php @@ -0,0 +1,21 @@ +get('owner')), + $this->get('name'), + OwnerAddress::fromArray($this->get('address')), + $this->get('registrationNumber'), + $this->get('vatNumber') + ); + } +} diff --git a/src/Factories/CreateCustomerPayloadFactory.php b/src/Factories/CreateCustomerPayloadFactory.php new file mode 100644 index 000000000..6390452b8 --- /dev/null +++ b/src/Factories/CreateCustomerPayloadFactory.php @@ -0,0 +1,19 @@ +get('name'), + $this->get('email'), + $this->get('locale'), + $this->mapIfNotNull('metadata', Metadata::class), + ); + } +} diff --git a/src/Factories/CreateMandatePayloadFactory.php b/src/Factories/CreateMandatePayloadFactory.php new file mode 100644 index 000000000..b339b6cd9 --- /dev/null +++ b/src/Factories/CreateMandatePayloadFactory.php @@ -0,0 +1,27 @@ +has(['method', 'consumerName'])) { + throw new \InvalidArgumentException('Method and consumerName are required for creating a mandate'); + } + + return new CreateMandatePayload( + $this->get('method'), + $this->get('consumerName'), + $this->get('consumerAccount'), + $this->get('consumerBic'), + $this->get('consumerEmail'), + $this->mapIfNotNull('signatureDate', fn (string $date) => DateTimeImmutable::createFromFormat('Y-m-d', $date)), + $this->get('mandateReference'), + $this->get('paypalBillingAgreementId'), + ); + } +} diff --git a/src/Factories/CreatePaymentCapturePayloadFactory.php b/src/Factories/CreatePaymentCapturePayloadFactory.php new file mode 100644 index 000000000..2e207dcca --- /dev/null +++ b/src/Factories/CreatePaymentCapturePayloadFactory.php @@ -0,0 +1,18 @@ +get('description'), + $this->mapIfNotNull('amount', fn (array $item) => MoneyFactory::new($item)->create()), + $this->mapIfNotNull('metadata', Metadata::class) + ); + } +} diff --git a/src/Factories/CreatePaymentLinkPayloadFactory.php b/src/Factories/CreatePaymentLinkPayloadFactory.php new file mode 100644 index 000000000..9c6eed9c7 --- /dev/null +++ b/src/Factories/CreatePaymentLinkPayloadFactory.php @@ -0,0 +1,21 @@ +get('description'), + $this->mapIfNotNull('amount', fn (array $amount) => MoneyFactory::new($amount)->create()), + $this->get('redirectUrl'), + $this->get('webhookUrl'), + $this->get('profileId'), + $this->get('reusable'), + $this->get('expiresAt'), + ); + } +} diff --git a/src/Factories/CreatePaymentPayloadFactory.php b/src/Factories/CreatePaymentPayloadFactory.php new file mode 100644 index 000000000..c9aeaeca6 --- /dev/null +++ b/src/Factories/CreatePaymentPayloadFactory.php @@ -0,0 +1,49 @@ +get('description'), + MoneyFactory::new($this->get('amount'))->create(), + $this->get('redirectUrl'), + $this->get('cancelUrl'), + $this->get('webhookUrl'), + $this + ->mapIfNotNull( + 'lines', + fn (array $items) => OrderLineCollectionFactory::new($items)->create() + ), + $this->mapIfNotNull('billingAddress', fn (array $item) => Address::fromArray($item)), + $this->mapIfNotNull('shippingAddress', fn (array $item) => Address::fromArray($item)), + $this->get('locale'), + $this->get('method'), + $this->get('issuer'), + $this->get('restrictPaymentMethodsToCountry'), + $this->mapIfNotNull('metadata', Metadata::class), + $this->get('captureMode'), + $this->get('captureDelay'), + $this->mapIfNotNull( + 'applicationFee', + fn (array $item) => ApplicationFeeFactory::new($item)->create() + ), + $this->mapIfNotNull( + 'routing', + fn (array $items) => PaymentRouteCollectionFactory::new($items)->create() + ), + $this->get('sequenceType'), + $this->get('mandateId'), + $this->get('customerId'), + $this->get('profileId'), + $this->get('additional') ?? Utility::filterByProperties(CreatePaymentPayload::class, $this->data), + ); + } +} diff --git a/src/Factories/CreateProfilePayloadFactory.php b/src/Factories/CreateProfilePayloadFactory.php new file mode 100644 index 000000000..c0357b5fd --- /dev/null +++ b/src/Factories/CreateProfilePayloadFactory.php @@ -0,0 +1,21 @@ +get('name'), + $this->get('website'), + $this->get('email'), + $this->get('phone'), + $this->get('description'), + $this->get('countriesOfActivity'), + $this->get('businessCategory') + ); + } +} diff --git a/src/Factories/CreateRefundPaymentPayloadFactory.php b/src/Factories/CreateRefundPaymentPayloadFactory.php new file mode 100644 index 000000000..42e561847 --- /dev/null +++ b/src/Factories/CreateRefundPaymentPayloadFactory.php @@ -0,0 +1,24 @@ +get('description'), + MoneyFactory::new($this->data['amount'])->create(), + $this->mapIfNotNull('metadata', Metadata::class), + $this->get('reverseRouting'), + $this + ->mapIfNotNull( + 'routingReversals', + fn (array $items) => RefundRouteCollectionFactory::new($items)->create() + ), + ); + } +} diff --git a/src/Factories/CreateSalesInvoicePayloadFactory.php b/src/Factories/CreateSalesInvoicePayloadFactory.php new file mode 100644 index 000000000..3d7eeb857 --- /dev/null +++ b/src/Factories/CreateSalesInvoicePayloadFactory.php @@ -0,0 +1,38 @@ +get('currency'), + $this->get('status'), + $this->get('vatScheme'), + $this->get('vatMode'), + $this->get('paymentTerm'), + $this->get('recipientIdentifier'), + RecipientFactory::new($this->get('recipient'))->create(), + $this + ->mapIfNotNull( + 'lines', + fn (array $items) => InvoiceLineCollectionFactory::new($items)->create() + ), + $this->get('profileId'), + $this->get('memo'), + $this->mapIfNotNull('paymentDetails', fn (array $data) => PaymentDetails::fromArray($data)), + $this->mapIfNotNull('emailDetails', fn (array $data) => EmailDetails::fromArray($data)), + $this->get('webhookUrl'), + $this->mapIfNotNull('discount', fn (array $data) => Discount::fromArray($data)) + ); + } +} diff --git a/src/Factories/CreateSubscriptionPayloadFactory.php b/src/Factories/CreateSubscriptionPayloadFactory.php new file mode 100644 index 000000000..27e7a3721 --- /dev/null +++ b/src/Factories/CreateSubscriptionPayloadFactory.php @@ -0,0 +1,28 @@ +get('amount'))->create(), + $this->get('interval'), + $this->get('description'), + $this->get('status'), + $this->get('times'), + $this->mapIfNotNull('startDate', fn (string $date) => DateTimeImmutable::createFromFormat('Y-m-d', $date)), + $this->get('method'), + $this->mapIfNotNull('applicationFee', fn (array $fee) => ApplicationFeeFactory::new($fee)->create()), + $this->mapIfNotNull('metadata', Metadata::class), + $this->get('webhookUrl'), + $this->get('mandateId'), + $this->get('profileId'), + ); + } +} diff --git a/src/Factories/Factory.php b/src/Factories/Factory.php new file mode 100644 index 000000000..0ac9262de --- /dev/null +++ b/src/Factories/Factory.php @@ -0,0 +1,78 @@ +data = $data->toArray(); + } else { + $this->data = $data; + } + } + + public static function new($data): self + { + /** @phpstan-ignore-next-line */ + return new static($data); + } + + /** + * Get a value from the data array or the backup key. + * + * @param string|array $key + * @param mixed $default + */ + protected function get($key, $default = null, $backupKey = 'filters.') + { + $keys = (array) $key; + + if ($backupKey !== null) { + $keys[] = $backupKey.$key; + } + + foreach ($keys as $key) { + if ($value = Arr::get($this->data, $key, $default)) { + return $value; + } + } + + return $default; + } + + protected function has($keys): bool + { + return Arr::has($this->data, $keys); + } + + /** + * @param string|array $key + * @param mixed $value + */ + protected function includes($key, $value, $backupKey = 'filters.'): bool + { + return Arr::includes($this->data, [$backupKey.$key, $key], $value); + } + + /** + * Map a value to a new form if it is not null. + * + * @param string|array $key The key to retrieve the value from the data array. + * @param callable|string $composable A callable function to transform the value, or the name of a class to instantiate. + * @param string $backupKey The key to retrieve the value from the data array if the first key is null. + * @return mixed The transformed value, a new class instance, or null if the value is null. + */ + protected function mapIfNotNull($key, $composable, $backupKey = 'filters.') + { + return Utility::compose($this->get($key, null, $backupKey), $composable); + } +} diff --git a/src/Factories/GetAllPaginatedSubscriptionsQueryFactory.php b/src/Factories/GetAllPaginatedSubscriptionsQueryFactory.php new file mode 100644 index 000000000..23837a335 --- /dev/null +++ b/src/Factories/GetAllPaginatedSubscriptionsQueryFactory.php @@ -0,0 +1,19 @@ + $this->get('from'), + 'limit' => $this->get('limit'), + ])->create(), + $this->get('profileId') + ); + } +} diff --git a/src/Factories/GetAllPaymentMethodsQueryFactory.php b/src/Factories/GetAllPaymentMethodsQueryFactory.php new file mode 100644 index 000000000..eba8e55f2 --- /dev/null +++ b/src/Factories/GetAllPaymentMethodsQueryFactory.php @@ -0,0 +1,22 @@ +includes('include', MethodQuery::INCLUDE_ISSUERS); + $includePricing = $this->includes('include', MethodQuery::INCLUDE_PRICING); + + return new GetAllMethodsQuery( + $this->get('includeIssuers', $includeIssuers), + $this->get('includePricing', $includePricing), + $this->get('locale'), + $this->mapIfNotNull('amount', MoneyFactory::class) + ); + } +} diff --git a/src/Factories/GetBalanceReportQueryFactory.php b/src/Factories/GetBalanceReportQueryFactory.php new file mode 100644 index 000000000..f0da20016 --- /dev/null +++ b/src/Factories/GetBalanceReportQueryFactory.php @@ -0,0 +1,22 @@ +has(['from', 'until'])) { + throw new \InvalidArgumentException('The "from" and "until" fields are required.'); + } + + return new GetBalanceReportQuery( + DateTimeImmutable::createFromFormat('Y-m-d', $this->get('from')), + DateTimeImmutable::createFromFormat('Y-m-d', $this->get('until')), + $this->get('grouping'), + ); + } +} diff --git a/src/Factories/GetClientQueryFactory.php b/src/Factories/GetClientQueryFactory.php new file mode 100644 index 000000000..7e8e47c4d --- /dev/null +++ b/src/Factories/GetClientQueryFactory.php @@ -0,0 +1,20 @@ +includes('embed', ClientQuery::EMBED_ORGANIZATION); + $embedOnboarding = $this->includes('embed', ClientQuery::EMBED_ONBOARDING); + + return new GetClientQuery( + $this->get('embedOrganization', $embedOrganization), + $this->get('embedOnboarding', $embedOnboarding), + ); + } +} diff --git a/src/Factories/GetEnabledPaymentMethodsQueryFactory.php b/src/Factories/GetEnabledPaymentMethodsQueryFactory.php new file mode 100644 index 000000000..073ba2990 --- /dev/null +++ b/src/Factories/GetEnabledPaymentMethodsQueryFactory.php @@ -0,0 +1,29 @@ +includes('include', MethodQuery::INCLUDE_ISSUERS); + $includePricing = $this->includes('include', MethodQuery::INCLUDE_PRICING); + + return new GetEnabledPaymentMethodsQuery( + $this->get('sequenceType', SequenceType::ONEOFF), + $this->get('resource', MethodQuery::RESOURCE_PAYMENTS), + $this->get('locale'), + $this->mapIfNotNull('amount', fn (array $item) => MoneyFactory::new($item)->create()), + $this->get('billingCountry'), + $this->get('includeWallets'), + $this->get('orderLineCategories', []), + $this->get('profileId'), + $this->get('includeIssuers', $includeIssuers), + $this->get('includePricing', $includePricing), + ); + } +} diff --git a/src/Factories/GetPaginatedBalanceQueryFactory.php b/src/Factories/GetPaginatedBalanceQueryFactory.php new file mode 100644 index 000000000..438e0e8f1 --- /dev/null +++ b/src/Factories/GetPaginatedBalanceQueryFactory.php @@ -0,0 +1,16 @@ +data)->create(), + $this->get('currency') + ); + } +} diff --git a/src/Factories/GetPaginatedChargebackQueryFactory.php b/src/Factories/GetPaginatedChargebackQueryFactory.php new file mode 100644 index 000000000..9823d81af --- /dev/null +++ b/src/Factories/GetPaginatedChargebackQueryFactory.php @@ -0,0 +1,17 @@ +data)->create(), + $this->get('includePayment', false), + $this->get('profileId') + ); + } +} diff --git a/src/Factories/GetPaginatedClientQueryFactory.php b/src/Factories/GetPaginatedClientQueryFactory.php new file mode 100644 index 000000000..214b32629 --- /dev/null +++ b/src/Factories/GetPaginatedClientQueryFactory.php @@ -0,0 +1,21 @@ +includes('embed', ClientQuery::EMBED_ORGANIZATION); + $embedOnboarding = $this->includes('embed', ClientQuery::EMBED_ONBOARDING); + + return new GetPaginatedClientQuery( + PaginatedQueryFactory::new($this->data)->create(), + $this->get('embedOrganization', $embedOrganization), + $this->get('embedOnboarding', $embedOnboarding), + ); + } +} diff --git a/src/Factories/GetPaginatedCustomerPaymentsQueryFactory.php b/src/Factories/GetPaginatedCustomerPaymentsQueryFactory.php new file mode 100644 index 000000000..1317452eb --- /dev/null +++ b/src/Factories/GetPaginatedCustomerPaymentsQueryFactory.php @@ -0,0 +1,16 @@ +data)->create(), + $this->get('profileId') + ); + } +} diff --git a/src/Factories/GetPaginatedInvoiceQueryFactory.php b/src/Factories/GetPaginatedInvoiceQueryFactory.php new file mode 100644 index 000000000..c7cb97481 --- /dev/null +++ b/src/Factories/GetPaginatedInvoiceQueryFactory.php @@ -0,0 +1,20 @@ +get('filters.reference'); + $year = $this->get('filters.year'); + + return new GetPaginatedInvoiceQuery( + PaginatedQueryFactory::new($this->data)->create(), + $this->get('reference', $reference), + $this->get('year', $year) + ); + } +} diff --git a/src/Factories/GetPaginatedPaymentCapturesQueryFactory.php b/src/Factories/GetPaginatedPaymentCapturesQueryFactory.php new file mode 100644 index 000000000..eff146b1d --- /dev/null +++ b/src/Factories/GetPaginatedPaymentCapturesQueryFactory.php @@ -0,0 +1,19 @@ +includes('include', PaymentIncludesQuery::PAYMENT); + + return new GetPaginatedPaymentCapturesQuery( + PaginatedQueryFactory::new($this->data)->create(), + $this->get('includePayments', $includePayments) + ); + } +} diff --git a/src/Factories/GetPaginatedPaymentChargebacksQueryFactory.php b/src/Factories/GetPaginatedPaymentChargebacksQueryFactory.php new file mode 100644 index 000000000..47998792e --- /dev/null +++ b/src/Factories/GetPaginatedPaymentChargebacksQueryFactory.php @@ -0,0 +1,19 @@ +includes('include', PaymentIncludesQuery::PAYMENT); + + return new GetPaginatedPaymentChargebacksQuery( + PaginatedQueryFactory::new($this->data)->create(), + $this->get('includePayment', $includePayment), + ); + } +} diff --git a/src/Factories/GetPaginatedPaymentRefundQueryFactory.php b/src/Factories/GetPaginatedPaymentRefundQueryFactory.php new file mode 100644 index 000000000..ecc44959d --- /dev/null +++ b/src/Factories/GetPaginatedPaymentRefundQueryFactory.php @@ -0,0 +1,16 @@ +data)->create(), + $this->get('includePayment', false) + ); + } +} diff --git a/src/Factories/GetPaginatedRefundsQueryFactory.php b/src/Factories/GetPaginatedRefundsQueryFactory.php new file mode 100644 index 000000000..780ca39a3 --- /dev/null +++ b/src/Factories/GetPaginatedRefundsQueryFactory.php @@ -0,0 +1,20 @@ +includes('embed', PaymentIncludesQuery::PAYMENT); + + return new GetPaginatedRefundsQuery( + PaginatedQueryFactory::new($this->data)->create(), + $this->get('embedPayment', $embedPayment), + $this->get('profileId') + ); + } +} diff --git a/src/Factories/GetPaginatedSettlementCapturesQueryFactory.php b/src/Factories/GetPaginatedSettlementCapturesQueryFactory.php new file mode 100644 index 000000000..27e769c7a --- /dev/null +++ b/src/Factories/GetPaginatedSettlementCapturesQueryFactory.php @@ -0,0 +1,19 @@ +includes('include', PaymentIncludesQuery::PAYMENT); + + return new GetPaginatedSettlementCapturesQuery( + PaginatedQueryFactory::new($this->data)->create(), + $this->get('includePayment', $includePayment) + ); + } +} diff --git a/src/Factories/GetPaginatedSettlementChargebacksQueryFactory.php b/src/Factories/GetPaginatedSettlementChargebacksQueryFactory.php new file mode 100644 index 000000000..196f236eb --- /dev/null +++ b/src/Factories/GetPaginatedSettlementChargebacksQueryFactory.php @@ -0,0 +1,20 @@ +data)->create(), + $this->get('includePayment', false), + $this->get('profileId') + ); + } +} diff --git a/src/Factories/GetPaginatedSettlementRefundsQueryFactory.php b/src/Factories/GetPaginatedSettlementRefundsQueryFactory.php new file mode 100644 index 000000000..50b42c5e1 --- /dev/null +++ b/src/Factories/GetPaginatedSettlementRefundsQueryFactory.php @@ -0,0 +1,19 @@ +includes('include', PaymentIncludesQuery::PAYMENT); + + return new GetPaginatedSettlementRefundsQuery( + PaginatedQueryFactory::new($this->data)->create(), + $this->get('includePayment', $includePayment) + ); + } +} diff --git a/src/Factories/GetPaginatedSettlementsQueryFactory.php b/src/Factories/GetPaginatedSettlementsQueryFactory.php new file mode 100644 index 000000000..e31c6e436 --- /dev/null +++ b/src/Factories/GetPaginatedSettlementsQueryFactory.php @@ -0,0 +1,21 @@ +get('balanceId'); + + return new GetPaginatedSettlementsQuery( + PaginatedQueryFactory::new($this->data)->create(), + $this->get('filters.balanceId', $balanceId), + ); + } +} diff --git a/src/Factories/GetPaymentCaptureQueryFactory.php b/src/Factories/GetPaymentCaptureQueryFactory.php new file mode 100644 index 000000000..cd8c538ea --- /dev/null +++ b/src/Factories/GetPaymentCaptureQueryFactory.php @@ -0,0 +1,18 @@ +includes('include', PaymentIncludesQuery::PAYMENT); + + return new GetPaymentCaptureQuery( + $this->get('includePayment', $includePayment), + ); + } +} diff --git a/src/Factories/GetPaymentChargebackQueryFactory.php b/src/Factories/GetPaymentChargebackQueryFactory.php new file mode 100644 index 000000000..b1bf16a24 --- /dev/null +++ b/src/Factories/GetPaymentChargebackQueryFactory.php @@ -0,0 +1,18 @@ +includes('include', PaymentIncludesQuery::PAYMENT); + + return new GetPaymentChargebackQuery( + $this->get('includePayment', $includePayment), + ); + } +} diff --git a/src/Factories/GetPaymentMethodQueryFactory.php b/src/Factories/GetPaymentMethodQueryFactory.php new file mode 100644 index 000000000..330d50c4e --- /dev/null +++ b/src/Factories/GetPaymentMethodQueryFactory.php @@ -0,0 +1,23 @@ +includes('include', MethodQuery::INCLUDE_ISSUERS); + $includePricing = $this->includes('include', MethodQuery::INCLUDE_PRICING); + + return new GetPaymentMethodQuery( + $this->get('locale'), + $this->get('currency'), + $this->get('profileId'), + $this->get('includeIssuers', $includeIssuers), + $this->get('includePricing', $includePricing), + ); + } +} diff --git a/src/Factories/GetPaymentQueryFactory.php b/src/Factories/GetPaymentQueryFactory.php new file mode 100644 index 000000000..4740ab13a --- /dev/null +++ b/src/Factories/GetPaymentQueryFactory.php @@ -0,0 +1,26 @@ +includes('embed', PaymentQuery::EMBED_CAPTURES); + $embedRefunds = $this->includes('embed', PaymentQuery::EMBED_REFUNDS); + $embedChargebacks = $this->includes('embed', PaymentQuery::EMBED_CHARGEBACKS); + $includeQrCode = $this->includes('include', PaymentQuery::INCLUDE_QR_CODE); + $includeRemainderDetails = $this->includes('include', PaymentQuery::INCLUDE_REMAINDER_DETAILS); + + return new GetPaymentQuery( + $this->get('embedCaptures', $embedCaptures), + $this->get('embedRefunds', $embedRefunds), + $this->get('embedChargebacks', $embedChargebacks), + $this->get('includeQrCode', $includeQrCode), + $this->get('includeRemainderDetails', $includeRemainderDetails), + ); + } +} diff --git a/src/Factories/GetPaymentRefundQueryFactory.php b/src/Factories/GetPaymentRefundQueryFactory.php new file mode 100644 index 000000000..626627836 --- /dev/null +++ b/src/Factories/GetPaymentRefundQueryFactory.php @@ -0,0 +1,18 @@ +includes('include', PaymentIncludesQuery::PAYMENT); + + return new GetPaymentRefundQuery( + $this->get('includePayment', $includePayment), + ); + } +} diff --git a/src/Factories/InvoiceLineCollectionFactory.php b/src/Factories/InvoiceLineCollectionFactory.php new file mode 100644 index 000000000..920f4cd31 --- /dev/null +++ b/src/Factories/InvoiceLineCollectionFactory.php @@ -0,0 +1,16 @@ + InvoiceLineFactory::new($item)->create(), + $this->data + )); + } +} diff --git a/src/Factories/InvoiceLineFactory.php b/src/Factories/InvoiceLineFactory.php new file mode 100644 index 000000000..560bf271c --- /dev/null +++ b/src/Factories/InvoiceLineFactory.php @@ -0,0 +1,20 @@ +get('description'), + $this->get('quantity'), + $this->get('vatRate'), + MoneyFactory::new($this->get('unitPrice'))->create(), + $this->mapIfNotNull('discount', fn (array $data) => Discount::fromArray($data)) + ); + } +} diff --git a/src/Factories/MoneyFactory.php b/src/Factories/MoneyFactory.php new file mode 100644 index 000000000..7386921c2 --- /dev/null +++ b/src/Factories/MoneyFactory.php @@ -0,0 +1,20 @@ +has(['currency', 'value'])) { + throw new \InvalidArgumentException('Invalid Money data provided'); + } + + return new Money( + $this->get('currency'), + $this->get('value') + ); + } +} diff --git a/src/Factories/OrderLineCollectionFactory.php b/src/Factories/OrderLineCollectionFactory.php new file mode 100644 index 000000000..f41d15ae3 --- /dev/null +++ b/src/Factories/OrderLineCollectionFactory.php @@ -0,0 +1,16 @@ + OrderLineFactory::new($item)->create(), + $this->data + )); + } +} diff --git a/src/Factories/OrderLineFactory.php b/src/Factories/OrderLineFactory.php new file mode 100644 index 000000000..99b4d0eca --- /dev/null +++ b/src/Factories/OrderLineFactory.php @@ -0,0 +1,27 @@ +get('description'), + $this->get('quantity'), + MoneyFactory::new($this->get('unitPrice'))->create(), + MoneyFactory::new($this->get('totalAmount'))->create(), + $this->get('type'), + $this->get('quantityUnit'), + $this->mapIfNotNull('discountAmount', fn (array $item) => MoneyFactory::new($item)->create()), + $this->mapIfNotNull('recurring', fn (array $item) => RecurringBillingCycleFactory::new($item)->create()), + $this->get('vatRate'), + $this->mapIfNotNull('vatAmount', fn (array $item) => MoneyFactory::new($item)->create()), + $this->get('sku'), + $this->get('imageUrl'), + $this->get('productUrl'), + ); + } +} diff --git a/src/Factories/PaginatedQueryFactory.php b/src/Factories/PaginatedQueryFactory.php new file mode 100644 index 000000000..98498c459 --- /dev/null +++ b/src/Factories/PaginatedQueryFactory.php @@ -0,0 +1,16 @@ +get('from'), + $this->get('limit'), + ); + } +} diff --git a/src/Factories/PaymentRouteCollectionFactory.php b/src/Factories/PaymentRouteCollectionFactory.php new file mode 100644 index 000000000..a430ae229 --- /dev/null +++ b/src/Factories/PaymentRouteCollectionFactory.php @@ -0,0 +1,32 @@ +has(['amount', 'destination.organizationId'])) { + throw new \InvalidArgumentException('Invalid PaymentRoute data provided'); + } + + return new PaymentRoute( + MoneyFactory::new(Arr::get($item, 'amount'))->create(), + Arr::get($item, 'destination.organizationId'), + Utility::compose( + Arr::get($item, 'delayUntil'), + fn ($value) => DateTimeImmutable::createFromFormat('Y-m-d', $value) + ) + ); + }, $this->data); + + return new DataCollection($paymentRoutes); + } +} diff --git a/src/Factories/RecipientFactory.php b/src/Factories/RecipientFactory.php new file mode 100644 index 000000000..34a8d0c14 --- /dev/null +++ b/src/Factories/RecipientFactory.php @@ -0,0 +1,30 @@ +get('type'), + $this->get('email'), + $this->get('streetAndNumber'), + $this->get('postalCode'), + $this->get('city'), + $this->get('country'), + $this->get('locale'), + $this->get('title'), + $this->get('givenName'), + $this->get('familyName'), + $this->get('organizationName'), + $this->get('organizationNumber'), + $this->get('vatNumber'), + $this->get('phone'), + $this->get('streetAdditional'), + $this->get('region'), + ); + } +} diff --git a/src/Factories/RecurringBillingCycleFactory.php b/src/Factories/RecurringBillingCycleFactory.php new file mode 100644 index 000000000..c55a8d7cd --- /dev/null +++ b/src/Factories/RecurringBillingCycleFactory.php @@ -0,0 +1,20 @@ +get('interval'), + $this->get('descriptipn'), + $this->mapIfNotNull('amount', fn (array $item) => MoneyFactory::new($item)->create()), + $this->get('times'), + $this->mapIfNotNull('startDate', fn (string $item) => DateTimeImmutable::createFromFormat('Y-m-d', $item)), + ); + } +} diff --git a/src/Factories/RefundRouteCollectionFactory.php b/src/Factories/RefundRouteCollectionFactory.php new file mode 100644 index 000000000..788cfa649 --- /dev/null +++ b/src/Factories/RefundRouteCollectionFactory.php @@ -0,0 +1,26 @@ +has(['amount', 'source.organizationId'])) { + throw new \InvalidArgumentException('Invalid RefundRoute data provided'); + } + + return new RefundRoute( + MoneyFactory::new(Arr::get($item, 'amount'))->create(), + Arr::get($item, 'source.organizationId') + ); + }, $this->data); + + return new DataCollection($refundRoutes); + } +} diff --git a/src/Factories/SortablePaginatedQueryFactory.php b/src/Factories/SortablePaginatedQueryFactory.php new file mode 100644 index 000000000..37dad3873 --- /dev/null +++ b/src/Factories/SortablePaginatedQueryFactory.php @@ -0,0 +1,17 @@ +get('from'), + $this->get('limit'), + $this->get('sort'), + ); + } +} diff --git a/src/Factories/UpdateCustomerPayloadFactory.php b/src/Factories/UpdateCustomerPayloadFactory.php new file mode 100644 index 000000000..53105dcc9 --- /dev/null +++ b/src/Factories/UpdateCustomerPayloadFactory.php @@ -0,0 +1,19 @@ +get('name'), + $this->get('email'), + $this->get('locale'), + $this->mapIfNotNull('metadata', Metadata::class), + ); + } +} diff --git a/src/Factories/UpdatePaymentLinkPayloadFactory.php b/src/Factories/UpdatePaymentLinkPayloadFactory.php new file mode 100644 index 000000000..5203b6600 --- /dev/null +++ b/src/Factories/UpdatePaymentLinkPayloadFactory.php @@ -0,0 +1,16 @@ +get('description'), + $this->get('archived'), + ); + } +} diff --git a/src/Factories/UpdatePaymentPayloadFactory.php b/src/Factories/UpdatePaymentPayloadFactory.php new file mode 100644 index 000000000..7c3b2992b --- /dev/null +++ b/src/Factories/UpdatePaymentPayloadFactory.php @@ -0,0 +1,25 @@ +get('description'), + $this->get('redirectUrl'), + $this->get('cancelUrl'), + $this->get('webhookUrl'), + $this->mapIfNotNull('metadata', Metadata::class), + $this->get('method'), + $this->get('locale'), + $this->get('restrictPaymentMethodsToCountry'), + $this->get('additional') ?? Utility::filterByProperties(UpdatePaymentPayload::class, $this->data), + ); + } +} diff --git a/src/Factories/UpdatePaymentRoutePayloadFactory.php b/src/Factories/UpdatePaymentRoutePayloadFactory.php new file mode 100644 index 000000000..f657aa8bd --- /dev/null +++ b/src/Factories/UpdatePaymentRoutePayloadFactory.php @@ -0,0 +1,16 @@ +get('releaseDate')), + ); + } +} diff --git a/src/Factories/UpdateProfilePayloadFactory.php b/src/Factories/UpdateProfilePayloadFactory.php new file mode 100644 index 000000000..1c23baeda --- /dev/null +++ b/src/Factories/UpdateProfilePayloadFactory.php @@ -0,0 +1,22 @@ +get('name'), + $this->get('website'), + $this->get('email'), + $this->get('phone'), + $this->get('description'), + $this->get('countriesOfActivity'), + $this->get('businessCategory'), + $this->get('mode') + ); + } +} diff --git a/src/Factories/UpdateSalesInvoicePayloadFactory.php b/src/Factories/UpdateSalesInvoicePayloadFactory.php new file mode 100644 index 000000000..8023d83fc --- /dev/null +++ b/src/Factories/UpdateSalesInvoicePayloadFactory.php @@ -0,0 +1,34 @@ +get('status'), + $this->get('recipientIdentifier'), + $this->get('paymentTerm'), + $this->get('memo'), + $this->mapIfNotNull('paymentDetails', fn (array $data) => PaymentDetails::fromArray($data)), + $this->mapIfNotNull('emailDetails', fn (array $data) => EmailDetails::fromArray($data)), + $this->mapIfNotNull('recipient', fn (array $data) => RecipientFactory::new($data)->create()), + $this + ->mapIfNotNull( + 'lines', + fn (array $items) => InvoiceLineCollectionFactory::new($items)->create() + ), + $this->get('webhookUrl'), + $this->mapIfNotNull('discount', fn (array $data) => Discount::fromArray($data)) + ); + } +} diff --git a/src/Factories/UpdateSubscriptionPayloadFactory.php b/src/Factories/UpdateSubscriptionPayloadFactory.php new file mode 100644 index 000000000..c833394f1 --- /dev/null +++ b/src/Factories/UpdateSubscriptionPayloadFactory.php @@ -0,0 +1,24 @@ +mapIfNotNull('amount', fn (array $amount) => MoneyFactory::new($amount)->create()), + $this->get('description'), + $this->get('interval'), + $this->mapIfNotNull('startDate', fn (string $date) => DateTimeImmutable::createFromFormat('Y-m-d', $date)), + $this->get('times'), + $this->mapIfNotNull('metadata', Metadata::class), + $this->get('webhookUrl'), + $this->get('mandateId') + ); + } +} diff --git a/src/Fake/MockMollieClient.php b/src/Fake/MockMollieClient.php new file mode 100644 index 000000000..93fbf10dc --- /dev/null +++ b/src/Fake/MockMollieClient.php @@ -0,0 +1,33 @@ +httpClient = new MockMollieHttpAdapter($expectedResponses); + + $this->setAccessToken('access_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); + } + + /** + * @param string|callable $callback + */ + public function assertSent($callback): void + { + $this->httpClient->assertSent($callback); + } + + public function assertSentCount(int $count): void + { + $this->httpClient->assertSentCount($count); + } +} diff --git a/src/Fake/MockMollieHttpAdapter.php b/src/Fake/MockMollieHttpAdapter.php new file mode 100644 index 000000000..9358e6fd4 --- /dev/null +++ b/src/Fake/MockMollieHttpAdapter.php @@ -0,0 +1,126 @@ + + */ + private array $expected; + + private array $recorded = []; + + public function __construct(array $expectedResponses = []) + { + $this->expected = $expectedResponses; + } + + /** + * {@inheritDoc} + */ + public function sendRequest(PendingRequest $pendingRequest): Response + { + $requestClass = get_class($request = $pendingRequest->getRequest()); + + $this->guardAgainstStrayRequests($requestClass); + + $mockedResponse = $this->getResponse($requestClass, $pendingRequest); + + $response = new Response( + $mockedResponse->createPsrResponse(), + $pendingRequest->createPsrRequest(), + $pendingRequest, + ); + + $this->recorded[] = [$request, $response]; + + return $response; + } + + private function guardAgainstStrayRequests(string $requestClass): void + { + if (! Arr::has($this->expected, $requestClass)) { + throw new \RuntimeException('The request class '.$requestClass.' is not expected.'); + } + } + + /** + * Get the mocked response and remove it from the expected responses. + */ + private function getResponse(string $requestClass, PendingRequest $pendingRequest): MockResponse + { + $mockedResponse = Arr::get($this->expected, $requestClass); + + if ($mockedResponse instanceof Closure) { + Arr::forget($this->expected, $requestClass); + + return $mockedResponse($pendingRequest); + } + + if (! ($mockedResponse instanceof SequenceMockResponse)) { + Arr::forget($this->expected, $requestClass); + + return $mockedResponse; + } + + $response = $mockedResponse->pop(); + + if ($mockedResponse->isEmpty()) { + Arr::forget($this->expected, $requestClass); + } + + return $response; + } + + public function recorded(?callable $callback = null): array + { + if ($callback === null) { + return $this->recorded; + } + + return array_filter($this->recorded, fn ($recorded) => $callback($recorded[0], $recorded[1])); + } + + /** + * @param string|callable $callback + */ + public function assertSent($callback): void + { + if (is_string($callback)) { + $callback = fn ($request) => get_class($request) === $callback; + } + + PHPUnit::assertTrue( + count($this->recorded($callback)) > 0, + 'No requests were sent.' + ); + } + + public function assertSentCount(int $count): void + { + PHPUnit::assertEquals( + $count, + count($this->recorded), + 'The expected number of requests was not sent.' + ); + } + + /** + * {@inheritDoc} + */ + public function version(): string + { + return 'mock-client/2.0'; + } +} diff --git a/src/Fake/MockResponse.php b/src/Fake/MockResponse.php new file mode 100644 index 000000000..1eb4acb13 --- /dev/null +++ b/src/Fake/MockResponse.php @@ -0,0 +1,115 @@ +body = is_array($body) ? json_encode($body) : $body; + $this->status = $status; + $this->resourceKey = $resourceKey; + } + + /** + * @param string|array $body + */ + public static function ok($body = [], string $resourceKey = ''): self + { + return new self($body, 200, $resourceKey); + } + + /** + * @param string|array $body + */ + public static function created($body = [], string $resourceKey = ''): self + { + return new self($body, 201, $resourceKey); + } + + /** + * @param string|array $body + */ + public static function noContent($body = [], string $resourceKey = ''): self + { + return new self($body, 204, $resourceKey); + } + + public static function notFound(string $resourceKey = ''): self + { + return new self('', 404, $resourceKey); + } + + /** + * @param string|array $body + */ + public static function unprocessableEntity($body = [], string $resourceKey = ''): self + { + return new self($body, 422, $resourceKey); + } + + public function createPsrResponse(): ResponseInterface + { + $psrResponse = $this + ->factories() + ->responseFactory + ->createResponse($this->status); + + $body = $this + ->factories() + ->streamFactory + ->createStream($this->body()); + + return $psrResponse->withBody($body); + } + + public function body(): string + { + if (empty($body = $this->body)) { + return ''; + } + + if ($this->isJson($body)) { + return $body; + } + + $path = Arr::join([ + __DIR__, + 'Responses', + $body.'.json', + ], DIRECTORY_SEPARATOR); + + $contents = file_get_contents($path); + + if (! empty($this->resourceKey)) { + $contents = str_replace('{{ RESOURCE_ID }}', $this->resourceKey, $contents); + } + + return $contents; + } + + private function isJson($string): bool + { + json_decode($string); + + return json_last_error() == JSON_ERROR_NONE; + } +} diff --git a/src/Fake/Responses/apple-pay-session.json b/src/Fake/Responses/apple-pay-session.json new file mode 100644 index 000000000..372904730 --- /dev/null +++ b/src/Fake/Responses/apple-pay-session.json @@ -0,0 +1,10 @@ +{ + "epochTimestamp": 1555507053169, + "expiresAt": 1555510653169, + "merchantSessionIdentifier": "SSH2EAF8AFAEAA94DEEA898162A5DAFD36E_916523AAED1343F5BC5815E12BEE9250AFFDC1A17C46B0DE5A9", + "nonce": "0206b8db", + "merchantIdentifier": "BD62FEB196874511C22DB28A9E14A89E3534C93194F73EA417EC566368D391EB", + "domainName": "pay.example.org", + "displayName": "Chuck Norris's Store", + "signature": "308006092a864886f7...8cc030ad3000000000000" +} diff --git a/src/Fake/Responses/balance-list.json b/src/Fake/Responses/balance-list.json new file mode 100644 index 000000000..29904614e --- /dev/null +++ b/src/Fake/Responses/balance-list.json @@ -0,0 +1,98 @@ +{ + "count": 2, + "_embedded": { + "balances": [ + { + "resource": "balance", + "id": "bal_gVMhHKqSSRYJyPsuoPNFH", + "mode": "live", + "createdAt": "2019-01-10T12:06:28+00:00", + "currency": "EUR", + "status": "active", + "availableAmount": { + "value": "0.00", + "currency": "EUR" + }, + "incomingAmount": { + "value": "0.00", + "currency": "EUR" + }, + "outgoingAmount": { + "value": "0.00", + "currency": "EUR" + }, + "transferFrequency": "daily", + "transferThreshold": { + "value": "40.00", + "currency": "EUR" + }, + "transferReference": "Mollie payout", + "transferDestination": { + "type": "bank-account", + "beneficiaryName": "Jack Bauer", + "bankAccount": "NL53INGB0654422370", + "bankAccountId": "bnk_jrty3f" + }, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + } + } + }, + { + "resource": "balance", + "id": "bal_gVMhHKqSSRYJyPsuoPABC", + "mode": "live", + "createdAt": "2019-01-10T10:23:41+00:00", + "status": "active", + "currency": "EUR", + "availableAmount": { + "value": "0.00", + "currency": "EUR" + }, + "incomingAmount": { + "value": "0.00", + "currency": "EUR" + }, + "outgoingAmount": { + "value": "0.00", + "currency": "EUR" + }, + "transferFrequency": "twice-a-month", + "transferThreshold": { + "value": "5.00", + "currency": "EUR" + }, + "transferReference": "Mollie payout", + "transferDestination": { + "type": "bank-account", + "beneficiaryName": "Jack Bauer", + "bankAccount": "NL97MOLL6351480700", + "bankAccountId": "bnk_jrty3e" + }, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + } + } + } + ] + }, + "_links": { + "documentation": { + "href": "...", + "type": "text/html" + }, + "self": { + "href": "https://api.mollie.com/v2/balances?limit=5", + "type": "application/hal+json" + }, + "previous": null, + "next": { + "href": "...", + "type": "application/hal+json" + } + } +} diff --git a/src/Fake/Responses/balance-report.json b/src/Fake/Responses/balance-report.json new file mode 100644 index 000000000..cd217ffec --- /dev/null +++ b/src/Fake/Responses/balance-report.json @@ -0,0 +1,149 @@ +{ + "resource": "balance-report", + "balanceId": "{{ RESOURCE_ID }}", + "timeZone": "Europe/Amsterdam", + "from": "2024-01-01", + "until": "2024-01-31", + "grouping": "transaction-categories", + "totals": { + "open": { + "available": { + "amount": { + "currency": "EUR", + "value": "0.00" + } + }, + "pending": { + "amount": { + "currency": "EUR", + "value": "0.00" + } + } + }, + "payments": { + "immediatelyAvailable": { + "amount": { + "currency": "EUR", + "value": "0.00" + } + }, + "pending": { + "amount": { + "currency": "EUR", + "value": "4.98" + }, + "subtotals": [ + { + "transactionType": "payment", + "count": 1, + "amount": { + "currency": "EUR", + "value": "4.98" + }, + "subtotals": [ + { + "method": "ideal", + "count": 1, + "amount": { + "currency": "EUR", + "value": "4.98" + } + } + ] + } + ] + }, + "movedToAvailable": { + "amount": { + "currency": "EUR", + "value": "0.00" + } + } + }, + "refunds": {}, + "capital": {}, + "chargebacks": {}, + "transfers": {}, + "fee-prepayments": { + "immediatelyAvailable": { + "amount": { + "currency": "EUR", + "value": "0.00" + } + }, + "movedToAvailable": { + "amount": { + "currency": "EUR", + "value": "-0.36" + }, + "subtotals": [ + { + "prepaymentPartType": "fee", + "count": 1, + "amount": { + "currency": "EUR", + "value": "-0.29" + }, + "subtotals": [ + { + "feeType": "payment-fee", + "method": "ideal", + "count": 1, + "amount": { + "currency": "EUR", + "value": "-0.29" + } + } + ] + }, + { + "prepaymentPartType": "fee-vat", + "amount": { + "currency": "EUR", + "value": "-0.0609" + } + }, + { + "prepaymentPartType": "fee-rounding-compensation", + "amount": { + "currency": "EUR", + "value": "-0.0091" + } + } + ] + }, + "pending": { + "amount": { + "currency": "EUR", + "value": "-0.36" + }, + "subtotals": [] + } + }, + "corrections": {}, + "close": { + "available": { + "amount": { + "currency": "EUR", + "value": "0.00" + } + }, + "pending": { + "amount": { + "currency": "EUR", + "value": "4.32" + } + } + } + }, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/balance-transactions.json b/src/Fake/Responses/balance-transactions.json new file mode 100644 index 000000000..a7966c9d7 --- /dev/null +++ b/src/Fake/Responses/balance-transactions.json @@ -0,0 +1,63 @@ +{ + "count": 5, + "_embedded": { + "balance_transactions": [ + { + "resource": "balance_transaction", + "id": "baltr_*", + "type": "refund", + "resultAmount": { + "currency": "EUR", + "value": "-10.25" + }, + "initialAmount": { + "currency": "EUR", + "value": "-10.00" + }, + "deductions": { + "currency": "EUR", + "value": "-0.25" + }, + "context": { + "paymentId": "tr_7UhSN1zuXS", + "refundId": "re_4qqhO89gsT" + } + }, + { + "resource": "balance_transaction", + "id": "baltr_WhmDwNYR87FPDbiwBhUXCh", + "type": "payment", + "resultAmount": { + "currency": "EUR", + "value": "9.71" + }, + "initialAmount": { + "currency": "EUR", + "value": "10.00" + }, + "deductions": { + "currency": "EUR", + "value": "-0.29" + }, + "context": { + "paymentId": "tr_7UhSN1zuXS" + } + } + ] + }, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "previous": null, + "next": { + "href": "https://api.mollie.com/v2/balances/bal_gVMhHKqSSRYJyPsuoPNFH/transactions?from=baltr_*&limit=5", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/balance.json b/src/Fake/Responses/balance.json new file mode 100644 index 000000000..cb9c0df7f --- /dev/null +++ b/src/Fake/Responses/balance.json @@ -0,0 +1,42 @@ +{ + "resource": "balance", + "id": "bal_gVMhHKqSSRYJyPsuoPNFH", + "mode": "live", + "createdAt": "2019-01-10T10:23:41+00:00", + "currency": "EUR", + "status": "active", + "availableAmount": { + "value": "0.00", + "currency": "EUR" + }, + "incomingAmount": { + "value": "0.00", + "currency": "EUR" + }, + "outgoingAmount": { + "value": "0.00", + "currency": "EUR" + }, + "transferFrequency": "twice-a-month", + "transferThreshold": { + "value": "5.00", + "currency": "EUR" + }, + "transferReference": "Mollie payout", + "transferDestination": { + "type": "bank-account", + "beneficiaryName": "Jack Bauer", + "bankAccount": "NL53INGB0654422370", + "bankAccountId": "bnk_jrty3f" + }, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/capture-list.json b/src/Fake/Responses/capture-list.json new file mode 100644 index 000000000..aa9a865ab --- /dev/null +++ b/src/Fake/Responses/capture-list.json @@ -0,0 +1,45 @@ +{ + "count": 1, + "_embedded": { + "captures": [ + { + "resource": "capture", + "id": "cpt_mNepDkEtco6ah3QNPUGYH", + "mode": "live", + "description": "Capture for cart #12345", + "amount": { + "currency": "EUR", + "value": "35.95" + }, + "metadata": "{\"bookkeeping_id\":12345}", + "paymentId": "tr_7UhSN1zuXS", + "createdAt": "2023-08-02T09:29:56.0Z", + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "payment": { + "href": "https://api.mollie.com/v2/payments/tr_7UhSN1zuXS", + "type": "application/hal+json" + } + } + } + ] + }, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "previous": null, + "next": { + "href": "https://api.mollie.com/v2/payments/tr_7UhSN1zuXS/captures?from=cpt_Sy3NzD2TYuQtUaxNyu8aH&limit=5", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/capture.json b/src/Fake/Responses/capture.json new file mode 100644 index 000000000..569077542 --- /dev/null +++ b/src/Fake/Responses/capture.json @@ -0,0 +1,27 @@ +{ + "resource": "capture", + "id": "{{ RESOURCE_ID }}", + "mode": "live", + "description": "Capture for cart #12345", + "amount": { + "currency": "EUR", + "value": "35.95" + }, + "metadata": "{\"bookkeeping_id\":12345}", + "paymentId": "tr_7UhSN1zuXS", + "createdAt": "2023-08-02T09:29:56.0Z", + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "payment": { + "href": "https://api.mollie.com/v2/payments/tr_7UhSN1zuXS", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/chargeback-list.json b/src/Fake/Responses/chargeback-list.json new file mode 100644 index 000000000..91e36fd18 --- /dev/null +++ b/src/Fake/Responses/chargeback-list.json @@ -0,0 +1,210 @@ +{ + "count": 2, + "_embedded": { + "chargebacks": [ + { + "resource": "chargeback", + "id": "chb_xg7414", + "amount": { + "value": "10.00", + "currency": "EUR" + }, + "createdAt": "2022-01-03T13:28:13+00:00", + "paymentId": "tr_HdQrGb6N3r", + "settlementAmount": { + "value": "-10.00", + "currency": "EUR" + }, + "_embedded": { + "payment": { + "resource": "payment", + "id": "tr_HdQrGb6N3r", + "mode": "test", + "createdAt": "2022-01-03T13:27:35+00:00", + "amount": { + "value": "10.00", + "currency": "EUR" + }, + "description": "This is the description of the payment", + "method": "creditcard", + "metadata": { + "someProperty": "someValue", + "anotherProperty": "anotherValue" + }, + "status": "paid", + "paidAt": "2022-01-03T13:28:10+00:00", + "amountRefunded": { + "value": "0.00", + "currency": "EUR" + }, + "amountRemaining": { + "value": "10.00", + "currency": "EUR" + }, + "amountChargedBack": { + "value": "10.00", + "currency": "EUR" + }, + "locale": "en_US", + "restrictPaymentMethodsToCountry": "NL", + "countryCode": "NL", + "profileId": "pfl_85dxyKqNHa", + "sequenceType": "oneoff", + "redirectUrl": "https://example.com/landing_page", + "webhookUrl": "https://example.com/redirect", + "settlementAmount": { + "value": "10.00", + "currency": "EUR" + }, + "details": { + "cardNumber": "6787", + "cardHolder": "T. TEST", + "cardAudience": "consumer", + "cardLabel": "Mastercard", + "cardCountryCode": "NL", + "cardSecurity": "normal", + "feeRegion": "other" + }, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "dashboard": { + "href": "https://www.mollie.com/dashboard/org_13514547/payments/tr_HdQrGb6N3r", + "type": "text/html" + }, + "changePaymentState": { + "href": "https://www.mollie.com/checkout/test-mode?method=creditcard&token=3.lxnsca", + "type": "text/html" + }, + "chargebacks": { + "href": "https://api.mollie.com/v2/payments/tr_HdQrGb6N3r/chargebacks", + "type": "application/hal+json" + } + } + } + }, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "payment": { + "href": "https://api.mollie.com/v2/payments/tr_HdQrGb6N3r", + "type": "application/hal+json" + } + } + }, + { + "resource": "chargeback", + "id": "chb_ls7ahg", + "amount": { + "value": "10.00", + "currency": "EUR" + }, + "createdAt": "2022-01-03T13:20:37+00:00", + "paymentId": "tr_8bVBhk2qs4", + "settlementAmount": { + "value": "-10.00", + "currency": "EUR" + }, + "_embedded": { + "payment": { + "resource": "payment", + "id": "tr_8bVBhk2qs4", + "mode": "test", + "createdAt": "2022-01-03T13:11:20+00:00", + "amount": { + "value": "10.00", + "currency": "EUR" + }, + "description": "This is the description of the payment", + "method": "creditcard", + "metadata": { + "someProperty": "someValue", + "anotherProperty": "anotherValue" + }, + "status": "paid", + "paidAt": "2022-01-03T13:18:39+00:00", + "amountRefunded": { + "value": "0.00", + "currency": "EUR" + }, + "amountRemaining": { + "value": "10.00", + "currency": "EUR" + }, + "amountChargedBack": { + "value": "10.00", + "currency": "EUR" + }, + "locale": "en_US", + "restrictPaymentMethodsToCountry": "NL", + "countryCode": "NL", + "profileId": "pfl_85dxyKqNHa", + "sequenceType": "oneoff", + "redirectUrl": "https://example.com/landing_page", + "webhookUrl": "https://example.com/redirect", + "settlementAmount": { + "value": "10.00", + "currency": "EUR" + }, + "details": { + "cardNumber": "6787", + "cardHolder": "T. TEST", + "cardAudience": "consumer", + "cardLabel": "Mastercard", + "cardCountryCode": "NL", + "cardSecurity": "normal", + "feeRegion": "other" + }, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "dashboard": { + "href": "https://www.mollie.com/dashboard/org_13514547/payments/tr_8bVBhk2qs4", + "type": "text/html" + }, + "changePaymentState": { + "href": "https://www.mollie.com/checkout/test-mode?method=creditcard&token=3.11roh2", + "type": "text/html" + }, + "chargebacks": { + "href": "https://api.mollie.com/v2/payments/tr_8bVBhk2qs4/chargebacks", + "type": "application/hal+json" + } + } + } + }, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "payment": { + "href": "https://api.mollie.com/v2/payments/tr_8bVBhk2qs4", + "type": "application/hal+json" + } + } + } + ] + }, + "_links": { + "documentation": { + "href": "...", + "type": "text/html" + }, + "self": { + "href": "...", + "type": "application/hal+json" + }, + "previous": null, + "next": { + "href": "...", + "type": "application/hal+json" + } + } +} diff --git a/src/Fake/Responses/chargeback.json b/src/Fake/Responses/chargeback.json new file mode 100644 index 000000000..2792646a2 --- /dev/null +++ b/src/Fake/Responses/chargeback.json @@ -0,0 +1,33 @@ +{ + "resource": "chargeback", + "id": "{{ RESOURCE_ID }}", + "amount": { + "currency": "USD", + "value": "43.38" + }, + "settlementAmount": { + "currency": "EUR", + "value": "-35.07" + }, + "reason": { + "code": "AC01", + "description": "Account identifier incorrect (i.e. invalid IBAN)" + }, + "paymentId": "tr_7UhSN1zuXS", + "createdAt": "2023-03-14T17:09:02.0Z", + "reversedAt": null, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "payment": { + "href": "https://api.mollie.com/v2/payments/tr_7UhSN1zuXS", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/client-link.json b/src/Fake/Responses/client-link.json new file mode 100644 index 000000000..5e2314c9d --- /dev/null +++ b/src/Fake/Responses/client-link.json @@ -0,0 +1,14 @@ +{ + "id": "csr_ayCz46QLwCbxpTaSYQQZH", + "resource": "client-link", + "_links": { + "clientLink": { + "href": "https://my.mollie.com/dashboard/client-link/csr_ayCz46QLwCbxpTaSYQQZH", + "type": "text/html" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/client-list.json b/src/Fake/Responses/client-list.json new file mode 100644 index 000000000..384c85fd0 --- /dev/null +++ b/src/Fake/Responses/client-list.json @@ -0,0 +1,33 @@ +{ + "count": 2, + "_embedded": { + "clients": [ + { + "resource": "client", + "id": "org_12345678", + "organizationCreatedAt": "2023-04-06 13:10:19+00:00", + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + } + } + } + ] + }, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "previous": null, + "next": { + "href": "https://api.mollie.com/v2/clients?from=org_63916732&limit=5", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/client.json b/src/Fake/Responses/client.json new file mode 100644 index 000000000..525e9a5a6 --- /dev/null +++ b/src/Fake/Responses/client.json @@ -0,0 +1,52 @@ +{ + "resource": "client", + "id": "org_7049691", + "organizationCreatedAt": "2019-12-06T10:09:32+00:00", + "_embedded": { + "organization": { + "resource": "organization", + "id": "org_7049691", + "name": "Hugo's eenzame zaak", + "email": "[[redacted]]", + "locale": "en_US", + "address": { + "streetAndNumber": "[[redacted]]", + "postalCode": "[[redacted]]", + "city": "[[redacted]]", + "country": "[[redacted]]" + }, + "registrationNumber": "[[redacted]]", + "vatNumber": "", + "vatRegulation": "dutch", + "verifiedAt": "2020-10-19T11:45:36+00:00", + "_links": { + "self": { + "href": "https://api.mollie.com/v2/organization/org_7049691", + "type": "application/hal+json" + }, + "dashboard": { + "href": "https://www.mollie.com/dashboard/org_7049691/", + "type": "text/html" + } + } + } + }, + "_links": { + "self": { + "href": "https://api.mollie.com/v2/clients/org_7049691", + "type": "application/hal+json" + }, + "onboarding": { + "href": "https://api.mollie.com/v2/onboarding/org_7049691", + "type": "application/hal+json" + }, + "organization": { + "href": "https://api.mollie.com/v2/organization/org_7049691", + "type": "application/hal+json" + }, + "documentation": { + "href": "https://docs.mollie.com/reference/v2/partners-api/get-client", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/current-profile.json b/src/Fake/Responses/current-profile.json new file mode 100644 index 000000000..bf5047cc4 --- /dev/null +++ b/src/Fake/Responses/current-profile.json @@ -0,0 +1,47 @@ +{ + "resource": "profile", + "id": "{{ RESOURCE_ID }}", + "mode": "live", + "name": "Jonas Test BV", + "website": "https://example.com", + "email": "test@mollie.com", + "phone": "+31612345678", + "categoryCode": 6012, + "businessCategory": "MONEY_SERVICES", + "status": "verified", + "createdAt": "2021-12-08T15:42:58+00:00", + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "dashboard": { + "href": "https://www.mollie.com/dashboard/org_13514547/settings/profiles/pfl_85dxyKqNHa", + "type": "text/html" + }, + "chargebacks": { + "href": "https://api.mollie.com/v2/chargebacks", + "type": "application/hal+json" + }, + "methods": { + "href": "https://api.mollie.com/v2/methods", + "type": "application/hal+json" + }, + "payments": { + "href": "https://api.mollie.com/v2/payments", + "type": "application/hal+json" + }, + "refunds": { + "href": "https://api.mollie.com/v2/refunds", + "type": "application/hal+json" + }, + "checkoutPreviewUrl": { + "href": "https://www.mollie.com/checkout/preview/{{ RESOURCE_ID }}", + "type": "text/html" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/cursor-collection-next.json b/src/Fake/Responses/cursor-collection-next.json new file mode 100644 index 000000000..30d922dae --- /dev/null +++ b/src/Fake/Responses/cursor-collection-next.json @@ -0,0 +1,18 @@ +{ + "count": 1, + "_links": { + "self": { + "href": "https:\/\/api.mollie.com\/v2\/payments?from={{ RESOURCE_ID }}" + }, + "next": { + "href": "https:\/\/api.mollie.com\/v2\/payments?from={{ RESOURCE_ID }}" + } + }, + "_embedded": { + "payments": [ + { + "id": "{{ RESOURCE_ID }}" + } + ] + } +} diff --git a/src/Fake/Responses/cursor-collection.json b/src/Fake/Responses/cursor-collection.json new file mode 100644 index 000000000..36a035a94 --- /dev/null +++ b/src/Fake/Responses/cursor-collection.json @@ -0,0 +1,15 @@ +{ + "count": 1, + "_links": { + "self": { + "href": "https:\/\/api.mollie.com\/v2\/payments?from={{ RESOURCE_ID }}" + } + }, + "_embedded": { + "payments": [ + { + "id": "{{ RESOURCE_ID }}" + } + ] + } +} diff --git a/src/Fake/Responses/customer-list.json b/src/Fake/Responses/customer-list.json new file mode 100644 index 000000000..1b73d9557 --- /dev/null +++ b/src/Fake/Responses/customer-list.json @@ -0,0 +1,36 @@ +{ + "count": 5, + "_embedded": { + "customers": [ + { + "resource": "customer", + "id": "cst_8wmqcHMN4U", + "mode": "live", + "name": "John Doe", + "email": "customer@example.org", + "createdAt": "2023-04-06T13:10:19.0Z", + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + } + } + } + ] + }, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "previous": null, + "next": { + "href": "https://api.mollie.com/v2/customers?from=cst_stTC2WHAuS&limit=5", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/customer.json b/src/Fake/Responses/customer.json new file mode 100644 index 000000000..e1e9171d6 --- /dev/null +++ b/src/Fake/Responses/customer.json @@ -0,0 +1,27 @@ +{ + "resource": "customer", + "id": "{{ RESOURCE_ID }}", + "mode": "test", + "name": "Jane Doe", + "email": "test@mollie.com", + "locale": "en_US", + "metadata": { + "someProperty": "someValue", + "anotherProperty": "anotherValue" + }, + "createdAt": "2022-01-03T13:42:04+00:00", + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "dashboard": { + "href": "https://www.mollie.com/dashboard/org_13514547/customers/cst_tKt44u85MM", + "type": "text/html" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/empty-list.json b/src/Fake/Responses/empty-list.json new file mode 100644 index 000000000..e928366cd --- /dev/null +++ b/src/Fake/Responses/empty-list.json @@ -0,0 +1,18 @@ +{ + "count": 0, + "_embedded": { + "{{ RESOURCE_ID }}": [] + }, + "_links": { + "documentation": { + "href": "...", + "type": "text/html" + }, + "self": { + "href": "...", + "type": "application/hal+json" + }, + "previous": null, + "next": null + } +} diff --git a/src/Fake/Responses/invoice-list.json b/src/Fake/Responses/invoice-list.json new file mode 100644 index 000000000..b4a60461b --- /dev/null +++ b/src/Fake/Responses/invoice-list.json @@ -0,0 +1,61 @@ +{ + "count": 1, + "_embedded": { + "invoices": [ + { + "resource": "invoice", + "id": "inv_xBEbP9rvAq", + "reference": "2023.10000", + "vatNumber": "NL001234567B01", + "status": "open", + "netAmount": { + "currency": "EUR", + "value": "45.00" + }, + "vatAmount": { + "currency": "EUR", + "value": "9.45" + }, + "grossAmount": { + "currency": "EUR", + "value": "54.45" + }, + "lines": [ + { + "period": "2023-09", + "description": "iDEAL payment fees", + "count": 100, + "vatPercentage": 21, + "amount": { + "currency": "EUR", + "value": "45.00" + } + } + ], + "issuedAt": "2023-09-01", + "dueAt": "2023-09-14", + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + } + } + } + ] + }, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "previous": null, + "next": { + "href": "https://api.mollie.com/v2/invoices?from=inv_TUhzbAFMrt&limit=5", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/invoice.json b/src/Fake/Responses/invoice.json new file mode 100644 index 000000000..1b5157f25 --- /dev/null +++ b/src/Fake/Responses/invoice.json @@ -0,0 +1,47 @@ +{ + "resource": "invoice", + "id": "{{ RESOURCE_ID }}", + "reference": "2023.10000", + "vatNumber": "NL001234567B01", + "status": "open", + "netAmount": { + "currency": "EUR", + "value": "45.00" + }, + "vatAmount": { + "currency": "EUR", + "value": "9.45" + }, + "grossAmount": { + "currency": "EUR", + "value": "54.45" + }, + "lines": [ + { + "period": "2023-09", + "description": "iDEAL payment fees", + "count": 100, + "vatPercentage": 21, + "amount": { + "currency": "EUR", + "value": "45.00" + } + } + ], + "issuedAt": "2023-09-01", + "dueAt": "2023-09-14", + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "pdf": { + "href": "https://www.mollie.com/merchant/download/invoice/xBEbP9rvAq/2ab44d60b35b1d06090bba955fa2c602", + "type": "application/pdf" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/issuer.json b/src/Fake/Responses/issuer.json new file mode 100644 index 000000000..fbfca9f91 --- /dev/null +++ b/src/Fake/Responses/issuer.json @@ -0,0 +1,16 @@ +{ + "resource": "issuer", + "id": "festivalcadeau", + "description": "FestivalCadeau Giftcard", + "status": "pending-issuer", + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/mandate-list.json b/src/Fake/Responses/mandate-list.json new file mode 100644 index 000000000..9fb048740 --- /dev/null +++ b/src/Fake/Responses/mandate-list.json @@ -0,0 +1,44 @@ +{ + "count": 1, + "_embedded": { + "mandates": [ + { + "resource": "mandate", + "id": "mdt_h3gAaD5zP", + "mode": "live", + "status": "valid", + "method": "directdebit", + "details": {}, + "mandateReference": "EXAMPLE-CORP-MD13804", + "signatureDate": "2023-05-07", + "customerId": "cst_4qqhO89gsT", + "createdAt": "2023-05-07T10:49:08.0Z", + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "customer": { + "href": "https://api.mollie.com/v2/customers/cst_4qqhO89gsT", + "type": "application/hal+json" + } + } + } + ] + }, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "previous": null, + "next": { + "href": "https://api.mollie.com/v2/mandates?from=mdt_pWUnw6pkBN&limit=5", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/mandate.json b/src/Fake/Responses/mandate.json new file mode 100644 index 000000000..c961c0de8 --- /dev/null +++ b/src/Fake/Responses/mandate.json @@ -0,0 +1,30 @@ +{ + "resource": "mandate", + "id": "{{ RESOURCE_ID }}", + "mode": "live", + "status": "valid", + "method": "directdebit", + "details": { + "consumerName": "John Doe", + "consumerAccount": "NL55INGB0000000000", + "consumerBic": "INGBNL2A" + }, + "mandateReference": "EXAMPLE-CORP-MD13804", + "signatureDate": "2023-05-07", + "customerId": "cst_4qqhO89gsT", + "createdAt": "2023-05-07T10:49:08.0Z", + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "customer": { + "href": "https://api.mollie.com/v2/customers/cst_4qqhO89gsT", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/method-list.json b/src/Fake/Responses/method-list.json new file mode 100644 index 000000000..b45f37967 --- /dev/null +++ b/src/Fake/Responses/method-list.json @@ -0,0 +1,55 @@ +{ + "count": 2, + "_embedded": { + "methods": [ + { + "resource": "method", + "id": "ideal", + "description": "iDEAL", + "minimumAmount": { + "value": "0.01", + "currency": "EUR" + }, + "maximumAmount": { + "value": "50000.00", + "currency": "EUR" + }, + "image": { + "size1x": "https://mollie.com/external/icons/payment-methods/ideal.png", + "size2x": "https://mollie.com/external/icons/payment-methods/ideal%402x.png", + "svg": "https://mollie.com/external/icons/payment-methods/ideal.svg" + }, + "status": "activated" + }, + { + "resource": "method", + "id": "creditcard", + "description": "Credit card", + "minimumAmount": { + "value": "0.01", + "currency": "EUR" + }, + "maximumAmount": { + "value": "2000.00", + "currency": "EUR" + }, + "image": { + "size1x": "https://mollie.com/external/icons/payment-methods/creditcard.png", + "size2x": "https://mollie.com/external/icons/payment-methods/creditcard%402x.png", + "svg": "https://mollie.com/external/icons/payment-methods/creditcard.svg" + }, + "status": "activated" + } + ] + }, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/method.json b/src/Fake/Responses/method.json new file mode 100644 index 000000000..a40be508b --- /dev/null +++ b/src/Fake/Responses/method.json @@ -0,0 +1,29 @@ +{ + "resource": "method", + "id": "{{ RESOURCE_ID }}", + "description": "iDEAL", + "minimumAmount": { + "value": "0.01", + "currency": "EUR" + }, + "maximumAmount": { + "value": "50000.00", + "currency": "EUR" + }, + "image": { + "size1x": "https://mollie.com/external/icons/payment-methods/ideal.png", + "size2x": "https://mollie.com/external/icons/payment-methods/ideal%402x.png", + "svg": "https://mollie.com/external/icons/payment-methods/ideal.svg" + }, + "status": "activated", + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/onboarding.json b/src/Fake/Responses/onboarding.json new file mode 100644 index 000000000..174aef972 --- /dev/null +++ b/src/Fake/Responses/onboarding.json @@ -0,0 +1,26 @@ +{ + "resource": "onboarding", + "name": "Mollie B.V.", + "status": "completed", + "canReceivePayments": true, + "canReceiveSettlements": true, + "signedUpAt": "2023-12-20T10:49:08.0Z", + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "dashboard": { + "href": "https://www.mollie.com/dashboard/onboarding", + "type": "text/html" + }, + "organization": { + "href": "https://api.mollie.com/v2/organizations/org_12345678", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/organization.json b/src/Fake/Responses/organization.json new file mode 100644 index 000000000..2c2125d7c --- /dev/null +++ b/src/Fake/Responses/organization.json @@ -0,0 +1,29 @@ +{ + "resource": "organization", + "id": "{{ RESOURCE_ID }}", + "name": "Mollie B.V.", + "email": "info@mollie.com", + "locale": "nl_NL", + "address": { + "streetAndNumber": "Keizersgracht 126", + "postalCode": "1015 CW", + "city": "Amsterdam", + "country": "NL" + }, + "registrationNumber": "30204462", + "vatNumber": "NL815839091B01", + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "dashboard": { + "href": "https://mollie.com/dashboard/{{ RESOURCE_ID }}", + "type": "text/html" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/partner-status.json b/src/Fake/Responses/partner-status.json new file mode 100644 index 000000000..e847dfa68 --- /dev/null +++ b/src/Fake/Responses/partner-status.json @@ -0,0 +1,19 @@ +{ + "resource": "partner", + "partnerType": "signuplink", + "partnerContractSignedAt": "2023-03-20T13:59:02.0Z", + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "signuplink": { + "href": "https://www.mollie.com/dashboard/signup/exampleCode", + "type": "text/html" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/payment-link-list.json b/src/Fake/Responses/payment-link-list.json new file mode 100644 index 000000000..334e7fef9 --- /dev/null +++ b/src/Fake/Responses/payment-link-list.json @@ -0,0 +1,49 @@ +{ + "count": 5, + "_embedded": { + "payment_links": [ + { + "resource": "payment-link", + "id": "pl_4Y0eZitmBnQ6IDoMqZQKh", + "mode": "live", + "description": "Bicycle tires", + "amount": { + "currency": "EUR", + "value": "24.95" + }, + "archived": false, + "redirectUrl": "https://webshop.example.org/thanks", + "webhookUrl": "https://webshop.example.org/payment-links/webhook", + "profileId": "pfl_QkEhN94Ba", + "createdAt": "2021-03-20T09:29:56.0Z", + "expiresAt": "2023-06-06T11:00:00.0Z", + "reusable": false, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "paymentLink": { + "href": "https://payment-links.mollie.com/payment/4Y0eZitmBnQ6IDoMqZQKh", + "type": "text/html" + } + } + } + ] + }, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "previous": null, + "next": { + "href": "https://api.mollie.com/v2/payment-links?from=pl_ayGNzD4TYuQtUaxNyu8aH&limit=5", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/payment-link.json b/src/Fake/Responses/payment-link.json new file mode 100644 index 000000000..d87231dac --- /dev/null +++ b/src/Fake/Responses/payment-link.json @@ -0,0 +1,31 @@ +{ + "resource": "payment-link", + "id": "{{ RESOURCE_ID }}", + "mode": "live", + "description": "Bicycle tires", + "amount": { + "currency": "EUR", + "value": "24.95" + }, + "archived": false, + "redirectUrl": "https://webshop.example.org/thanks", + "webhookUrl": "https://webshop.example.org/payment-links/webhook", + "profileId": "pfl_QkEhN94Ba", + "createdAt": "2021-03-20T09:29:56.0Z", + "expiresAt": "2023-06-06T11:00:00.0Z", + "reusable": false, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "paymentLink": { + "href": "https://payment-links.mollie.com/payment/4Y0eZitmBnQ6IDoMqZQKh", + "type": "text/html" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/payment-list.json b/src/Fake/Responses/payment-list.json new file mode 100644 index 000000000..cb56f4c0a --- /dev/null +++ b/src/Fake/Responses/payment-list.json @@ -0,0 +1,57 @@ +{ + "count": 5, + "_embedded": { + "payments": [ + { + "resource": "payment", + "id": "tr_7UhSN1zuXS", + "mode": "live", + "status": "open", + "isCancelable": false, + "amount": { + "value": "75.00", + "currency": "GBP" + }, + "description": "Order #12345", + "method": "ideal", + "metadata": { + "order_id": "12345" + }, + "details": null, + "profileId": "pfl_QkEhN94Ba", + "redirectUrl": "https://webshop.example.org/order/12345/", + "createdAt": "2024-02-12T11:58:35.0Z", + "expiresAt": "2024-02-12T12:13:35.0Z", + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "checkout": { + "href": "https://www.mollie.com/checkout/issuer/select/ideal/7UhSN1zuXS", + "type": "text/html" + }, + "dashboard": { + "href": "https://www.mollie.com/dashboard/org_12345678/payments/tr_7UhSN1zuXS", + "type": "text/html" + } + } + } + ] + }, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "previous": null, + "next": { + "href": "https://api.mollie.com/v2/payments?from=tr_SDkzMggpvx&limit=5", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/payment-route.json b/src/Fake/Responses/payment-route.json new file mode 100644 index 000000000..db073f52b --- /dev/null +++ b/src/Fake/Responses/payment-route.json @@ -0,0 +1,13 @@ +{ + "resource": "route", + "id": "rt_9dk4al1n", + "amount": { + "value": "7.50", + "currency": "EUR" + }, + "destination": { + "type": "organization", + "organizationId": "org_23456" + }, + "releaseDate": "2026-01-01" +} diff --git a/src/Fake/Responses/payment.json b/src/Fake/Responses/payment.json new file mode 100644 index 000000000..79408d2c5 --- /dev/null +++ b/src/Fake/Responses/payment.json @@ -0,0 +1,37 @@ +{ + "resource": "payment", + "id": "{{ RESOURCE_ID }}", + "mode": "test", + "createdAt": "2018-03-13T14:02:29+00:00", + "amount": { + "value": "20.00", + "currency": "EUR" + }, + "description": "My first API payment", + "method": "ideal", + "metadata": { + "order_id": "1234" + }, + "status": "open", + "isCancelable": false, + "expiresAt": "2018-03-13T14:17:29+00:00", + "details": null, + "profileId": "pfl_2A1gacu42V", + "sequenceType": "oneoff", + "redirectUrl": "https://example.org/redirect", + "webhookUrl": "https://example.org/webhook", + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "checkout": { + "href": "...", + "type": "text/html" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/permission-list.json b/src/Fake/Responses/permission-list.json new file mode 100644 index 000000000..a06245400 --- /dev/null +++ b/src/Fake/Responses/permission-list.json @@ -0,0 +1,41 @@ +{ + "count": 2, + "_embedded": { + "permissions": [ + { + "resource": "permission", + "id": "payments.read", + "description": "View your payments", + "granted": true, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + } + } + }, + { + "resource": "permission", + "id": "payments.write", + "description": "Create new payments", + "granted": false, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + } + } + } + ] + }, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/permission.json b/src/Fake/Responses/permission.json new file mode 100644 index 000000000..efa881d71 --- /dev/null +++ b/src/Fake/Responses/permission.json @@ -0,0 +1,16 @@ +{ + "resource": "permission", + "id": "{{ RESOURCE_ID }}", + "description": "View your payments", + "granted": true, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/profile-list.json b/src/Fake/Responses/profile-list.json new file mode 100644 index 000000000..a5d609bac --- /dev/null +++ b/src/Fake/Responses/profile-list.json @@ -0,0 +1,43 @@ +{ + "count": 1, + "_embedded": { + "profiles": [ + { + "resource": "profile", + "id": "pfl_QkEhN94Ba", + "mode": "live", + "name": "My website name", + "website": "https://shop.example.org", + "email": "info@example.org", + "phone": "+31208202070", + "businessCategory": "OTHER_MERCHANDISE", + "status": "verified", + "review": { + "status": "pending" + }, + "createdAt": "2023-03-20T09:28:37.0Z", + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + } + } + } + ] + }, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "previous": null, + "next": { + "href": "https://api.mollie.com/v2/profiles?from=pfl_v9hTwCvYqw&limit=5", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/profile.json b/src/Fake/Responses/profile.json new file mode 100644 index 000000000..1ab701945 --- /dev/null +++ b/src/Fake/Responses/profile.json @@ -0,0 +1,29 @@ +{ + "resource": "profile", + "id": "{{ RESOURCE_ID }}", + "mode": "live", + "name": "My website name", + "website": "https://shop.example.org", + "email": "info@example.org", + "phone": "+31208202070", + "businessCategory": "OTHER_MERCHANDISE", + "status": "verified", + "review": { + "status": "pending" + }, + "createdAt": "2023-03-20T09:28:37.0Z", + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "dashboard": { + "href": "https://www.mollie.com/dashboard/org_123456789/settings/profiles/pfl_QkEhN94Ba", + "type": "text/html" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/refund-list.json b/src/Fake/Responses/refund-list.json new file mode 100644 index 000000000..3ee516be5 --- /dev/null +++ b/src/Fake/Responses/refund-list.json @@ -0,0 +1,48 @@ +{ + "count": 1, + "_embedded": { + "refunds": [ + { + "resource": "refund", + "id": "re_4qqhO89gsT", + "mode": "live", + "description": "Order", + "amount": { + "currency": "EUR", + "value": "5.95" + }, + "status": "pending", + "metadata": { + "bookkeeping_id": 12345 + }, + "paymentId": "tr_7UhSN1zuXS", + "createdAt": "2023-03-14T17:09:02.0Z", + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "payment": { + "href": "https://api.mollie.com/v2/payments/tr_7UhSN1zuXS", + "type": "application/hal+json" + } + } + } + ] + }, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "previous": null, + "next": { + "href": "https://api.mollie.com/v2/payments/tr_7UhSN1zuXS/refunds?from=re_APBiGPH2vV&limit=5", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/refund.json b/src/Fake/Responses/refund.json new file mode 100644 index 000000000..c7c5dfce2 --- /dev/null +++ b/src/Fake/Responses/refund.json @@ -0,0 +1,28 @@ +{ + "resource": "refund", + "id": "{{ RESOURCE_ID }}", + "mode": "live", + "description": "Order", + "amount": { + "currency": "EUR", + "value": "5.95" + }, + "status": "pending", + "metadata": "{\"bookkeeping_id\":12345}", + "paymentId": "tr_7UhSN1zuXS", + "createdAt": "2023-03-14T17:09:02.0Z", + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "payment": { + "href": "https://api.mollie.com/v2/payments/tr_7UhSN1zuXS", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/route.json b/src/Fake/Responses/route.json new file mode 100644 index 000000000..1be2ba472 --- /dev/null +++ b/src/Fake/Responses/route.json @@ -0,0 +1,13 @@ +{ + "resource": "route", + "id": "{{ RESOURCE_ID }}", + "amount": { + "value": "7.50", + "currency": "EUR" + }, + "destination": { + "type": "organization", + "organizationId": "org_23456" + }, + "releaseDate": "2026-01-01" +} diff --git a/src/Fake/Responses/sales-invoice-list.json b/src/Fake/Responses/sales-invoice-list.json new file mode 100644 index 000000000..fdd397d29 --- /dev/null +++ b/src/Fake/Responses/sales-invoice-list.json @@ -0,0 +1,83 @@ +{ + "count": 1, + "_embedded": { + "sales_invoices": [ + { + "resource": "sales-invoice", + "id": "invoice_4Y0eZitmBnQ6IDoMqZQKh", + "profileId": "pfl_QkEhN94Ba", + "invoiceNumber": null, + "currency": "EUR", + "status": "draft", + "vatScheme": "standard", + "paymentTerm": "30 days", + "recipientIdentifier": "123532354", + "recipient": { + "title": null, + "givenName": "Given", + "familyName": "Family", + "email": "given.family@mollie.com", + "phone": null, + "streetAndNumber": "Street 1", + "streetAdditional": null, + "postalCode": "1000 AA", + "city": "Amsterdam", + "region": null, + "country": "NL" + }, + "lines": [ + { + "description": "LEGO 4440 Forest Police Station", + "quantity": 1, + "vatRate": "21", + "unitPrice": { + "value": "89.00", + "currency": "EUR" + }, + "discount": null + } + ], + "discount": null, + "amountDue": { + "value": "107.69", + "currency": "EUR" + }, + "subtotalAmount": { + "value": "89.00", + "currency": "EUR" + }, + "totalAmount": { + "value": "107.69", + "currency": "EUR" + }, + "totalVatAmount": { + "value": "18.69", + "currency": "EUR" + }, + "discountedSubtotalAmount": { + "value": "89.00", + "currency": "EUR" + }, + "createdAt": "2024-10-03T10:47:38.457381+00:00", + "issuedAt": null, + "dueAt": null, + "memo": null + } + ] + }, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "previous": null, + "next": { + "href": "https://api.mollie.com/v2/sales/invoices?from=invoice_4yUfQpbKnd2DUTouUdUwH&limit=5", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/sales-invoice.json b/src/Fake/Responses/sales-invoice.json new file mode 100644 index 000000000..bda9bba00 --- /dev/null +++ b/src/Fake/Responses/sales-invoice.json @@ -0,0 +1,81 @@ +{ + "resource": "sales-invoice", + "id": "invoice_4Y0eZitmBnQ6IDoMqZQKh", + "profileId": "pfl_QkEhN94Ba", + "invoiceNumber": null, + "currency": "EUR", + "status": "draft", + "vatScheme": "standard", + "paymentTerm": "30 days", + "recipientIdentifier": "123532354", + "recipient": { + "type": "consumer", + "title": null, + "givenName": "Given", + "familyName": "Family", + "email": "given.family@mollie.com", + "phone": null, + "streetAndNumber": "Street 1", + "streetAdditional": null, + "postalCode": "1000 AA", + "city": "Amsterdam", + "region": null, + "country": "NL", + "locale": "nl_NL" + }, + "lines": [ + { + "description": "LEGO 4440 Forest Police Station", + "quantity": 1, + "vatRate": "21", + "unitPrice": { + "value": "89.00", + "currency": "EUR" + }, + "discount": null + } + ], + "discount": null, + "amountDue": { + "value": "107.69", + "currency": "EUR" + }, + "subtotalAmount": { + "value": "89.00", + "currency": "EUR" + }, + "totalAmount": { + "value": "107.69", + "currency": "EUR" + }, + "totalVatAmount": { + "value": "18.69", + "currency": "EUR" + }, + "discountedSubtotalAmount": { + "value": "89.00", + "currency": "EUR" + }, + "createdAt": "2024-10-03T10:47:38.457381+00:00", + "issuedAt": null, + "dueAt": null, + "memo": null, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "invoicePayment": { + "href": "...", + "type": "application/hal+json" + }, + "pdfLink": { + "href": "...", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/session-list.json b/src/Fake/Responses/session-list.json new file mode 100644 index 000000000..3ffdaa8b8 --- /dev/null +++ b/src/Fake/Responses/session-list.json @@ -0,0 +1,53 @@ +{ + "count": 1, + "_embedded": { + "sessions": [ + { + "resource": "session", + "id": "ses_*", + "mode": "live", + "status": "created", + "amount": { + "value": "10.00", + "currency": "EUR" + }, + "description": "Order #12345", + "method": "paypal", + "methodDetails": { + "checkoutFlow": "express" + }, + "nextAction": "redirect", + "createdAt": "2024-01-10T12:06:28+00:00", + "_links": { + "self": { + "href": "https://api.mollie.com/v2/sessions/ses_*", + "type": "application/hal+json" + }, + "redirect": { + "href": "https://paypalc.com/order/dghjfidf;gj", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } + } + ] + }, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "previous": null, + "next": { + "href": "https://api.mollie.com/v2/sessions?from=ses_*&limit=5", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/session.json b/src/Fake/Responses/session.json new file mode 100644 index 000000000..efc2b7b8d --- /dev/null +++ b/src/Fake/Responses/session.json @@ -0,0 +1,31 @@ +{ + "resource": "session", + "id": "{{ RESOURCE_ID }}", + "mode": "live", + "status": "created", + "amount": { + "value": "10.00", + "currency": "EUR" + }, + "description": "Order #12345", + "method": "paypal", + "methodDetails": { + "checkoutFlow": "express" + }, + "nextAction": "redirect", + "createdAt": "2024-01-10T12:06:28+00:00", + "_links": { + "self": { + "href": "https://api.mollie.com/v2/sessions/{{ RESOURCE_ID }}", + "type": "application/hal+json" + }, + "redirect": { + "href": "https://paypalc.com/order/dghjfidf;gj", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/settlement-list.json b/src/Fake/Responses/settlement-list.json new file mode 100644 index 000000000..e971f995f --- /dev/null +++ b/src/Fake/Responses/settlement-list.json @@ -0,0 +1,41 @@ +{ + "count": 1, + "_embedded": { + "settlements": [ + { + "resource": "settlement", + "id": "stl_jDk30akdN", + "reference": "1234567.2404.03", + "status": "paidout", + "amount": { + "currency": "EUR", + "value": "39.75" + }, + "balanceId": "bal_3kUf4yU2nT", + "periods": {}, + "settledAt": "2024-04-06T09:41:44.0Z", + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + } + } + } + ] + }, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "previous": null, + "next": { + "href": "https://api.mollie.com/v2/settlements?from=cst_stTC2WHAuS&limit=5", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/settlement.json b/src/Fake/Responses/settlement.json new file mode 100644 index 000000000..523b4d026 --- /dev/null +++ b/src/Fake/Responses/settlement.json @@ -0,0 +1,125 @@ +{ + "resource": "settlement", + "id": "{{ RESOURCE_ID }}", + "reference": "1234567.2404.03", + "status": "paidout", + "amount": { + "currency": "EUR", + "value": "39.75" + }, + "balanceId": "bal_3kUf4yU2nT", + "periods": { + "2024": { + "04": { + "revenue": [ + { + "description": "iDEAL", + "method": "ideal", + "count": 6, + "amountNet": { + "currency": "EUR", + "value": "86.1000" + }, + "amountVat": null, + "amountGross": { + "currency": "EUR", + "value": "86.1000" + } + }, + { + "description": "Refunds iDEAL", + "method": "refund", + "count": 2, + "amountNet": { + "currency": "EUR", + "value": "-43.2000" + }, + "amountVat": null, + "amountGross": { + "currency": "EUR", + "value": "-43.2000" + } + } + ], + "costs": [ + { + "description": "iDEAL", + "method": "ideal", + "count": 6, + "rate": { + "fixed": { + "currency": "EUR", + "value": "0.3500" + }, + "percentage": null + }, + "amountNet": { + "currency": "EUR", + "value": "2.1000" + }, + "amountVat": { + "currency": "EUR", + "value": "0.4410" + }, + "amountGross": { + "currency": "EUR", + "value": "2.5410" + } + }, + { + "description": "Refunds iDEAL", + "method": "refund", + "count": 2, + "rate": { + "fixed": { + "currency": "EUR", + "value": "0.2500" + }, + "percentage": null + }, + "amountNet": { + "currency": "EUR", + "value": "0.5000" + }, + "amountVat": { + "currency": "EUR", + "value": "0.1050" + }, + "amountGross": { + "currency": "EUR", + "value": "0.6050" + } + } + ], + "invoiceId": "inv_FrvewDA3Pr" + } + } + }, + "settledAt": "2024-04-06T09:41:44.0Z", + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "payments": { + "href": "https://api.mollie.com/v2/settlements/{{ RESOURCE_ID }}/payments", + "type": "application/hal+json" + }, + "refunds": { + "href": "https://api.mollie.com/v2/settlements/{{ RESOURCE_ID }}/refunds", + "type": "application/hal+json" + }, + "chargebacks": { + "href": "https://api.mollie.com/v2/settlements/{{ RESOURCE_ID }}/chargebacks", + "type": "application/hal+json" + }, + "captures": { + "href": "https://api.mollie.com/v2/settlements/{{ RESOURCE_ID }}/captures", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/subscription-list.json b/src/Fake/Responses/subscription-list.json new file mode 100644 index 000000000..c0a47b7d2 --- /dev/null +++ b/src/Fake/Responses/subscription-list.json @@ -0,0 +1,53 @@ +{ + "count": 1, + "_embedded": { + "subscriptions": [ + { + "resource": "subscription", + "id": "sub_rVKGtNd6s3", + "mode": "live", + "amount": { + "currency": "EUR", + "value": "25.00" + }, + "times": 4, + "timesRemaining": 4, + "interval": "3 months", + "startDate": "2023-06-01", + "nextPaymentDate": "2023-09-01", + "description": "Quarterly payment", + "method": null, + "status": "active", + "webhookUrl": "https://webshop.example.org/payments/webhook", + "customerId": "cst_stTC2WHAuS", + "mandateId": "mdt_38HS4fsS", + "createdAt": "2023-04-06T13:10:19.0Z", + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "customer": { + "href": "https://api.mollie.com/v2/customers/cst_stTC2WHAuS", + "type": "application/hal+json" + } + } + } + ] + }, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "previous": null, + "next": { + "href": "https://api.mollie.com/v2/subscriptions?from=sub_mnXbwhMfvo&limit=5", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/subscription.json b/src/Fake/Responses/subscription.json new file mode 100644 index 000000000..7ff63ff86 --- /dev/null +++ b/src/Fake/Responses/subscription.json @@ -0,0 +1,35 @@ +{ + "resource": "subscription", + "id": "{{ RESOURCE_ID }}", + "mode": "live", + "amount": { + "currency": "EUR", + "value": "25.00" + }, + "times": 4, + "timesRemaining": 4, + "interval": "3 months", + "startDate": "2023-06-01", + "nextPaymentDate": "2023-09-01", + "description": "Quarterly payment", + "method": null, + "status": "active", + "webhookUrl": "https://webshop.example.org/payments/webhook", + "customerId": "cst_stTC2WHAuS", + "mandateId": "mdt_38HS4fsS", + "createdAt": "2023-04-06T13:10:19.0Z", + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "customer": { + "href": "https://api.mollie.com/v2/customers/cst_stTC2WHAuS", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/terminal-list.json b/src/Fake/Responses/terminal-list.json new file mode 100644 index 000000000..bf081f8f6 --- /dev/null +++ b/src/Fake/Responses/terminal-list.json @@ -0,0 +1,41 @@ +{ + "count": 1, + "_embedded": { + "terminals": [ + { + "resource": "terminal", + "id": "term_7MgL4wea46qkRcoTZjWEH", + "mode": "live", + "status": "active", + "brand": "PAX", + "model": "A920", + "serialNumber": "1234567890", + "currency": "EUR", + "description": "Terminal #12345", + "profileId": "pfl_QkEhN94Ba", + "createdAt": "2022-02-12T11:58:35.0Z", + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + } + } + } + ] + }, + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "previous": null, + "next": { + "href": "...", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/terminal.json b/src/Fake/Responses/terminal.json new file mode 100644 index 000000000..42f91bcff --- /dev/null +++ b/src/Fake/Responses/terminal.json @@ -0,0 +1,23 @@ +{ + "resource": "terminal", + "id": "{{ RESOURCE_ID }}", + "mode": "live", + "status": "active", + "brand": "PAX", + "model": "A920", + "serialNumber": "1234567890", + "currency": "EUR", + "description": "Terminal #12345", + "profileId": "pfl_QkEhN94Ba", + "createdAt": "2022-02-12T11:58:35.0Z", + "_links": { + "self": { + "href": "...", + "type": "application/hal+json" + }, + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/unprocessable-entity-with-field.json b/src/Fake/Responses/unprocessable-entity-with-field.json new file mode 100644 index 000000000..e0d977c08 --- /dev/null +++ b/src/Fake/Responses/unprocessable-entity-with-field.json @@ -0,0 +1,12 @@ +{ + "status": 422, + "title": "Unprocessable Entity", + "detail": "Non-existent parameter \"recurringType\" for this API call. Did you mean: \"sequenceType\"?", + "field": "recurringType", + "_links": { + "documentation": { + "href": "...", + "type": "text/html" + } + } +} diff --git a/src/Fake/Responses/unprocessable-entity.json b/src/Fake/Responses/unprocessable-entity.json new file mode 100644 index 000000000..1a1617c56 --- /dev/null +++ b/src/Fake/Responses/unprocessable-entity.json @@ -0,0 +1,5 @@ +{ + "status": 422, + "title": "Unprocessable Entity", + "detail": "Non-existent parameter \"recurringType\" for this API call. Did you mean: \"sequenceType\"?" +} diff --git a/src/Fake/SequenceMockResponse.php b/src/Fake/SequenceMockResponse.php new file mode 100644 index 000000000..a6c0f16a1 --- /dev/null +++ b/src/Fake/SequenceMockResponse.php @@ -0,0 +1,38 @@ + + */ + private array $responses; + + private int $index = 0; + + public function __construct(...$responses) + { + $this->responses = $responses; + } + + public function pop(): MockResponse + { + if (! isset($this->responses[$this->index])) { + throw new \RuntimeException('No more responses available.'); + } + + $response = $this->responses[$this->index]; + + unset($this->responses[$this->index]); + + $this->index++; + + return $response; + } + + public function isEmpty(): bool + { + return count($this->responses) === 0; + } +} diff --git a/src/Http/Adapter/CurlMollieHttpAdapter.php b/src/Http/Adapter/CurlMollieHttpAdapter.php new file mode 100644 index 000000000..8a0a1dd8a --- /dev/null +++ b/src/Http/Adapter/CurlMollieHttpAdapter.php @@ -0,0 +1,233 @@ +send($pendingRequest); + + return $this->createResponse($pendingRequest, $statusCode, $headers, $body); + } catch (CurlConnectTimeoutException $e) { + return $this->createResponse($pendingRequest, 504, [], null, $e); + } + } + } + + protected function createResponse(PendingRequest $pendingRequest, int $statusCode, $headers = [], $body = null, ?Throwable $error = null): Response + { + $factoryCollection = $pendingRequest->getFactoryCollection(); + $responseFactory = $factoryCollection->responseFactory; + + $response = $responseFactory->createResponse($statusCode) + ->withBody($factoryCollection->streamFactory->createStream($body)); + + foreach ($headers as $key => $value) { + $response = $response->withHeader($key, $value); + } + + return new Response( + $response, + $pendingRequest->createPsrRequest(), + $pendingRequest, + $error + ); + } + + /** + * @throws \Mollie\Api\Exceptions\ApiException + */ + protected function send(PendingRequest $pendingRequest): array + { + $request = $pendingRequest->createPsrRequest(); + + $curl = $this->initializeCurl($request->getUri()); + $this->setCurlHeaders($curl, $pendingRequest->headers()->all()); + $this->setCurlMethodOptions($curl, $pendingRequest->method(), $request->getBody()); + + $startTime = microtime(true); + $response = curl_exec($curl); + $endTime = microtime(true); + + if ($response === false) { + $this->handleCurlError($curl, $endTime - $startTime); + } + + [$headers, $content, $statusCode] = $this->extractResponseDetails($curl, $response); + curl_close($curl); + + return [$headers, $content, $statusCode]; + } + + private function initializeCurl(string $url) + { + $curl = curl_init($url); + + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_HEADER, true); + curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, self::DEFAULT_CONNECT_TIMEOUT); + curl_setopt($curl, CURLOPT_TIMEOUT, self::DEFAULT_TIMEOUT); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true); + curl_setopt($curl, CURLOPT_CAINFO, CaBundle::getBundledCaBundlePath()); + + return $curl; + } + + private function setCurlHeaders($curl, array $headers) + { + $headers['Content-Type'] = 'application/json'; + + curl_setopt($curl, CURLOPT_HTTPHEADER, $this->parseHeaders($headers)); + } + + private function setCurlMethodOptions($curl, string $method, ?string $body): void + { + switch ($method) { + case Method::POST: + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, $body); + + break; + + case Method::PATCH: + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, Method::PATCH); + curl_setopt($curl, CURLOPT_POSTFIELDS, $body); + + break; + + case Method::DELETE: + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, Method::DELETE); + curl_setopt($curl, CURLOPT_POSTFIELDS, $body); + + break; + + case Method::GET: + default: + if ($method !== Method::GET) { + throw new \InvalidArgumentException('Invalid HTTP method: '.$method); + } + + break; + } + } + + private function handleCurlError($curl, float $executionTime): void + { + $curlErrorNumber = curl_errno($curl); + $curlErrorMessage = 'Curl error: '.curl_error($curl); + + if ($this->isConnectTimeoutError($curlErrorNumber, $executionTime)) { + throw new CurlConnectTimeoutException('Unable to connect to Mollie. '.$curlErrorMessage); + } + + throw new ApiException($curlErrorMessage); + } + + private function extractResponseDetails($curl, string $response): array + { + $headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE); + $headerValues = substr($response, 0, $headerSize); + $content = substr($response, $headerSize); + $statusCode = curl_getinfo($curl, CURLINFO_RESPONSE_CODE); + + $headers = []; + $headerLines = explode("\r\n", $headerValues); + foreach ($headerLines as $headerLine) { + if (strpos($headerLine, ':') !== false) { + [$key, $value] = explode(': ', $headerLine, 2); + $headers[$key] = $value; + } + } + + return [$headers, $content, $statusCode]; + } + + /** + * @param string|float $executionTime + */ + protected function isConnectTimeoutError(int $curlErrorNumber, $executionTime): bool + { + $connectErrors = [ + \CURLE_COULDNT_RESOLVE_HOST => true, + \CURLE_COULDNT_CONNECT => true, + \CURLE_SSL_CONNECT_ERROR => true, + \CURLE_GOT_NOTHING => true, + ]; + + if (isset($connectErrors[$curlErrorNumber])) { + return true; + } + + if ($curlErrorNumber === \CURLE_OPERATION_TIMEOUTED) { + if ($executionTime > self::DEFAULT_TIMEOUT) { + return false; + } + + return true; + } + + return false; + } + + private function parseHeaders(array $headers): array + { + $result = []; + + foreach ($headers as $key => $value) { + $result[] = $key.': '.$value; + } + + return $result; + } + + /** + * The version number for the underlying http client, if available. + * + * @example Guzzle/6.3 + */ + public function version(): string + { + return 'Curl/*'; + } +} diff --git a/src/Http/Adapter/GuzzleMollieHttpAdapter.php b/src/Http/Adapter/GuzzleMollieHttpAdapter.php new file mode 100644 index 000000000..5500bbab0 --- /dev/null +++ b/src/Http/Adapter/GuzzleMollieHttpAdapter.php @@ -0,0 +1,137 @@ +httpClient = $httpClient; + } + + public function factories(): Factories + { + $factory = new HttpFactory; + + return new Factories( + $factory, + $factory, + $factory, + $factory, + ); + } + + /** + * Instantiate a default adapter with sane configuration for Guzzle 6 or 7. + */ + public static function createDefault(): self + { + $retryMiddlewareFactory = new GuzzleRetryMiddlewareFactory; + $handlerStack = HandlerStack::create(); + $handlerStack->push($retryMiddlewareFactory->retry()); + + $client = new Client([ + GuzzleRequestOptions::VERIFY => CaBundle::getBundledCaBundlePath(), + GuzzleRequestOptions::TIMEOUT => self::DEFAULT_TIMEOUT, + GuzzleRequestOptions::CONNECT_TIMEOUT => self::DEFAULT_CONNECT_TIMEOUT, + 'handler' => $handlerStack, + ]); + + return new GuzzleMollieHttpAdapter($client); + } + + /** + * Send a request to the specified Mollie api url. + * + * @throws \Mollie\Api\Exceptions\ApiException + */ + public function sendRequest(PendingRequest $pendingRequest): Response + { + $request = $pendingRequest->createPsrRequest(); + + try { + $response = $this->httpClient->send($request, ['http_errors' => false]); + + return $this->createResponse($response, $request, $pendingRequest); + } catch (ConnectException $e) { + if (! $this->debug) { + $request = null; + } + + throw new ApiException($e->getMessage(), $e->getCode(), null, $request, null); + } catch (RequestException $e) { + // Prevent sensitive request data from ending up in exception logs unintended + if (! $this->debug) { + $request = null; + } + + return $this->createResponse($e->getResponse(), $request, $pendingRequest, $e); + } + } + + /** + * Create a response. + */ + protected function createResponse( + ResponseInterface $psrResponse, + RequestInterface $psrRequest, + PendingRequest $pendingRequest, + ?Throwable $exception = null + ): Response { + return new Response( + $psrResponse, + $psrRequest, + $pendingRequest, + $exception + ); + } + + /** + * The version number for the underlying http client, if available. + * This is used to report the UserAgent to Mollie, for convenient support. + * + * @example Guzzle/7.0 + */ + public function version(): string + { + return 'Guzzle/'.ClientInterface::MAJOR_VERSION; + } +} diff --git a/src/HttpAdapter/Guzzle6And7RetryMiddlewareFactory.php b/src/Http/Adapter/GuzzleRetryMiddlewareFactory.php similarity index 76% rename from src/HttpAdapter/Guzzle6And7RetryMiddlewareFactory.php rename to src/Http/Adapter/GuzzleRetryMiddlewareFactory.php index a0543e083..2118dfec5 100644 --- a/src/HttpAdapter/Guzzle6And7RetryMiddlewareFactory.php +++ b/src/Http/Adapter/GuzzleRetryMiddlewareFactory.php @@ -1,6 +1,6 @@ newRetryDecider(), @@ -36,10 +34,8 @@ public function retry($delay = true) /** * Returns a method that takes the number of retries and returns the number of milliseconds * to wait - * - * @return callable */ - private function getRetryDelay() + private function getRetryDelay(): callable { return function ($numberOfRetries) { return static::DELAY_INCREASE_MS * $numberOfRetries; @@ -48,20 +44,15 @@ private function getRetryDelay() /** * Returns a method that returns zero milliseconds to wait - * - * @return callable */ - private function getZeroRetryDelay() + private function getZeroRetryDelay(): callable { return function ($numberOfRetries) { return 0; }; } - /** - * @return callable - */ - private function newRetryDecider() + private function newRetryDecider(): callable { return function ( $retries, diff --git a/src/HttpAdapter/MollieHttpAdapterPicker.php b/src/Http/Adapter/MollieHttpAdapterPicker.php similarity index 61% rename from src/HttpAdapter/MollieHttpAdapterPicker.php rename to src/Http/Adapter/MollieHttpAdapterPicker.php index 41615d744..77261d1eb 100644 --- a/src/HttpAdapter/MollieHttpAdapterPicker.php +++ b/src/Http/Adapter/MollieHttpAdapterPicker.php @@ -1,54 +1,49 @@ guzzleIsDetected()) { $guzzleVersion = $this->guzzleMajorVersionNumber(); if ($guzzleVersion && in_array($guzzleVersion, [6, 7])) { - return Guzzle6And7MollieHttpAdapter::createDefault(); + return GuzzleMollieHttpAdapter::createDefault(); } } return new CurlMollieHttpAdapter; } - if ($httpClient instanceof MollieHttpAdapterInterface) { + if ($httpClient instanceof HttpAdapterContract) { return $httpClient; } if ($httpClient instanceof \GuzzleHttp\ClientInterface) { - return new Guzzle6And7MollieHttpAdapter($httpClient); + return new GuzzleMollieHttpAdapter($httpClient); } throw new UnrecognizedClientException('The provided http client or adapter was not recognized.'); } - /** - * @return bool - */ - private function guzzleIsDetected() + private function guzzleIsDetected(): bool { - return interface_exists('\\' . \GuzzleHttp\ClientInterface::class); + return interface_exists('\\'.\GuzzleHttp\ClientInterface::class); } - /** - * @return int|null - */ - private function guzzleMajorVersionNumber() + private function guzzleMajorVersionNumber(): ?int { // Guzzle 7 if (defined('\GuzzleHttp\ClientInterface::MAJOR_VERSION')) { diff --git a/src/Http/Adapter/PSR18MollieHttpAdapter.php b/src/Http/Adapter/PSR18MollieHttpAdapter.php new file mode 100644 index 000000000..7e2f082cb --- /dev/null +++ b/src/Http/Adapter/PSR18MollieHttpAdapter.php @@ -0,0 +1,97 @@ +httpClient = $httpClient; + $this->requestFactory = $requestFactory; + $this->responseFactory = $responseFactory; + $this->streamFactory = $streamFactory; + $this->uriFactory = $uriFactory; + } + + public function factories(): Factories + { + return new Factories( + $this->requestFactory, + $this->responseFactory, + $this->streamFactory, + $this->uriFactory, + ); + } + + /** + * {@inheritdoc} + */ + public function sendRequest(PendingRequest $pendingRequest): Response + { + $request = $pendingRequest->createPsrRequest(); + + try { + $response = $this->httpClient->sendRequest($request); + + return new Response( + $response, + $request, + $pendingRequest + ); + } catch (ClientExceptionInterface $e) { + if (! $this->debug) { + $request = null; + } + + throw new ApiException( + 'Error while sending request to Mollie API: '.$e->getMessage(), + 0, + $e, + $request, + null + ); + } + } + + /** + * {@inheritdoc} + */ + public function version(): string + { + return 'PSR18MollieHttpAdapter'; + } +} diff --git a/src/Http/Auth/AccessTokenAuthenticator.php b/src/Http/Auth/AccessTokenAuthenticator.php new file mode 100644 index 000000000..2efd1b9d2 --- /dev/null +++ b/src/Http/Auth/AccessTokenAuthenticator.php @@ -0,0 +1,18 @@ +token = trim($token); + } + + public function authenticate(PendingRequest $pendingRequest): void + { + $pendingRequest->headers()->add('Authorization', "Bearer {$this->token}"); + } +} diff --git a/src/Http/Data/Address.php b/src/Http/Data/Address.php new file mode 100644 index 000000000..dcd4c26e8 --- /dev/null +++ b/src/Http/Data/Address.php @@ -0,0 +1,81 @@ +title = $title; + $this->givenName = $givenName; + $this->familyName = $familyName; + $this->organizationName = $organizationName; + $this->streetAndNumber = $streetAndNumber; + $this->streetAdditional = $streetAdditional; + $this->postalCode = $postalCode; + $this->email = $email; + $this->phone = $phone; + $this->city = $city; + $this->region = $region; + $this->country = $country; + } + + public function toArray(): array + { + return [ + 'title' => $this->title, + 'givenName' => $this->givenName, + 'familyName' => $this->familyName, + 'organizationName' => $this->organizationName, + 'streetAndNumber' => $this->streetAndNumber, + 'streetAdditional' => $this->streetAdditional, + 'postalCode' => $this->postalCode, + 'email' => $this->email, + 'phone' => $this->phone, + 'city' => $this->city, + 'region' => $this->region, + 'country' => $this->country, + ]; + } +} diff --git a/src/Http/Data/AnyData.php b/src/Http/Data/AnyData.php new file mode 100644 index 000000000..b47be321f --- /dev/null +++ b/src/Http/Data/AnyData.php @@ -0,0 +1,23 @@ +data = $data; + } + + public function toArray(): array + { + return $this->data ?? []; + } +} diff --git a/src/Http/Data/ApplicationFee.php b/src/Http/Data/ApplicationFee.php new file mode 100644 index 000000000..0b66a5e5c --- /dev/null +++ b/src/Http/Data/ApplicationFee.php @@ -0,0 +1,28 @@ +amount = $amount; + $this->description = $description; + } + + public function toArray(): array + { + return [ + 'amount' => $this->amount, + 'description' => $this->description, + ]; + } +} diff --git a/src/Http/Data/CreateClientLinkPayload.php b/src/Http/Data/CreateClientLinkPayload.php new file mode 100644 index 000000000..6c3efdaad --- /dev/null +++ b/src/Http/Data/CreateClientLinkPayload.php @@ -0,0 +1,43 @@ +owner = $owner; + $this->name = $name; + $this->address = $address; + $this->registrationNumber = $registrationNumber; + $this->vatNumber = $vatNumber; + } + + public function toArray(): array + { + return [ + 'owner' => $this->owner, + 'name' => $this->name, + 'address' => $this->address, + 'registrationNumber' => $this->registrationNumber, + 'vatNumber' => $this->vatNumber, + ]; + } +} diff --git a/src/Http/Data/CreateCustomerPayload.php b/src/Http/Data/CreateCustomerPayload.php new file mode 100644 index 000000000..ca4577303 --- /dev/null +++ b/src/Http/Data/CreateCustomerPayload.php @@ -0,0 +1,38 @@ +name = $name; + $this->email = $email; + $this->locale = $locale; + $this->metadata = $metadata; + } + + public function toArray(): array + { + return [ + 'name' => $this->name, + 'email' => $this->email, + 'locale' => $this->locale, + 'metadata' => $this->metadata, + ]; + } +} diff --git a/src/Http/Data/CreateMandatePayload.php b/src/Http/Data/CreateMandatePayload.php new file mode 100644 index 000000000..06a212f95 --- /dev/null +++ b/src/Http/Data/CreateMandatePayload.php @@ -0,0 +1,59 @@ +method = $method; + $this->consumerName = $consumerName; + $this->consumerAccount = $consumerAccount; + $this->consumerBic = $consumerBic; + $this->consumerEmail = $consumerEmail; + $this->signatureDate = $signatureDate; + $this->mandateReference = $mandateReference; + $this->paypalBillingAgreementId = $paypalBillingAgreementId; + } + + public function toArray(): array + { + return [ + 'method' => $this->method, + 'consumerName' => $this->consumerName, + 'consumerAccount' => $this->consumerAccount, + 'consumerBic' => $this->consumerBic, + 'consumerEmail' => $this->consumerEmail, + 'signatureDate' => $this->signatureDate ? $this->signatureDate->format('Y-m-d') : null, + 'mandateReference' => $this->mandateReference, + 'paypalBillingAgreementId' => $this->paypalBillingAgreementId, + ]; + } +} diff --git a/src/Http/Data/CreatePaymentCapturePayload.php b/src/Http/Data/CreatePaymentCapturePayload.php new file mode 100644 index 000000000..898cc0f95 --- /dev/null +++ b/src/Http/Data/CreatePaymentCapturePayload.php @@ -0,0 +1,33 @@ +amount = $amount; + $this->description = $description; + $this->metadata = $metadata; + } + + public function toArray(): array + { + return [ + 'description' => $this->description, + 'amount' => $this->amount, + 'metadata' => $this->metadata, + ]; + } +} diff --git a/src/Http/Data/CreatePaymentLinkPayload.php b/src/Http/Data/CreatePaymentLinkPayload.php new file mode 100644 index 000000000..3cd539280 --- /dev/null +++ b/src/Http/Data/CreatePaymentLinkPayload.php @@ -0,0 +1,54 @@ +description = $description; + $this->amount = $amount; + $this->redirectUrl = $redirectUrl; + $this->webhookUrl = $webhookUrl; + $this->profileId = $profileId; + $this->reusable = $reusable; + $this->expiresAt = $expiresAt; + } + + public function toArray(): array + { + return [ + 'description' => $this->description, + 'amount' => $this->amount, + 'redirectUrl' => $this->redirectUrl, + 'webhookUrl' => $this->webhookUrl, + 'profileId' => $this->profileId, + 'reusable' => $this->reusable, + 'expiresAt' => $this->expiresAt ? $this->expiresAt->format('Y-m-d') : null, + ]; + } +} diff --git a/src/Http/Data/CreatePaymentPayload.php b/src/Http/Data/CreatePaymentPayload.php new file mode 100644 index 000000000..9a0cbd5ef --- /dev/null +++ b/src/Http/Data/CreatePaymentPayload.php @@ -0,0 +1,138 @@ +|null + */ + public ?DataCollection $lines; + + public ?Address $billingAddress; + + public ?Address $shippingAddress; + + public ?string $locale; + + public ?string $method; + + public ?string $issuer; + + public ?string $restrictPaymentMethodsToCountry; + + public ?Metadata $metadata; + + public ?string $captureMode; + + public ?string $captureDelay; + + public ?ApplicationFee $applicationFee; + + /** + * @var DataCollection|null + */ + public ?DataCollection $routing; + + public ?string $sequenceType; + + public ?string $mandateId; + + public ?string $customerId; + + public ?string $profileId; + + /** + * Method specific data. + * + * s. https://docs.mollie.com/reference/extra-payment-parameters#payment-creation-request-parameters + */ + public array $additional = []; + + public function __construct( + string $description, + Money $amount, + ?string $redirectUrl = null, + ?string $cancelUrl = null, + ?string $webhookUrl = null, + ?DataCollection $lines = null, + ?Address $billingAddress = null, + ?Address $shippingAddress = null, + ?string $locale = null, + ?string $method = null, + ?string $issuer = null, + ?string $restrictPaymentMethodsToCountry = null, + ?Metadata $metadata = null, + ?string $captureMode = null, + ?string $captureDelay = null, + ?ApplicationFee $applicationFee = null, + ?DataCollection $routing = null, + ?string $sequenceType = null, + ?string $mandateId = null, + ?string $customerId = null, + ?string $profileId = null, + array $additional = [] + ) { + $this->description = $description; + $this->amount = $amount; + $this->redirectUrl = $redirectUrl; + $this->cancelUrl = $cancelUrl; + $this->webhookUrl = $webhookUrl; + $this->lines = $lines; + $this->billingAddress = $billingAddress; + $this->shippingAddress = $shippingAddress; + $this->locale = $locale; + $this->method = $method; + $this->issuer = $issuer; + $this->restrictPaymentMethodsToCountry = $restrictPaymentMethodsToCountry; + $this->metadata = $metadata; + $this->captureMode = $captureMode; + $this->captureDelay = $captureDelay; + $this->applicationFee = $applicationFee; + $this->routing = $routing; + $this->sequenceType = $sequenceType; + $this->mandateId = $mandateId; + $this->customerId = $customerId; + $this->profileId = $profileId; + $this->additional = $additional; + } + + public function toArray(): array + { + return array_merge([ + 'description' => $this->description, + 'amount' => $this->amount, + 'redirectUrl' => $this->redirectUrl, + 'cancelUrl' => $this->cancelUrl, + 'webhookUrl' => $this->webhookUrl, + 'lines' => $this->lines, + 'billingAddress' => $this->billingAddress, + 'shippingAddress' => $this->shippingAddress, + 'locale' => $this->locale, + 'method' => $this->method, + 'issuer' => $this->issuer, + 'restrictPaymentMethodsToCountry' => $this->restrictPaymentMethodsToCountry, + 'metadata' => $this->metadata, + 'captureMode' => $this->captureMode, + 'captureDelay' => $this->captureDelay, + 'applicationFee' => $this->applicationFee, + 'routing' => $this->routing, + 'sequenceType' => $this->sequenceType, + 'mandateId' => $this->mandateId, + 'customerId' => $this->customerId, + 'profileId' => $this->profileId, + ], $this->additional); + } +} diff --git a/src/Http/Data/CreatePaymentQuery.php b/src/Http/Data/CreatePaymentQuery.php new file mode 100644 index 000000000..d40c81fa5 --- /dev/null +++ b/src/Http/Data/CreatePaymentQuery.php @@ -0,0 +1,27 @@ +includeQrCode = $includeQrCode; + } + + public function toArray(): array + { + return [ + 'include' => $this->includeQrCode ? PaymentQuery::INCLUDE_QR_CODE : null, + ]; + } +} diff --git a/src/Http/Data/CreateProfilePayload.php b/src/Http/Data/CreateProfilePayload.php new file mode 100644 index 000000000..2d3a3e173 --- /dev/null +++ b/src/Http/Data/CreateProfilePayload.php @@ -0,0 +1,53 @@ +name = $name; + $this->website = $website; + $this->email = $email; + $this->phone = $phone; + $this->description = $description; + $this->countriesOfActivity = $countriesOfActivity; + $this->businessCategory = $businessCategory; + } + + public function toArray(): array + { + return [ + 'name' => $this->name, + 'website' => $this->website, + 'email' => $this->email, + 'phone' => $this->phone, + 'description' => $this->description, + 'countriesOfActivity' => $this->countriesOfActivity, + 'businessCategory' => $this->businessCategory, + ]; + } +} diff --git a/src/Http/Data/CreateRefundPaymentPayload.php b/src/Http/Data/CreateRefundPaymentPayload.php new file mode 100644 index 000000000..e1212fd78 --- /dev/null +++ b/src/Http/Data/CreateRefundPaymentPayload.php @@ -0,0 +1,46 @@ + + */ + public ?DataCollection $routingReversals = null; + + public function __construct( + string $description, + Money $amount, + ?Metadata $metadata = null, + ?bool $reverseRouting = null, + ?DataCollection $routingReversals = null + ) { + $this->description = $description; + $this->amount = $amount; + $this->metadata = $metadata; + $this->reverseRouting = $reverseRouting; + $this->routingReversals = $routingReversals; + } + + public function toArray(): array + { + return [ + 'description' => $this->description, + 'amount' => $this->amount, + 'metadata' => $this->metadata, + 'reverseRouting' => $this->reverseRouting, + 'routingReversals' => $this->routingReversals, + ]; + } +} diff --git a/src/Http/Data/CreateSalesInvoicePayload.php b/src/Http/Data/CreateSalesInvoicePayload.php new file mode 100644 index 000000000..104b12815 --- /dev/null +++ b/src/Http/Data/CreateSalesInvoicePayload.php @@ -0,0 +1,94 @@ + + */ + public DataCollection $lines; + + public ?string $webhookUrl; + + public ?Discount $discount; + + public function __construct( + string $currency, + string $status, + string $vatScheme, + string $vatMode, + string $paymentTerm, + string $recipientIdentifier, + Recipient $recipient, + DataCollection $lines, + ?string $profileId = null, + ?string $memo = null, + ?PaymentDetails $paymentDetails = null, + ?EmailDetails $emailDetails = null, + ?string $webhookUrl = null, + ?Discount $discount = null + ) { + $this->profileId = $profileId; + $this->currency = $currency; + $this->status = $status; + $this->vatScheme = $vatScheme; + $this->vatMode = $vatMode; + $this->memo = $memo; + $this->paymentTerm = $paymentTerm; + $this->paymentDetails = $paymentDetails; + $this->emailDetails = $emailDetails; + $this->recipientIdentifier = $recipientIdentifier; + $this->recipient = $recipient; + $this->lines = $lines; + $this->webhookUrl = $webhookUrl; + $this->discount = $discount; + } + + public function toArray(): array + { + return [ + 'profileId' => $this->profileId, + 'currency' => $this->currency, + 'status' => $this->status, + 'vatScheme' => $this->vatScheme, + 'vatMode' => $this->vatMode, + 'memo' => $this->memo, + 'paymentTerm' => $this->paymentTerm, + 'paymentDetails' => $this->paymentDetails, + 'emailDetails' => $this->emailDetails, + 'recipientIdentifier' => $this->recipientIdentifier, + 'recipient' => $this->recipient, + 'lines' => $this->lines, + 'webhookUrl' => $this->webhookUrl, + 'discount' => $this->discount, + ]; + } +} diff --git a/src/Http/Data/CreateSubscriptionPayload.php b/src/Http/Data/CreateSubscriptionPayload.php new file mode 100644 index 000000000..bf28405d3 --- /dev/null +++ b/src/Http/Data/CreateSubscriptionPayload.php @@ -0,0 +1,79 @@ +amount = $amount; + $this->interval = $interval; + $this->description = $description; + $this->status = $status; + $this->times = $times; + $this->startDate = $startDate; + $this->method = $method; + $this->applicationFee = $applicationFee; + $this->metadata = $metadata; + $this->webhookUrl = $webhookUrl; + $this->mandateId = $mandateId; + $this->profileId = $profileId; + } + + public function toArray(): array + { + return [ + 'amount' => $this->amount, + 'interval' => $this->interval, + 'description' => $this->description, + 'status' => $this->status, + 'times' => $this->times, + 'startDate' => $this->startDate ? $this->startDate->format('Y-m-d') : null, + 'method' => $this->method, + 'applicationFee' => $this->applicationFee, + 'metadata' => $this->metadata, + 'webhookUrl' => $this->webhookUrl, + 'mandateId' => $this->mandateId, + 'profileId' => $this->profileId, + ]; + } +} diff --git a/src/Http/Data/DataCollection.php b/src/Http/Data/DataCollection.php new file mode 100644 index 000000000..69d0f38b5 --- /dev/null +++ b/src/Http/Data/DataCollection.php @@ -0,0 +1,57 @@ + + */ + public array $items; + + /** + * @param array $items + */ + public function __construct(array $items) + { + $this->items = $items; + } + + /** + * @param mixed $subject + */ + public static function wrap($subject): self + { + if ($subject instanceof static) { + return $subject; + } + + if ($subject instanceof Arrayable) { + return new static($subject->toArray()); + } + + return new static(Arr::wrap($subject)); + } + + public function toArray(): array + { + return $this->items; + } + + public function map(callable $callback): self + { + return new static(array_map($callback, $this->items)); + } + + public function filter(): self + { + return new static(array_filter($this->items)); + } +} diff --git a/src/Http/Data/Discount.php b/src/Http/Data/Discount.php new file mode 100644 index 000000000..6434e6a95 --- /dev/null +++ b/src/Http/Data/Discount.php @@ -0,0 +1,31 @@ +type = $type; + $this->value = $value; + } + + public function toArray(): array + { + return [ + 'type' => $this->type, + 'value' => $this->value, + ]; + } +} diff --git a/src/Http/Data/EmailDetails.php b/src/Http/Data/EmailDetails.php new file mode 100644 index 000000000..e96b5e157 --- /dev/null +++ b/src/Http/Data/EmailDetails.php @@ -0,0 +1,31 @@ +subject = $subject; + $this->body = $body; + } + + public function toArray(): array + { + return [ + 'subject' => $this->subject, + 'body' => $this->body, + ]; + } +} diff --git a/src/Http/Data/GetAllMethodsQuery.php b/src/Http/Data/GetAllMethodsQuery.php new file mode 100644 index 000000000..5c16ef2dd --- /dev/null +++ b/src/Http/Data/GetAllMethodsQuery.php @@ -0,0 +1,41 @@ +locale = $locale; + $this->includeIssuers = $includeIssuers; + $this->includePricing = $includePricing; + $this->amount = $amount; + } + + public function toArray(): array + { + return [ + 'include' => array_filter([ + $this->includeIssuers ? MethodQuery::INCLUDE_ISSUERS : null, + $this->includePricing ? MethodQuery::INCLUDE_PRICING : null, + ]), + 'locale' => $this->locale, + 'amount' => $this->amount, + ]; + } +} diff --git a/src/Http/Data/GetAllPaginatedSubscriptionsQuery.php b/src/Http/Data/GetAllPaginatedSubscriptionsQuery.php new file mode 100644 index 000000000..2efec758d --- /dev/null +++ b/src/Http/Data/GetAllPaginatedSubscriptionsQuery.php @@ -0,0 +1,25 @@ +paginatedQuery = $paginatedQuery; + $this->profileId = $profileId; + } + + public function toArray(): array + { + return array_merge($this->paginatedQuery->toArray(), [ + 'profileId' => $this->profileId, + ]); + } +} diff --git a/src/Http/Data/GetBalanceReportQuery.php b/src/Http/Data/GetBalanceReportQuery.php new file mode 100644 index 000000000..26f7bdaa7 --- /dev/null +++ b/src/Http/Data/GetBalanceReportQuery.php @@ -0,0 +1,34 @@ +from = $from; + $this->until = $until; + $this->grouping = $grouping; + } + + public function toArray(): array + { + return [ + 'from' => $this->from, + 'until' => $this->until, + 'grouping' => $this->grouping, + ]; + } +} diff --git a/src/Http/Data/GetClientQuery.php b/src/Http/Data/GetClientQuery.php new file mode 100644 index 000000000..75177bb00 --- /dev/null +++ b/src/Http/Data/GetClientQuery.php @@ -0,0 +1,32 @@ +embedOrganization = $embedOrganization; + $this->embedOnboarding = $embedOnboarding; + } + + public function toArray(): array + { + return [ + 'embed' => Arr::join([ + $this->embedOrganization ? ClientQuery::EMBED_ORGANIZATION : null, + $this->embedOnboarding ? ClientQuery::EMBED_ONBOARDING : null, + ]), + ]; + } +} diff --git a/src/Http/Data/GetEnabledPaymentMethodsQuery.php b/src/Http/Data/GetEnabledPaymentMethodsQuery.php new file mode 100644 index 000000000..a979224bd --- /dev/null +++ b/src/Http/Data/GetEnabledPaymentMethodsQuery.php @@ -0,0 +1,78 @@ +sequenceType = $sequenceType; + $this->resource = $resource; + $this->locale = $locale; + $this->amount = $amount; + $this->billingCountry = $billingCountry; + $this->includeWallets = $includeWallets; + $this->orderLineCategories = $orderLineCategories; + $this->profileId = $profileId; + $this->includeIssuers = $includeIssuers; + $this->includePricing = $includePricing; + } + + public function toArray(): array + { + return [ + 'sequenceType' => $this->sequenceType, + 'locale' => $this->locale, + 'amount' => $this->amount, + 'resource' => $this->resource, + 'billingCountry' => $this->billingCountry, + 'includeWallets' => Arr::join($this->includeWallets ?? []), + 'orderLineCategories' => Arr::join($this->orderLineCategories ?? []), + 'profileId' => $this->profileId, + 'include' => array_filter([ + $this->includeIssuers ? MethodQuery::INCLUDE_ISSUERS : null, + $this->includePricing ? MethodQuery::INCLUDE_PRICING : null, + ]), + ]; + } +} diff --git a/src/Http/Data/GetPaginatedBalanceQuery.php b/src/Http/Data/GetPaginatedBalanceQuery.php new file mode 100644 index 000000000..90de853cd --- /dev/null +++ b/src/Http/Data/GetPaginatedBalanceQuery.php @@ -0,0 +1,30 @@ +paginatedQuery = $paginatedQuery; + $this->currency = $currency; + } + + public function toArray(): array + { + return array_merge( + $this->paginatedQuery->toArray(), + [ + 'currency' => $this->currency, + ] + ); + } +} diff --git a/src/Http/Data/GetPaginatedChargebackQuery.php b/src/Http/Data/GetPaginatedChargebackQuery.php new file mode 100644 index 000000000..5e6333b2e --- /dev/null +++ b/src/Http/Data/GetPaginatedChargebackQuery.php @@ -0,0 +1,36 @@ +paginatedQuery = $paginatedQuery; + $this->includePayment = $includePayment; + $this->profileId = $profileId; + } + + public function toArray(): array + { + return array_merge( + $this->paginatedQuery->toArray(), + [ + 'include' => $this->includePayment ? PaymentIncludesQuery::PAYMENT : null, + 'profileId' => $this->profileId, + ] + ); + } +} diff --git a/src/Http/Data/GetPaginatedClientQuery.php b/src/Http/Data/GetPaginatedClientQuery.php new file mode 100644 index 000000000..e36276f4f --- /dev/null +++ b/src/Http/Data/GetPaginatedClientQuery.php @@ -0,0 +1,39 @@ +paginatedQuery = $paginatedQuery; + $this->embedOrganization = $embedOrganization; + $this->embedOnboarding = $embedOnboarding; + } + + public function toArray(): array + { + return array_merge( + $this->paginatedQuery->toArray(), + [ + 'embed' => Arr::join([ + $this->embedOrganization ? ClientQuery::EMBED_ORGANIZATION : null, + $this->embedOnboarding ? ClientQuery::EMBED_ONBOARDING : null, + ]), + ] + ); + } +} diff --git a/src/Http/Data/GetPaginatedCustomerPaymentsQuery.php b/src/Http/Data/GetPaginatedCustomerPaymentsQuery.php new file mode 100644 index 000000000..b417065d9 --- /dev/null +++ b/src/Http/Data/GetPaginatedCustomerPaymentsQuery.php @@ -0,0 +1,30 @@ +paginatedQuery = $paginatedQuery; + $this->profileId = $profileId; + } + + public function toArray(): array + { + return array_merge( + $this->paginatedQuery->toArray(), + [ + 'profileId' => $this->profileId, + ] + ); + } +} diff --git a/src/Http/Data/GetPaginatedInvoiceQuery.php b/src/Http/Data/GetPaginatedInvoiceQuery.php new file mode 100644 index 000000000..129ffa15f --- /dev/null +++ b/src/Http/Data/GetPaginatedInvoiceQuery.php @@ -0,0 +1,35 @@ +paginatedQuery = $paginatedQuery; + $this->reference = $reference; + $this->year = $year; + } + + public function toArray(): array + { + return array_merge( + $this->paginatedQuery->toArray(), + [ + 'reference' => $this->reference, + 'year' => $this->year, + ] + ); + } +} diff --git a/src/Http/Data/GetPaginatedPaymentCapturesQuery.php b/src/Http/Data/GetPaginatedPaymentCapturesQuery.php new file mode 100644 index 000000000..8f1ee2698 --- /dev/null +++ b/src/Http/Data/GetPaginatedPaymentCapturesQuery.php @@ -0,0 +1,32 @@ +paginatedQuery = $paginatedQuery; + $this->includePayment = $includePayment; + } + + public function toArray(): array + { + return array_merge( + $this->paginatedQuery->toArray(), + [ + 'include' => Arr::join($this->includePayment ? [PaymentIncludesQuery::PAYMENT] : []), + ] + ); + } +} diff --git a/src/Http/Data/GetPaginatedPaymentChargebacksQuery.php b/src/Http/Data/GetPaginatedPaymentChargebacksQuery.php new file mode 100644 index 000000000..76ada52ac --- /dev/null +++ b/src/Http/Data/GetPaginatedPaymentChargebacksQuery.php @@ -0,0 +1,31 @@ +paginatedQuery = $paginatedQuery; + $this->includePayment = $includePayment; + } + + public function toArray(): array + { + return array_merge( + $this->paginatedQuery->toArray(), + [ + 'include' => $this->includePayment ? PaymentIncludesQuery::PAYMENT : [], + ] + ); + } +} diff --git a/src/Http/Data/GetPaginatedPaymentRefundQuery.php b/src/Http/Data/GetPaginatedPaymentRefundQuery.php new file mode 100644 index 000000000..20e51da43 --- /dev/null +++ b/src/Http/Data/GetPaginatedPaymentRefundQuery.php @@ -0,0 +1,31 @@ +paginatedQuery = $paginatedQuery; + $this->includePayment = $includePayment; + } + + public function toArray(): array + { + return array_merge( + $this->paginatedQuery->toArray(), + [ + 'include' => $this->includePayment ? PaymentIncludesQuery::PAYMENT : null, + ] + ); + } +} diff --git a/src/Http/Data/GetPaginatedRefundsQuery.php b/src/Http/Data/GetPaginatedRefundsQuery.php new file mode 100644 index 000000000..c2f363dd1 --- /dev/null +++ b/src/Http/Data/GetPaginatedRefundsQuery.php @@ -0,0 +1,36 @@ +paginatedQuery = $paginatedQuery; + $this->embedPayment = $embedPayment; + $this->profileId = $profileId; + } + + public function toArray(): array + { + return array_merge( + $this->paginatedQuery->toArray(), + [ + 'embed' => $this->embedPayment ? PaymentIncludesQuery::PAYMENT : null, + 'profileId' => $this->profileId, + ] + ); + } +} diff --git a/src/Http/Data/GetPaginatedSettlementCapturesQuery.php b/src/Http/Data/GetPaginatedSettlementCapturesQuery.php new file mode 100644 index 000000000..f63ee558d --- /dev/null +++ b/src/Http/Data/GetPaginatedSettlementCapturesQuery.php @@ -0,0 +1,5 @@ +query = $query; + $this->balanceId = $balanceId; + } + + public function toArray(): array + { + return array_merge( + $this->query->toArray(), + $this->balanceId ? ['balanceId' => $this->balanceId] : [] + ); + } +} diff --git a/src/Http/Data/GetPaymentCaptureQuery.php b/src/Http/Data/GetPaymentCaptureQuery.php new file mode 100644 index 000000000..617d7c1af --- /dev/null +++ b/src/Http/Data/GetPaymentCaptureQuery.php @@ -0,0 +1,25 @@ +includePayment = $includePayment; + } + + public function toArray(): array + { + return [ + 'include' => Arr::join($this->includePayment ? [PaymentIncludesQuery::PAYMENT] : []), + ]; + } +} diff --git a/src/Http/Data/GetPaymentChargebackQuery.php b/src/Http/Data/GetPaymentChargebackQuery.php new file mode 100644 index 000000000..fad918774 --- /dev/null +++ b/src/Http/Data/GetPaymentChargebackQuery.php @@ -0,0 +1,24 @@ +includePayment = $includePayment; + } + + public function toArray(): array + { + return [ + 'include' => $this->includePayment ? PaymentIncludesQuery::PAYMENT : null, + ]; + } +} diff --git a/src/Http/Data/GetPaymentMethodQuery.php b/src/Http/Data/GetPaymentMethodQuery.php new file mode 100644 index 000000000..bd0c47310 --- /dev/null +++ b/src/Http/Data/GetPaymentMethodQuery.php @@ -0,0 +1,47 @@ +locale = $locale; + $this->currency = $currency; + $this->profileId = $profileId; + $this->includeIssuers = $includeIssuers; + $this->includePricing = $includePricing; + } + + public function toArray(): array + { + return [ + 'locale' => $this->locale, + 'currency' => $this->currency, + 'profileId' => $this->profileId, + 'include' => Arr::join([ + $this->includeIssuers ? MethodQuery::INCLUDE_ISSUERS : null, + $this->includePricing ? MethodQuery::INCLUDE_PRICING : null, + ]), + ]; + } +} diff --git a/src/Http/Data/GetPaymentQuery.php b/src/Http/Data/GetPaymentQuery.php new file mode 100644 index 000000000..35a561e60 --- /dev/null +++ b/src/Http/Data/GetPaymentQuery.php @@ -0,0 +1,49 @@ +embedCaptures = $embedCaptures; + $this->embedRefunds = $embedRefunds; + $this->embedChargebacks = $embedChargebacks; + $this->includeQrCode = $includeQrCode; + $this->includeRemainderDetails = $includeRemainderDetails; + } + + public function toArray(): array + { + return [ + 'embed' => Arr::join([ + $this->embedCaptures ? PaymentQuery::EMBED_CAPTURES : null, + $this->embedRefunds ? PaymentQuery::EMBED_REFUNDS : null, + $this->embedChargebacks ? PaymentQuery::EMBED_CHARGEBACKS : null, + ]), + 'include' => Arr::join([ + $this->includeQrCode ? PaymentQuery::INCLUDE_QR_CODE : null, + $this->includeRemainderDetails ? PaymentQuery::INCLUDE_REMAINDER_DETAILS : null, + ]), + ]; + } +} diff --git a/src/Http/Data/GetPaymentRefundQuery.php b/src/Http/Data/GetPaymentRefundQuery.php new file mode 100644 index 000000000..cf4bae72a --- /dev/null +++ b/src/Http/Data/GetPaymentRefundQuery.php @@ -0,0 +1,24 @@ +includePayment = $includePayment; + } + + public function toArray(): array + { + return [ + 'include' => $this->includePayment ? PaymentIncludesQuery::PAYMENT : null, + ]; + } +} diff --git a/src/Http/Data/InvoiceLine.php b/src/Http/Data/InvoiceLine.php new file mode 100644 index 000000000..c4febc16a --- /dev/null +++ b/src/Http/Data/InvoiceLine.php @@ -0,0 +1,43 @@ +description = $description; + $this->quantity = $quantity; + $this->vatRate = $vatRate; + $this->unitPrice = $unitPrice; + $this->discount = $discount; + } + + public function toArray(): array + { + return [ + 'description' => $this->description, + 'quantity' => $this->quantity, + 'vatRate' => $this->vatRate, + 'unitPrice' => $this->unitPrice, + 'discount' => $this->discount, + ]; + } +} diff --git a/src/Http/Data/Metadata.php b/src/Http/Data/Metadata.php new file mode 100644 index 000000000..2274e45b0 --- /dev/null +++ b/src/Http/Data/Metadata.php @@ -0,0 +1,20 @@ +data = $data; + } + + public function __toString(): string + { + return @json_encode($this->data); + } +} diff --git a/src/Http/Data/Money.php b/src/Http/Data/Money.php new file mode 100644 index 000000000..45374dc23 --- /dev/null +++ b/src/Http/Data/Money.php @@ -0,0 +1,28 @@ +currency = $currency; + $this->value = $value; + } + + public function toArray(): array + { + return [ + 'currency' => $this->currency, + 'value' => $this->value, + ]; + } +} diff --git a/src/Http/Data/OrderLine.php b/src/Http/Data/OrderLine.php new file mode 100644 index 000000000..0b03897b3 --- /dev/null +++ b/src/Http/Data/OrderLine.php @@ -0,0 +1,83 @@ +description = $description; + $this->quantity = $quantity; + $this->unitPrice = $unitPrice; + $this->totalAmount = $totalAmount; + $this->type = $type; + $this->quantityUnit = $quantityUnit; + $this->discountAmount = $discountAmount; + $this->recurring = $recurring; + $this->vatRate = $vatRate; + $this->vatAmount = $vatAmount; + $this->sku = $sku; + $this->imageUrl = $imageUrl; + $this->productUrl = $productUrl; + } + + public function toArray(): array + { + return [ + 'description' => $this->description, + 'quantity' => $this->quantity, + 'unitPrice' => $this->unitPrice, + 'totalAmount' => $this->totalAmount, + 'type' => $this->type, + 'quantityUnit' => $this->quantityUnit, + 'discountAmount' => $this->discountAmount, + 'recurring' => $this->recurring, + 'vatRate' => $this->vatRate, + 'vatAmount' => $this->vatAmount, + 'sku' => $this->sku, + 'imageUrl' => $this->imageUrl, + 'productUrl' => $this->productUrl, + ]; + } +} diff --git a/src/Http/Data/Owner.php b/src/Http/Data/Owner.php new file mode 100644 index 000000000..edc493f89 --- /dev/null +++ b/src/Http/Data/Owner.php @@ -0,0 +1,41 @@ +email = $email; + $this->givenName = $givenName; + $this->familyName = $familyName; + $this->locale = $locale; + } + + public function toArray(): array + { + return [ + 'email' => $this->email, + 'givenName' => $this->givenName, + 'familyName' => $this->familyName, + 'locale' => $this->locale, + ]; + } +} diff --git a/src/Http/Data/OwnerAddress.php b/src/Http/Data/OwnerAddress.php new file mode 100644 index 000000000..d3c547c7c --- /dev/null +++ b/src/Http/Data/OwnerAddress.php @@ -0,0 +1,46 @@ +country = $country; + $this->streetAndNumber = $streetAndNumber; + $this->postalCode = $postalCode; + $this->city = $city; + $this->region = $region; + } + + public function toArray(): array + { + return [ + 'streetAndNumber' => $this->streetAndNumber, + 'postalCode' => $this->postalCode, + 'city' => $this->city, + 'region' => $this->region, + 'country' => $this->country, + ]; + } +} diff --git a/src/Http/Data/PaginatedQuery.php b/src/Http/Data/PaginatedQuery.php new file mode 100644 index 000000000..98efcf343 --- /dev/null +++ b/src/Http/Data/PaginatedQuery.php @@ -0,0 +1,28 @@ +from = $from; + $this->limit = $limit; + } + + public function toArray(): array + { + return [ + 'from' => $this->from, + 'limit' => $this->limit, + ]; + } +} diff --git a/src/Http/Data/PaymentDetails.php b/src/Http/Data/PaymentDetails.php new file mode 100644 index 000000000..38d3baa00 --- /dev/null +++ b/src/Http/Data/PaymentDetails.php @@ -0,0 +1,31 @@ +source = $source; + $this->sourceDescription = $sourceDescription; + } + + public function toArray(): array + { + return [ + 'source' => $this->source, + 'sourceDescription' => $this->sourceDescription, + ]; + } +} diff --git a/src/Http/Data/PaymentRoute.php b/src/Http/Data/PaymentRoute.php new file mode 100644 index 000000000..cae663f9e --- /dev/null +++ b/src/Http/Data/PaymentRoute.php @@ -0,0 +1,37 @@ +amount = $amount; + $this->organizationId = $organizationId; + $this->delayUntil = $delayUntil; + } + + public function toArray(): array + { + return [ + 'amount' => $this->amount, + 'destination' => [ + 'type' => 'organization', + 'organizationId' => $this->organizationId, + ], + 'delayUntil' => $this->delayUntil, + ]; + } +} diff --git a/src/Http/Data/Recipient.php b/src/Http/Data/Recipient.php new file mode 100644 index 000000000..394f7c648 --- /dev/null +++ b/src/Http/Data/Recipient.php @@ -0,0 +1,98 @@ +type = $type; + $this->title = $title; + $this->givenName = $givenName; + $this->familyName = $familyName; + $this->organizationName = $organizationName; + $this->organizationNumber = $organizationNumber; + $this->vatNumber = $vatNumber; + $this->email = $email; + $this->phone = $phone; + $this->streetAndNumber = $streetAndNumber; + $this->streetAdditional = $streetAdditional; + $this->postalCode = $postalCode; + $this->city = $city; + $this->region = $region; + $this->country = $country; + $this->locale = $locale; + } + + public function toArray(): array + { + return [ + 'type' => $this->type, + 'title' => $this->title, + 'givenName' => $this->givenName, + 'familyName' => $this->familyName, + 'organizationName' => $this->organizationName, + 'organizationNumber' => $this->organizationNumber, + 'vatNumber' => $this->vatNumber, + 'email' => $this->email, + 'phone' => $this->phone, + 'streetAndNumber' => $this->streetAndNumber, + 'streetAdditional' => $this->streetAdditional, + 'postalCode' => $this->postalCode, + 'city' => $this->city, + 'region' => $this->region, + 'country' => $this->country, + 'locale' => $this->locale, + ]; + } +} diff --git a/src/Http/Data/RecurringBillingCycle.php b/src/Http/Data/RecurringBillingCycle.php new file mode 100644 index 000000000..b3f576521 --- /dev/null +++ b/src/Http/Data/RecurringBillingCycle.php @@ -0,0 +1,49 @@ +interval = $interval; + $this->description = $description; + $this->amount = $amount; + $this->times = $times; + $this->startDate = $startDate; + } + + public function toArray(): array + { + return [ + 'interval' => $this->interval, + 'description' => $this->description, + 'amount' => $this->amount, + 'times' => $this->times, + 'startDate' => $this->startDate, + ]; + } +} diff --git a/src/Http/Data/RefundRoute.php b/src/Http/Data/RefundRoute.php new file mode 100644 index 000000000..726423992 --- /dev/null +++ b/src/Http/Data/RefundRoute.php @@ -0,0 +1,31 @@ +amount = $amount; + $this->organizationId = $organizationId; + } + + public function toArray(): array + { + return [ + 'amount' => $this->amount, + 'source' => [ + 'type' => 'organization', + 'organizationId' => $this->organizationId, + ], + ]; + } +} diff --git a/src/Http/Data/RequestApplePayPaymentSessionPayload.php b/src/Http/Data/RequestApplePayPaymentSessionPayload.php new file mode 100644 index 000000000..f3ed782d2 --- /dev/null +++ b/src/Http/Data/RequestApplePayPaymentSessionPayload.php @@ -0,0 +1,33 @@ +domain = $domain; + $this->validationUrl = $validationUrl; + $this->profileId = $profileId; + } + + public function toArray(): array + { + return [ + 'domain' => $this->domain, + 'validationUrl' => $this->validationUrl, + 'profileId' => $this->profileId, + ]; + } +} diff --git a/src/Http/Data/SortablePaginatedQuery.php b/src/Http/Data/SortablePaginatedQuery.php new file mode 100644 index 000000000..874f489f9 --- /dev/null +++ b/src/Http/Data/SortablePaginatedQuery.php @@ -0,0 +1,28 @@ +sort = $sort; + } + + public function toArray(): array + { + return array_merge( + parent::toArray(), + [ + 'sort' => $this->sort, + ] + ); + } +} diff --git a/src/Http/Data/UpdateCustomerPayload.php b/src/Http/Data/UpdateCustomerPayload.php new file mode 100644 index 000000000..ef64bb7b7 --- /dev/null +++ b/src/Http/Data/UpdateCustomerPayload.php @@ -0,0 +1,8 @@ +description = $description; + $this->archived = $archived; + } + + public function toArray(): array + { + return [ + 'description' => $this->description, + 'archived' => $this->archived, + ]; + } +} diff --git a/src/Http/Data/UpdatePaymentPayload.php b/src/Http/Data/UpdatePaymentPayload.php new file mode 100644 index 000000000..e5dc0f072 --- /dev/null +++ b/src/Http/Data/UpdatePaymentPayload.php @@ -0,0 +1,67 @@ +description = $description; + $this->redirectUrl = $redirectUrl; + $this->cancelUrl = $cancelUrl; + $this->webhookUrl = $webhookUrl; + $this->metadata = $metadata; + $this->method = $method; + $this->locale = $locale; + $this->restrictPaymentMethodsToCountry = $restrictPaymentMethodsToCountry; + $this->additional = $additional; + } + + public function toArray(): array + { + return array_merge([ + 'description' => $this->description, + 'redirectUrl' => $this->redirectUrl, + 'cancelUrl' => $this->cancelUrl, + 'webhookUrl' => $this->webhookUrl, + 'metadata' => $this->metadata, + 'method' => $this->method, + 'locale' => $this->locale, + 'restrictPaymentMethodsToCountry' => $this->restrictPaymentMethodsToCountry, + ], $this->additional); + } +} diff --git a/src/Http/Data/UpdatePaymentRoutePayload.php b/src/Http/Data/UpdatePaymentRoutePayload.php new file mode 100644 index 000000000..443d8de43 --- /dev/null +++ b/src/Http/Data/UpdatePaymentRoutePayload.php @@ -0,0 +1,24 @@ +releaseDate = $releaseDate; + } + + public function toArray(): array + { + return [ + 'releaseDate' => $this->releaseDate, + ]; + } +} diff --git a/src/Http/Data/UpdateProfilePayload.php b/src/Http/Data/UpdateProfilePayload.php new file mode 100644 index 000000000..3b3e140e5 --- /dev/null +++ b/src/Http/Data/UpdateProfilePayload.php @@ -0,0 +1,58 @@ +name = $name; + $this->website = $website; + $this->email = $email; + $this->phone = $phone; + $this->description = $description; + $this->countriesOfActivity = $countriesOfActivity; + $this->businessCategory = $businessCategory; + $this->mode = $mode; + } + + public function toArray(): array + { + return [ + 'name' => $this->name, + 'website' => $this->website, + 'email' => $this->email, + 'phone' => $this->phone, + 'description' => $this->description, + 'countriesOfActivity' => $this->countriesOfActivity, + 'businessCategory' => $this->businessCategory, + 'mode' => $this->mode, + ]; + } +} diff --git a/src/Http/Data/UpdateSalesInvoicePayload.php b/src/Http/Data/UpdateSalesInvoicePayload.php new file mode 100644 index 000000000..215e21427 --- /dev/null +++ b/src/Http/Data/UpdateSalesInvoicePayload.php @@ -0,0 +1,71 @@ + + */ + public ?DataCollection $lines; + + public ?string $webhookUrl; + + public ?Discount $discount; + + public function __construct( + string $status, + string $recipientIdentifier, + ?string $paymentTerm = null, + ?string $memo = null, + ?PaymentDetails $paymentDetails = null, + ?EmailDetails $emailDetails = null, + ?Recipient $recipient = null, + ?DataCollection $lines = null, + ?string $webhookUrl = null, + ?Discount $discount = null + ) { + $this->status = $status; + $this->paymentTerm = $paymentTerm; + $this->recipientIdentifier = $recipientIdentifier; + $this->memo = $memo; + $this->paymentDetails = $paymentDetails; + $this->emailDetails = $emailDetails; + $this->recipient = $recipient; + $this->lines = $lines; + $this->webhookUrl = $webhookUrl; + $this->discount = $discount; + } + + public function toArray(): array + { + return [ + 'status' => $this->status, + 'memo' => $this->memo, + 'paymentTerm' => $this->paymentTerm, + 'paymentDetails' => $this->paymentDetails, + 'emailDetails' => $this->emailDetails, + 'recipientIdentifier' => $this->recipientIdentifier, + 'recipient' => $this->recipient, + 'lines' => $this->lines, + 'webhookUrl' => $this->webhookUrl, + 'discount' => $this->discount, + ]; + } +} diff --git a/src/Http/Data/UpdateSubscriptionPayload.php b/src/Http/Data/UpdateSubscriptionPayload.php new file mode 100644 index 000000000..599d75292 --- /dev/null +++ b/src/Http/Data/UpdateSubscriptionPayload.php @@ -0,0 +1,59 @@ +amount = $amount; + $this->description = $description; + $this->interval = $interval; + $this->startDate = $startDate; + $this->times = $times; + $this->metadata = $metadata; + $this->webhookUrl = $webhookUrl; + $this->mandateId = $mandateId; + } + + public function toArray(): array + { + return [ + 'amount' => $this->amount, + 'description' => $this->description, + 'interval' => $this->interval, + 'startDate' => $this->startDate, + 'times' => $this->times, + 'metadata' => $this->metadata, + 'webhookUrl' => $this->webhookUrl, + 'mandateId' => $this->mandateId, + ]; + } +} diff --git a/src/Http/Middleware.php b/src/Http/Middleware.php new file mode 100644 index 000000000..7f48a541b --- /dev/null +++ b/src/Http/Middleware.php @@ -0,0 +1,89 @@ +onRequest = new Handlers; + $this->onResponse = new Handlers; + } + + public function onRequest(callable $callback, ?string $name = null, string $priority = MiddlewarePriority::MEDIUM): self + { + $this->onRequest->add(static function (PendingRequest $pendingRequest) use ($callback): PendingRequest { + $result = $callback($pendingRequest); + + if ($result instanceof PendingRequest) { + return $result; + } + + return $pendingRequest; + }, $name, $priority); + + return $this; + } + + public function onResponse(callable $callback, ?string $name = null, string $priority = MiddlewarePriority::MEDIUM): self + { + /** @param Response|IsResponseAware $response */ + $this->onResponse->add(static function ($response) use ($callback) { + $result = $callback($response); + + return $result instanceof Response + || $result instanceof ViableResponse + ? $result + : $response; + }, $name, $priority); + + return $this; + } + + public function executeOnRequest(PendingRequest $pendingRequest): PendingRequest + { + return $this->onRequest->execute($pendingRequest); + } + + /** + * @return Response|ViableResponse + */ + public function executeOnResponse(Response $response) + { + return $this->onResponse->execute($response); + } + + /** + * @param array ...$handlersCollection + */ + public function merge(...$handlersCollection): self + { + /** @var Middleware $handlers */ + foreach ($handlersCollection as $handlers) { + $onRequestHandlers = array_merge( + $this->onRequest->getHandlers(), + $handlers->onRequest->getHandlers() + ); + + $this->onRequest->setHandlers($onRequestHandlers); + + $onResponseHandlers = array_merge( + $this->onResponse->getHandlers(), + $handlers->onResponse->getHandlers() + ); + + $this->onResponse->setHandlers($onResponseHandlers); + } + + return $this; + } +} diff --git a/src/Http/Middleware/ApplyIdempotencyKey.php b/src/Http/Middleware/ApplyIdempotencyKey.php new file mode 100644 index 000000000..9f7e67d96 --- /dev/null +++ b/src/Http/Middleware/ApplyIdempotencyKey.php @@ -0,0 +1,40 @@ +isMutatingRequest($pendingRequest)) { + $pendingRequest->headers()->remove(self::IDEMPOTENCY_KEY_HEADER); + + return $pendingRequest; + } + + $idempotencyKey = $pendingRequest->getConnector()->getIdempotencyKey(); + $idempotencyKeyGenerator = $pendingRequest->getConnector()->getIdempotencyKeyGenerator(); + + if ($idempotencyKey === null && $idempotencyKeyGenerator === null) { + return $pendingRequest; + } + + $pendingRequest->headers()->add( + self::IDEMPOTENCY_KEY_HEADER, + $idempotencyKey ?? $idempotencyKeyGenerator->generate() + ); + + return $pendingRequest; + } + + private function isMutatingRequest(PendingRequest $pendingRequest): bool + { + return in_array($pendingRequest->method(), [Method::POST, Method::PATCH, Method::DELETE]); + } +} diff --git a/src/Http/Middleware/GuardResponse.php b/src/Http/Middleware/GuardResponse.php new file mode 100644 index 000000000..45d48bd93 --- /dev/null +++ b/src/Http/Middleware/GuardResponse.php @@ -0,0 +1,35 @@ +getResponse() : $response; + + if (($isEmpty = $response->isEmpty()) && $response->status() !== ResponseStatusCode::HTTP_NO_CONTENT) { + throw new ApiException('No response body found.'); + } + + if ($isEmpty) { + return; + } + + $data = $response->json(); + + // @todo check if this is still necessary as it seems to be from api v1 + if (isset($data->error)) { + throw new ApiException($data->error->message); + } + } +} diff --git a/src/Http/Middleware/Handler.php b/src/Http/Middleware/Handler.php new file mode 100644 index 000000000..b3cc7eefd --- /dev/null +++ b/src/Http/Middleware/Handler.php @@ -0,0 +1,36 @@ +callback = $callback; + $this->name = $name; + $this->priority = $priority; + } + + public function callback(): callable + { + return $this->callback; + } + + public function name(): ?string + { + return $this->name; + } + + public function priority(): string + { + return $this->priority; + } +} diff --git a/src/Http/Middleware/Handlers.php b/src/Http/Middleware/Handlers.php new file mode 100644 index 000000000..4427ba432 --- /dev/null +++ b/src/Http/Middleware/Handlers.php @@ -0,0 +1,94 @@ + + */ + protected array $handlers = []; + + public function add(callable $handler, ?string $name = null, string $priority = MiddlewarePriority::MEDIUM): void + { + if (in_array($name, [MiddlewarePriority::HIGH, MiddlewarePriority::MEDIUM, MiddlewarePriority::LOW])) { + $priority = $name; + $name = null; + } + + if (is_string($name) && $this->handlerExists($name)) { + throw new \InvalidArgumentException("Handler with name '{$name}' already exists."); + } + + $this->handlers[] = new Handler($handler, $name, $priority); + } + + public function setHandlers(array $handlers): void + { + $this->handlers = $handlers; + } + + public function getHandlers(): array + { + return $this->handlers; + } + + /** + * Execute the handlers + * + * @param PendingRequest|Response|mixed $payload + * @return PendingRequest|Response|IsResponseAware|ViableResponse + */ + public function execute($payload) + { + /** @var Handler $handler */ + foreach ($this->sortHandlers() as $handler) { + $payload = call_user_func($handler->callback(), $payload); + + /** + * If the handler returns a value that is not an instance of PendingRequest or Response, + * we assume that the handler has transformed the payload in some way and we return the transformed value. + */ + if ($payload instanceof ViableResponse) { + return $payload; + } + } + + return $payload; + } + + protected function sortHandlers(): array + { + $highPriority = []; + $mediumPriority = []; + $lowPriority = []; + + $priorityMap = [ + MiddlewarePriority::HIGH => &$highPriority, + MiddlewarePriority::MEDIUM => &$mediumPriority, + MiddlewarePriority::LOW => &$lowPriority, + ]; + + foreach ($this->handlers as $handler) { + $priorityMap[$handler->priority()][] = $handler; + } + + return array_merge($highPriority, $mediumPriority, $lowPriority); + } + + private function handlerExists(string $name): bool + { + foreach ($this->handlers as $handler) { + if ($handler->name() === $name) { + return true; + } + } + + return false; + } +} diff --git a/src/Http/Middleware/Hydrate.php b/src/Http/Middleware/Hydrate.php new file mode 100644 index 000000000..749a1c2a5 --- /dev/null +++ b/src/Http/Middleware/Hydrate.php @@ -0,0 +1,22 @@ +getRequest(); + + if ($request instanceof ResourceHydratableRequest && $request->isHydratable()) { + return (new ResourceHydrator)->hydrate($request, $response); + } + + return $response; + } +} diff --git a/src/Http/Middleware/MiddlewarePriority.php b/src/Http/Middleware/MiddlewarePriority.php new file mode 100644 index 000000000..1531067b3 --- /dev/null +++ b/src/Http/Middleware/MiddlewarePriority.php @@ -0,0 +1,12 @@ +getConnector()->resetIdempotencyKey(); + } +} diff --git a/src/Http/Middleware/ThrowExceptionIfRequestFailed.php b/src/Http/Middleware/ThrowExceptionIfRequestFailed.php new file mode 100644 index 000000000..b4e60ac3a --- /dev/null +++ b/src/Http/Middleware/ThrowExceptionIfRequestFailed.php @@ -0,0 +1,49 @@ +successful()) { + return; + } + + $body = $response->json(); + + $message = "Error executing API call ({$body->status}: {$body->title}): {$body->detail}"; + + $field = null; + + if (! empty($body->field)) { + $field = $body->field; + } + + if (isset($body->_links, $body->_links->documentation)) { + $message .= ". Documentation: {$body->_links->documentation->href}"; + } + + if ($response->getPendingRequest()->payload()) { + $streamFactory = $response + ->getPendingRequest() + ->getFactoryCollection() + ->streamFactory; + + $message .= ". Request body: {$response->getPendingRequest()->payload()->toStream($streamFactory)->getContents()}"; + } + + throw new ApiException( + $message, + $response->status(), + $field, + $response->getPsrRequest(), + $response->getPsrResponse(), + $response->getSenderException() + ); + } +} diff --git a/src/Http/PendingRequest.php b/src/Http/PendingRequest.php new file mode 100644 index 000000000..b2e3e088e --- /dev/null +++ b/src/Http/PendingRequest.php @@ -0,0 +1,152 @@ +factoryCollection = $connector->getHttpClient()->factories(); + + $this->connector = $connector; + $this->request = $request; + + $this->method = $request->getMethod(); + $this->url = Url::join($connector->resolveBaseUrl(), $request->resolveResourcePath()); + + $this->middleware()->merge($request->middleware(), $connector->middleware()); + + $this + ->tap(new MergeRequestProperties) + ->tap(new SetBody) + ->tap(new SetUserAgent) + ->tap(new AddTestmodeIfEnabled) + ->tap(new AuthenticateRequest) + ->tap(new RemoveTestmodeFromApiAuthenticatedRequests); + + $this + ->middleware() + + /** On request */ + ->onRequest(new ApplyIdempotencyKey, 'idempotency') + + /** On response */ + ->onResponse(new ResetIdempotencyKey, 'idempotency') + ->onResponse(new Hydrate, 'hydrate', MiddlewarePriority::LOW) + ->onResponse(new GuardResponse, MiddlewarePriority::HIGH) + ->onResponse(new ThrowExceptionIfRequestFailed, MiddlewarePriority::HIGH); + } + + public function setTestmode(bool $testmode): self + { + if ($this->request instanceof SupportsTestmodeInQuery) { + $this->query()->add('testmode', $testmode); + } elseif ($this->request instanceof SupportsTestmodeInPayload) { + $this->payload()->add('testmode', $testmode); + } + + return $this; + } + + public function getTestmode(): bool + { + if (! $this->request instanceof SupportsTestmodeInQuery && ! $this->request instanceof SupportsTestmodeInPayload) { + return false; + } + + return $this->request instanceof SupportsTestmodeInQuery + ? $this->query()->get('testmode', false) + : $this->payload()->get('testmode', false); + } + + public function setPayload(PayloadRepository $bodyRepository): self + { + $this->payload = $bodyRepository; + + return $this; + } + + public function payload(): ?PayloadRepository + { + return $this->payload; + } + + public function url(): string + { + return $this->url; + } + + public function method(): string + { + return $this->method; + } + + public function getConnector(): Connector + { + return $this->connector; + } + + public function getRequest(): Request + { + return $this->request; + } + + public function executeRequestHandlers(): self + { + return $this->middleware()->executeOnRequest($this); + } + + /** + * @return Response|IsResponseAware + */ + public function executeResponseHandlers(Response $response) + { + return $this->middleware()->executeOnResponse($response); + } + + protected function tap(callable $callable): self + { + $callable($this); + + return $this; + } +} diff --git a/src/Http/PendingRequest/AddTestmodeIfEnabled.php b/src/Http/PendingRequest/AddTestmodeIfEnabled.php new file mode 100644 index 000000000..f19760fc6 --- /dev/null +++ b/src/Http/PendingRequest/AddTestmodeIfEnabled.php @@ -0,0 +1,19 @@ +getConnector(); + + if ($connector->getTestmode() || $pendingRequest->getRequest()->getTestmode()) { + $pendingRequest->setTestmode(true); + } + + return $pendingRequest; + } +} diff --git a/src/Http/PendingRequest/AuthenticateRequest.php b/src/Http/PendingRequest/AuthenticateRequest.php new file mode 100644 index 000000000..bc2be737f --- /dev/null +++ b/src/Http/PendingRequest/AuthenticateRequest.php @@ -0,0 +1,22 @@ +getConnector()->getAuthenticator(); + + if (! $authenticator) { + throw new ApiException('You have not set an API key or OAuth access token. Please use setApiKey() to set the API key.'); + } + + $authenticator->authenticate($pendingRequest); + + return $pendingRequest; + } +} diff --git a/src/Http/PendingRequest/MergeRequestProperties.php b/src/Http/PendingRequest/MergeRequestProperties.php new file mode 100644 index 000000000..81c681ecc --- /dev/null +++ b/src/Http/PendingRequest/MergeRequestProperties.php @@ -0,0 +1,26 @@ +getConnector(); + $request = $pendingRequest->getRequest(); + + $pendingRequest->headers()->merge( + $client->headers()->all(), + $request->headers()->all() + ); + + $pendingRequest->query()->merge( + $client->query()->all(), + $request->query()->all() + ); + + return $pendingRequest; + } +} diff --git a/src/Http/PendingRequest/RemoveTestmodeFromApiAuthenticatedRequests.php b/src/Http/PendingRequest/RemoveTestmodeFromApiAuthenticatedRequests.php new file mode 100644 index 000000000..726e33f18 --- /dev/null +++ b/src/Http/PendingRequest/RemoveTestmodeFromApiAuthenticatedRequests.php @@ -0,0 +1,33 @@ +getConnector()->getAuthenticator(); + + if ($authenticator instanceof ApiKeyAuthenticator) { + $this->removeTestmode($pendingRequest); + } + + return $pendingRequest; + } + + private function removeTestmode(PendingRequest $pendingRequest): void + { + if ($pendingRequest->getRequest() instanceof SupportsTestmodeInQuery) { + $pendingRequest->query()->remove('testmode'); + } + + if ($pendingRequest->getRequest() instanceof SupportsTestmodeInPayload) { + $pendingRequest->payload()->remove('testmode'); + } + } +} diff --git a/src/Http/PendingRequest/SetBody.php b/src/Http/PendingRequest/SetBody.php new file mode 100644 index 000000000..3c71bc7b8 --- /dev/null +++ b/src/Http/PendingRequest/SetBody.php @@ -0,0 +1,28 @@ +getRequest(); + + if (! $request instanceof HasPayload) { + return $pendingRequest; + } + + $body = $request->payload(); + + $pendingRequest->setPayload($body); + + if (! $pendingRequest->headers()->get('Content-Type')) { + $pendingRequest->headers()->add('Content-Type', 'application/json'); + } + + return $pendingRequest; + } +} diff --git a/src/Http/PendingRequest/SetUserAgent.php b/src/Http/PendingRequest/SetUserAgent.php new file mode 100644 index 000000000..55e34187e --- /dev/null +++ b/src/Http/PendingRequest/SetUserAgent.php @@ -0,0 +1,25 @@ +getConnector()->getVersionStrings(), ' '); + + $authenticator = $pendingRequest->getConnector()->getAuthenticator(); + + if ($authenticator instanceof AccessTokenAuthenticator) { + $userAgent .= ' Auth/Token'; + } + + $pendingRequest->headers()->add('User-Agent', $userAgent); + + return $pendingRequest; + } +} diff --git a/src/Http/Request.php b/src/Http/Request.php new file mode 100644 index 000000000..9ba7e92fa --- /dev/null +++ b/src/Http/Request.php @@ -0,0 +1,37 @@ +payload = $payload; + } + + public function resolveResourcePath(): string + { + return 'wallets/applepay/sessions'; + } + + public function defaultPayload(): array + { + return $this->payload->toArray(); + } +} diff --git a/src/Http/Requests/CancelPaymentRefundRequest.php b/src/Http/Requests/CancelPaymentRefundRequest.php new file mode 100644 index 000000000..ec0873476 --- /dev/null +++ b/src/Http/Requests/CancelPaymentRefundRequest.php @@ -0,0 +1,27 @@ +paymentId = $paymentId; + $this->id = $id; + } + + public function resolveResourcePath(): string + { + return "payments/{$this->paymentId}/refunds/{$this->id}"; + } +} diff --git a/src/Http/Requests/CancelPaymentRequest.php b/src/Http/Requests/CancelPaymentRequest.php new file mode 100644 index 000000000..df2e8ea9b --- /dev/null +++ b/src/Http/Requests/CancelPaymentRequest.php @@ -0,0 +1,26 @@ +id = $id; + } + + public function resolveResourcePath(): string + { + return "payments/{$this->id}"; + } +} diff --git a/src/Http/Requests/CancelSessionRequest.php b/src/Http/Requests/CancelSessionRequest.php new file mode 100644 index 000000000..1618d0978 --- /dev/null +++ b/src/Http/Requests/CancelSessionRequest.php @@ -0,0 +1,25 @@ +sessionId = $sessionId; + } + + public function resolveResourcePath(): string + { + return "sessions/{$this->sessionId}"; + } +} diff --git a/src/Http/Requests/CancelSubscriptionRequest.php b/src/Http/Requests/CancelSubscriptionRequest.php new file mode 100644 index 000000000..e2c59a05b --- /dev/null +++ b/src/Http/Requests/CancelSubscriptionRequest.php @@ -0,0 +1,38 @@ +customerId = $customerId; + $this->subscriptionId = $subscriptionId; + } + + /** + * The resource path. + */ + public function resolveResourcePath(): string + { + return "customers/{$this->customerId}/subscriptions/{$this->subscriptionId}"; + } +} diff --git a/src/Http/Requests/CreateClientLinkRequest.php b/src/Http/Requests/CreateClientLinkRequest.php new file mode 100644 index 000000000..70c77be03 --- /dev/null +++ b/src/Http/Requests/CreateClientLinkRequest.php @@ -0,0 +1,41 @@ +payload = $payload; + } + + protected function defaultPayload(): array + { + return $this->payload->toArray(); + } + + public function resolveResourcePath(): string + { + return 'client-links'; + } +} diff --git a/src/Http/Requests/CreateCustomerPaymentRequest.php b/src/Http/Requests/CreateCustomerPaymentRequest.php new file mode 100644 index 000000000..146353ceb --- /dev/null +++ b/src/Http/Requests/CreateCustomerPaymentRequest.php @@ -0,0 +1,28 @@ +customerId = $customerId; + } + + public function resolveResourcePath(): string + { + return "customers/{$this->customerId}/payments"; + } +} diff --git a/src/Http/Requests/CreateCustomerRequest.php b/src/Http/Requests/CreateCustomerRequest.php new file mode 100644 index 000000000..8ad7cbc41 --- /dev/null +++ b/src/Http/Requests/CreateCustomerRequest.php @@ -0,0 +1,36 @@ +payload = $payload; + } + + protected function defaultPayload(): array + { + return $this->payload->toArray(); + } + + public function resolveResourcePath(): string + { + return 'customers'; + } +} diff --git a/src/Http/Requests/CreateMandateRequest.php b/src/Http/Requests/CreateMandateRequest.php new file mode 100644 index 000000000..6167de575 --- /dev/null +++ b/src/Http/Requests/CreateMandateRequest.php @@ -0,0 +1,45 @@ +customerId = $customerId; + $this->payload = $payload; + } + + protected function defaultPayload(): array + { + return $this->payload->toArray(); + } + + public function resolveResourcePath(): string + { + return "customers/{$this->customerId}/mandates"; + } +} diff --git a/src/Http/Requests/CreatePaymentCaptureRequest.php b/src/Http/Requests/CreatePaymentCaptureRequest.php new file mode 100644 index 000000000..383899594 --- /dev/null +++ b/src/Http/Requests/CreatePaymentCaptureRequest.php @@ -0,0 +1,45 @@ +paymentId = $paymentId; + $this->payload = $payload; + } + + protected function defaultPayload(): array + { + return $this->payload->toArray(); + } + + public function resolveResourcePath(): string + { + return "payments/{$this->paymentId}/captures"; + } +} diff --git a/src/Http/Requests/CreatePaymentLinkRequest.php b/src/Http/Requests/CreatePaymentLinkRequest.php new file mode 100644 index 000000000..cea9aa42f --- /dev/null +++ b/src/Http/Requests/CreatePaymentLinkRequest.php @@ -0,0 +1,44 @@ +payload = $payload; + } + + protected function defaultPayload(): array + { + return $this->payload->toArray(); + } + + /** + * The resource path. + */ + public function resolveResourcePath(): string + { + return 'payment-links'; + } +} diff --git a/src/Http/Requests/CreatePaymentRefundRequest.php b/src/Http/Requests/CreatePaymentRefundRequest.php new file mode 100644 index 000000000..eca3d8a39 --- /dev/null +++ b/src/Http/Requests/CreatePaymentRefundRequest.php @@ -0,0 +1,47 @@ +paymentId = $identifier; + $this->payload = $payload; + } + + protected function defaultPayload(): array + { + return $this->payload->toArray(); + } + + public function resolveResourcePath(): string + { + return "payments/{$this->paymentId}/refunds"; + } +} diff --git a/src/Http/Requests/CreatePaymentRequest.php b/src/Http/Requests/CreatePaymentRequest.php new file mode 100644 index 000000000..186fd774a --- /dev/null +++ b/src/Http/Requests/CreatePaymentRequest.php @@ -0,0 +1,54 @@ +payload = $payload; + $this->query = $query; + } + + protected function defaultPayload(): array + { + return $this->payload->toArray(); + } + + protected function defaultQuery(): array + { + return $this->query ? $this->query->toArray() : []; + } + + /** + * The resource path. + */ + public function resolveResourcePath(): string + { + return 'payments'; + } +} diff --git a/src/Http/Requests/CreateProfileRequest.php b/src/Http/Requests/CreateProfileRequest.php new file mode 100644 index 000000000..2984c25c9 --- /dev/null +++ b/src/Http/Requests/CreateProfileRequest.php @@ -0,0 +1,44 @@ +payload = $payload; + } + + protected function defaultPayload(): array + { + return $this->payload->toArray(); + } + + /** + * The resource path. + */ + public function resolveResourcePath(): string + { + return 'profiles'; + } +} diff --git a/src/Http/Requests/CreateSalesInvoiceRequest.php b/src/Http/Requests/CreateSalesInvoiceRequest.php new file mode 100644 index 000000000..31f696064 --- /dev/null +++ b/src/Http/Requests/CreateSalesInvoiceRequest.php @@ -0,0 +1,35 @@ +payload = $payload; + } + + public function resolveResourcePath(): string + { + return 'sales-invoices'; + } + + public function defaultPayload(): array + { + return $this->payload->toArray(); + } +} diff --git a/src/Http/Requests/CreateSessionRequest.php b/src/Http/Requests/CreateSessionRequest.php new file mode 100644 index 000000000..94be5ebba --- /dev/null +++ b/src/Http/Requests/CreateSessionRequest.php @@ -0,0 +1,43 @@ +payload = $payload; + $this->query = $query; + } + + protected function defaultPayload(): array + { + return $this->payload->toArray(); + } + + protected function defaultQuery(): array + { + return $this->query->toArray(); + } + + public function resolveResourcePath(): string + { + return 'sessions'; + } +} diff --git a/src/Http/Requests/CreateSubscriptionRequest.php b/src/Http/Requests/CreateSubscriptionRequest.php new file mode 100644 index 000000000..9030a9a9e --- /dev/null +++ b/src/Http/Requests/CreateSubscriptionRequest.php @@ -0,0 +1,48 @@ +customerId = $customerId; + $this->payload = $payload; + } + + protected function defaultPayload(): array + { + return $this->payload->toArray(); + } + + /** + * The resource path. + */ + public function resolveResourcePath(): string + { + return "customers/{$this->customerId}/subscriptions"; + } +} diff --git a/src/Http/Requests/DeleteCustomerRequest.php b/src/Http/Requests/DeleteCustomerRequest.php new file mode 100644 index 000000000..6eb2c009a --- /dev/null +++ b/src/Http/Requests/DeleteCustomerRequest.php @@ -0,0 +1,24 @@ +id = $id; + } + + public function resolveResourcePath(): string + { + return "customers/{$this->id}"; + } +} diff --git a/src/Http/Requests/DeletePaymentLinkRequest.php b/src/Http/Requests/DeletePaymentLinkRequest.php new file mode 100644 index 000000000..7fb89041e --- /dev/null +++ b/src/Http/Requests/DeletePaymentLinkRequest.php @@ -0,0 +1,24 @@ +id = $id; + } + + public function resolveResourcePath(): string + { + return "payment-links/{$this->id}"; + } +} diff --git a/src/Http/Requests/DeleteProfileRequest.php b/src/Http/Requests/DeleteProfileRequest.php new file mode 100644 index 000000000..9156442cb --- /dev/null +++ b/src/Http/Requests/DeleteProfileRequest.php @@ -0,0 +1,26 @@ +id = $id; + } + + public function resolveResourcePath(): string + { + return "profiles/{$this->id}"; + } +} diff --git a/src/Http/Requests/DeleteSalesInvoiceRequest.php b/src/Http/Requests/DeleteSalesInvoiceRequest.php new file mode 100644 index 000000000..c1d56cf21 --- /dev/null +++ b/src/Http/Requests/DeleteSalesInvoiceRequest.php @@ -0,0 +1,23 @@ +id = $id; + } + + public function resolveResourcePath(): string + { + return "sales-invoices/{$this->id}"; + } +} diff --git a/src/Http/Requests/DisableMethodIssuerRequest.php b/src/Http/Requests/DisableMethodIssuerRequest.php new file mode 100644 index 000000000..953a9c22d --- /dev/null +++ b/src/Http/Requests/DisableMethodIssuerRequest.php @@ -0,0 +1,32 @@ +profileId = $profileId; + $this->methodId = $methodId; + $this->issuerId = $issuerId; + } + + public function resolveResourcePath(): string + { + return "profiles/{$this->profileId}/methods/{$this->methodId}/issuers/{$this->issuerId}"; + } +} diff --git a/src/Http/Requests/DisableProfileMethodRequest.php b/src/Http/Requests/DisableProfileMethodRequest.php new file mode 100644 index 000000000..b687243f7 --- /dev/null +++ b/src/Http/Requests/DisableProfileMethodRequest.php @@ -0,0 +1,29 @@ +profileId = $profileId; + $this->methodId = $methodId; + } + + public function resolveResourcePath(): string + { + return "profiles/{$this->profileId}/methods/{$this->methodId}"; + } +} diff --git a/src/Http/Requests/DynamicGetRequest.php b/src/Http/Requests/DynamicGetRequest.php new file mode 100644 index 000000000..b3b959723 --- /dev/null +++ b/src/Http/Requests/DynamicGetRequest.php @@ -0,0 +1,29 @@ +query = $query; + } + + protected function defaultQuery(): array + { + return $this->query; + } +} diff --git a/src/Http/Requests/DynamicRequest.php b/src/Http/Requests/DynamicRequest.php new file mode 100644 index 000000000..1d5b7a27f --- /dev/null +++ b/src/Http/Requests/DynamicRequest.php @@ -0,0 +1,18 @@ +url = $url; + } + + public function resolveResourcePath(): string + { + return $this->url; + } +} diff --git a/src/Http/Requests/EnableMethodIssuerRequest.php b/src/Http/Requests/EnableMethodIssuerRequest.php new file mode 100644 index 000000000..aeec0d4d7 --- /dev/null +++ b/src/Http/Requests/EnableMethodIssuerRequest.php @@ -0,0 +1,55 @@ +profileId = $profileId; + $this->methodId = $methodId; + $this->issuerId = $issuerId; + $this->contractId = $contractId; + } + + protected function defaultPayload(): array + { + return [ + 'contractId' => $this->contractId, + ]; + } + + public function resolveResourcePath(): string + { + return "profiles/{$this->profileId}/methods/{$this->methodId}/issuers/{$this->issuerId}"; + } +} diff --git a/src/Http/Requests/EnableProfileMethodRequest.php b/src/Http/Requests/EnableProfileMethodRequest.php new file mode 100644 index 000000000..f0309cfc6 --- /dev/null +++ b/src/Http/Requests/EnableProfileMethodRequest.php @@ -0,0 +1,34 @@ +profileId = $profileId; + $this->methodId = $methodId; + } + + public function resolveResourcePath(): string + { + return "profiles/{$this->profileId}/methods/{$this->methodId}"; + } +} diff --git a/src/Http/Requests/GetAllMethodsRequest.php b/src/Http/Requests/GetAllMethodsRequest.php new file mode 100644 index 000000000..5ddab9469 --- /dev/null +++ b/src/Http/Requests/GetAllMethodsRequest.php @@ -0,0 +1,37 @@ +query = $query ?: new GetAllMethodsQuery; + } + + protected function defaultQuery(): array + { + return $this->query->toArray(); + } + + public function resolveResourcePath(): string + { + return 'methods/all'; + } +} diff --git a/src/Http/Requests/GetAllPaginatedSubscriptionsRequest.php b/src/Http/Requests/GetAllPaginatedSubscriptionsRequest.php new file mode 100644 index 000000000..ca69d815f --- /dev/null +++ b/src/Http/Requests/GetAllPaginatedSubscriptionsRequest.php @@ -0,0 +1,26 @@ +balanceId = $balanceId; + $this->query = $query; + } + + protected function defaultQuery(): array + { + return $this->query->toArray(); + } + + /** + * Resolve the resource path. + */ + public function resolveResourcePath(): string + { + return "balances/{$this->balanceId}/report"; + } +} diff --git a/src/Http/Requests/GetBalanceRequest.php b/src/Http/Requests/GetBalanceRequest.php new file mode 100644 index 000000000..9373c8e41 --- /dev/null +++ b/src/Http/Requests/GetBalanceRequest.php @@ -0,0 +1,29 @@ +id = $id; + } + + /** + * Resolve the resource path. + */ + public function resolveResourcePath(): string + { + return "balances/{$this->id}"; + } +} diff --git a/src/Http/Requests/GetClientRequest.php b/src/Http/Requests/GetClientRequest.php new file mode 100644 index 000000000..5f707ce43 --- /dev/null +++ b/src/Http/Requests/GetClientRequest.php @@ -0,0 +1,40 @@ +id = $id; + $this->query = $query; + } + + protected function defaultQuery(): array + { + return $this->query ? $this->query->toArray() : []; + } + + public function resolveResourcePath(): string + { + return "clients/{$this->id}"; + } +} diff --git a/src/Http/Requests/GetCustomerRequest.php b/src/Http/Requests/GetCustomerRequest.php new file mode 100644 index 000000000..c16eac87f --- /dev/null +++ b/src/Http/Requests/GetCustomerRequest.php @@ -0,0 +1,29 @@ +id = $id; + } + + /** + * Resolve the resource path. + */ + public function resolveResourcePath(): string + { + return "customers/{$this->id}"; + } +} diff --git a/src/Http/Requests/GetEnabledMethodsRequest.php b/src/Http/Requests/GetEnabledMethodsRequest.php new file mode 100644 index 000000000..60551bcef --- /dev/null +++ b/src/Http/Requests/GetEnabledMethodsRequest.php @@ -0,0 +1,32 @@ +query = $query; + } + + protected function defaultQuery(): array + { + return $this->query ? $this->query->toArray() : []; + } + + public function resolveResourcePath(): string + { + return 'methods'; + } +} diff --git a/src/Http/Requests/GetInvoiceRequest.php b/src/Http/Requests/GetInvoiceRequest.php new file mode 100644 index 000000000..83c870202 --- /dev/null +++ b/src/Http/Requests/GetInvoiceRequest.php @@ -0,0 +1,28 @@ +id = $id; + } + + /** + * Resolve the resource path. + */ + public function resolveResourcePath(): string + { + return "invoices/{$this->id}"; + } +} diff --git a/src/Http/Requests/GetMandateRequest.php b/src/Http/Requests/GetMandateRequest.php new file mode 100644 index 000000000..04d0ff03b --- /dev/null +++ b/src/Http/Requests/GetMandateRequest.php @@ -0,0 +1,35 @@ +customerId = $customerId; + $this->mandateId = $mandateId; + } + + public function resolveResourcePath(): string + { + return "customers/{$this->customerId}/mandates/{$this->mandateId}"; + } +} diff --git a/src/Http/Requests/GetOnboardingStatusRequest.php b/src/Http/Requests/GetOnboardingStatusRequest.php new file mode 100644 index 000000000..84ddbf975 --- /dev/null +++ b/src/Http/Requests/GetOnboardingStatusRequest.php @@ -0,0 +1,18 @@ +id = $id; + } + + public function resolveResourcePath(): string + { + return "organizations/{$this->id}"; + } +} diff --git a/src/Http/Requests/GetPaginatedBalanceRequest.php b/src/Http/Requests/GetPaginatedBalanceRequest.php new file mode 100644 index 000000000..4b7b6394b --- /dev/null +++ b/src/Http/Requests/GetPaginatedBalanceRequest.php @@ -0,0 +1,26 @@ +balanceId = $balanceId; + } + + public function resolveResourcePath(): string + { + return "balances/{$this->balanceId}/transactions"; + } +} diff --git a/src/Http/Requests/GetPaginatedChargebacksRequest.php b/src/Http/Requests/GetPaginatedChargebacksRequest.php new file mode 100644 index 000000000..488a3bdad --- /dev/null +++ b/src/Http/Requests/GetPaginatedChargebacksRequest.php @@ -0,0 +1,23 @@ +customerId = $customerId; + } + + public function resolveResourcePath(): string + { + return "customers/{$this->customerId}/payments"; + } +} diff --git a/src/Http/Requests/GetPaginatedCustomerRequest.php b/src/Http/Requests/GetPaginatedCustomerRequest.php new file mode 100644 index 000000000..fbd7e1b2a --- /dev/null +++ b/src/Http/Requests/GetPaginatedCustomerRequest.php @@ -0,0 +1,20 @@ +customerId = $customerId; + } + + public function resolveResourcePath(): string + { + return "customers/{$this->customerId}/mandates"; + } +} diff --git a/src/Http/Requests/GetPaginatedPaymentCapturesRequest.php b/src/Http/Requests/GetPaginatedPaymentCapturesRequest.php new file mode 100644 index 000000000..6cbbd8188 --- /dev/null +++ b/src/Http/Requests/GetPaginatedPaymentCapturesRequest.php @@ -0,0 +1,48 @@ +paymentId = $paymentId; + $this->query = $query; + } + + protected function defaultQuery(): array + { + return $this->query ? $this->query->toArray() : []; + } + + /** + * Resolve the resource path. + */ + public function resolveResourcePath(): string + { + return "payments/{$this->paymentId}/captures"; + } +} diff --git a/src/Http/Requests/GetPaginatedPaymentChargebacksRequest.php b/src/Http/Requests/GetPaginatedPaymentChargebacksRequest.php new file mode 100644 index 000000000..ed51d048b --- /dev/null +++ b/src/Http/Requests/GetPaginatedPaymentChargebacksRequest.php @@ -0,0 +1,39 @@ +paymentId = $paymentId; + } + + public function resolveResourcePath(): string + { + return "payments/{$this->paymentId}/chargebacks"; + } +} diff --git a/src/Http/Requests/GetPaginatedPaymentLinkPaymentsRequest.php b/src/Http/Requests/GetPaginatedPaymentLinkPaymentsRequest.php new file mode 100644 index 000000000..d23914a28 --- /dev/null +++ b/src/Http/Requests/GetPaginatedPaymentLinkPaymentsRequest.php @@ -0,0 +1,35 @@ +paymentLinkId = $paymentLinkId; + } + + /** + * Resolve the resource path. + */ + public function resolveResourcePath(): string + { + return "payment-links/{$this->paymentLinkId}/payments"; + } +} diff --git a/src/Http/Requests/GetPaginatedPaymentLinksRequest.php b/src/Http/Requests/GetPaginatedPaymentLinksRequest.php new file mode 100644 index 000000000..5c05b2180 --- /dev/null +++ b/src/Http/Requests/GetPaginatedPaymentLinksRequest.php @@ -0,0 +1,29 @@ +paymentId = $paymentId; + } + + public function resolveResourcePath(): string + { + return "payments/{$this->paymentId}/refunds"; + } +} diff --git a/src/Http/Requests/GetPaginatedPaymentsRequest.php b/src/Http/Requests/GetPaginatedPaymentsRequest.php new file mode 100644 index 000000000..18c7f0f6c --- /dev/null +++ b/src/Http/Requests/GetPaginatedPaymentsRequest.php @@ -0,0 +1,26 @@ +settlementId = $settlementId; + + parent::__construct($query); + } + + /** + * Resolve the resource path. + */ + public function resolveResourcePath(): string + { + return "settlements/{$this->settlementId}/captures"; + } +} diff --git a/src/Http/Requests/GetPaginatedSettlementChargebacksRequest.php b/src/Http/Requests/GetPaginatedSettlementChargebacksRequest.php new file mode 100644 index 000000000..b846929ad --- /dev/null +++ b/src/Http/Requests/GetPaginatedSettlementChargebacksRequest.php @@ -0,0 +1,36 @@ +settlementId = $settlementId; + + parent::__construct($query); + } + + /** + * Resolve the resource path. + */ + public function resolveResourcePath(): string + { + return "settlements/{$this->settlementId}/chargebacks"; + } +} diff --git a/src/Http/Requests/GetPaginatedSettlementPaymentsRequest.php b/src/Http/Requests/GetPaginatedSettlementPaymentsRequest.php new file mode 100644 index 000000000..20770a80e --- /dev/null +++ b/src/Http/Requests/GetPaginatedSettlementPaymentsRequest.php @@ -0,0 +1,36 @@ +settlementId = $settlementId; + + parent::__construct($query); + } + + /** + * Resolve the resource path. + */ + public function resolveResourcePath(): string + { + return "settlements/{$this->settlementId}/payments"; + } +} diff --git a/src/Http/Requests/GetPaginatedSettlementRefundsRequest.php b/src/Http/Requests/GetPaginatedSettlementRefundsRequest.php new file mode 100644 index 000000000..4d33a662b --- /dev/null +++ b/src/Http/Requests/GetPaginatedSettlementRefundsRequest.php @@ -0,0 +1,36 @@ +settlementId = $settlementId; + + parent::__construct($query); + } + + /** + * Resolve the resource path. + */ + public function resolveResourcePath(): string + { + return "settlements/{$this->settlementId}/refunds"; + } +} diff --git a/src/Http/Requests/GetPaginatedSettlementsRequest.php b/src/Http/Requests/GetPaginatedSettlementsRequest.php new file mode 100644 index 000000000..427d59c1c --- /dev/null +++ b/src/Http/Requests/GetPaginatedSettlementsRequest.php @@ -0,0 +1,25 @@ +customerId = $customerId; + $this->subscriptionId = $subscriptionId; + + parent::__construct($query); + } + + /** + * The resource path. + */ + public function resolveResourcePath(): string + { + return "customers/{$this->customerId}/subscriptions/{$this->subscriptionId}/payments"; + } +} diff --git a/src/Http/Requests/GetPaginatedSubscriptionsRequest.php b/src/Http/Requests/GetPaginatedSubscriptionsRequest.php new file mode 100644 index 000000000..aa7bfedcf --- /dev/null +++ b/src/Http/Requests/GetPaginatedSubscriptionsRequest.php @@ -0,0 +1,36 @@ +customerId = $customerId; + + parent::__construct($query); + } + + /** + * The resource path. + */ + public function resolveResourcePath(): string + { + return "customers/{$this->customerId}/subscriptions"; + } +} diff --git a/src/Http/Requests/GetPaginatedTerminalsRequest.php b/src/Http/Requests/GetPaginatedTerminalsRequest.php new file mode 100644 index 000000000..d85d0f965 --- /dev/null +++ b/src/Http/Requests/GetPaginatedTerminalsRequest.php @@ -0,0 +1,26 @@ +paymentId = $paymentId; + $this->captureId = $captureId; + $this->query = $query; + } + + protected function defaultQuery(): array + { + return $this->query ? $this->query->toArray() : []; + } + + public function resolveResourcePath(): string + { + return "payments/{$this->paymentId}/captures/{$this->captureId}"; + } +} diff --git a/src/Http/Requests/GetPaymentChargebackRequest.php b/src/Http/Requests/GetPaymentChargebackRequest.php new file mode 100644 index 000000000..a1ac16903 --- /dev/null +++ b/src/Http/Requests/GetPaymentChargebackRequest.php @@ -0,0 +1,44 @@ +paymentId = $paymentId; + $this->chargebackId = $chargebackId; + $this->query = $query; + } + + protected function defaultQuery(): array + { + return $this->query ? $this->query->toArray() : []; + } + + public function resolveResourcePath(): string + { + return "payments/{$this->paymentId}/chargebacks/{$this->chargebackId}"; + } +} diff --git a/src/Http/Requests/GetPaymentLinkRequest.php b/src/Http/Requests/GetPaymentLinkRequest.php new file mode 100644 index 000000000..f50229d66 --- /dev/null +++ b/src/Http/Requests/GetPaymentLinkRequest.php @@ -0,0 +1,35 @@ +id = $id; + } + + /** + * Resolve the resource path. + */ + public function resolveResourcePath(): string + { + return "payment-links/{$this->id}"; + } +} diff --git a/src/Http/Requests/GetPaymentMethodRequest.php b/src/Http/Requests/GetPaymentMethodRequest.php new file mode 100644 index 000000000..882a2c4f3 --- /dev/null +++ b/src/Http/Requests/GetPaymentMethodRequest.php @@ -0,0 +1,35 @@ +methodId = $methodId; + $this->query = $query; + } + + protected function defaultQuery(): array + { + return $this->query ? $this->query->toArray() : []; + } + + public function resolveResourcePath(): string + { + return "methods/{$this->methodId}"; + } +} diff --git a/src/Http/Requests/GetPaymentRefundRequest.php b/src/Http/Requests/GetPaymentRefundRequest.php new file mode 100644 index 000000000..ebdfed5d6 --- /dev/null +++ b/src/Http/Requests/GetPaymentRefundRequest.php @@ -0,0 +1,47 @@ +paymentId = $paymentId; + $this->refundId = $refundId; + $this->query = $query; + } + + protected function defaultQuery(): array + { + return $this->query ? $this->query->toArray() : []; + } + + /** + * Resolve the resource path. + */ + public function resolveResourcePath(): string + { + return "payments/{$this->paymentId}/refunds/{$this->refundId}"; + } +} diff --git a/src/Http/Requests/GetPaymentRequest.php b/src/Http/Requests/GetPaymentRequest.php new file mode 100644 index 000000000..683e9dfac --- /dev/null +++ b/src/Http/Requests/GetPaymentRequest.php @@ -0,0 +1,46 @@ +id = $id; + $this->query = $query; + } + + protected function defaultQuery(): array + { + return $this->query ? $this->query->toArray() : []; + } + + /** + * Resolve the resource path. + */ + public function resolveResourcePath(): string + { + return "payments/{$this->id}"; + } +} diff --git a/src/Http/Requests/GetPermissionRequest.php b/src/Http/Requests/GetPermissionRequest.php new file mode 100644 index 000000000..95e5184df --- /dev/null +++ b/src/Http/Requests/GetPermissionRequest.php @@ -0,0 +1,29 @@ +id = $id; + } + + public function resolveResourcePath(): string + { + return "permissions/{$this->id}"; + } +} diff --git a/src/Http/Requests/GetProfileRequest.php b/src/Http/Requests/GetProfileRequest.php new file mode 100644 index 000000000..b95d553dc --- /dev/null +++ b/src/Http/Requests/GetProfileRequest.php @@ -0,0 +1,29 @@ +id = $id; + } + + public function resolveResourcePath(): string + { + return "profiles/{$this->id}"; + } +} diff --git a/src/Http/Requests/GetSalesInvoiceRequest.php b/src/Http/Requests/GetSalesInvoiceRequest.php new file mode 100644 index 000000000..224da3b90 --- /dev/null +++ b/src/Http/Requests/GetSalesInvoiceRequest.php @@ -0,0 +1,31 @@ +id = $id; + } + + public function resolveResourcePath(): string + { + return "sales-invoices/{$this->id}"; + } +} diff --git a/src/Http/Requests/GetSessionRequest.php b/src/Http/Requests/GetSessionRequest.php new file mode 100644 index 000000000..4bf471fb0 --- /dev/null +++ b/src/Http/Requests/GetSessionRequest.php @@ -0,0 +1,34 @@ +sessionId = $sessionId; + $this->query = $query; + } + + protected function defaultQuery(): array + { + return $this->query->toArray(); + } + + public function resolveResourcePath(): string + { + return "sessions/{$this->sessionId}"; + } +} diff --git a/src/Http/Requests/GetSettlementRequest.php b/src/Http/Requests/GetSettlementRequest.php new file mode 100644 index 000000000..bb25e8973 --- /dev/null +++ b/src/Http/Requests/GetSettlementRequest.php @@ -0,0 +1,26 @@ +id = $id; + } + + public function resolveResourcePath(): string + { + return "settlements/{$this->id}"; + } +} diff --git a/src/Http/Requests/GetSubscriptionRequest.php b/src/Http/Requests/GetSubscriptionRequest.php new file mode 100644 index 000000000..722465ac0 --- /dev/null +++ b/src/Http/Requests/GetSubscriptionRequest.php @@ -0,0 +1,35 @@ +customerId = $customerId; + $this->id = $id; + } + + public function resolveResourcePath(): string + { + return "customers/{$this->customerId}/subscriptions/{$this->id}"; + } +} diff --git a/src/Http/Requests/GetTerminalRequest.php b/src/Http/Requests/GetTerminalRequest.php new file mode 100644 index 000000000..c9cc5bf14 --- /dev/null +++ b/src/Http/Requests/GetTerminalRequest.php @@ -0,0 +1,32 @@ +id = $id; + } + + /** + * The resource path. + */ + public function resolveResourcePath(): string + { + return "terminals/{$this->id}"; + } +} diff --git a/src/Http/Requests/ListPermissionsRequest.php b/src/Http/Requests/ListPermissionsRequest.php new file mode 100644 index 000000000..b2c4c2d76 --- /dev/null +++ b/src/Http/Requests/ListPermissionsRequest.php @@ -0,0 +1,21 @@ +query = $query; + } + + protected function defaultQuery(): array + { + return $this->query + ? $this->query->toArray() + : []; + } +} diff --git a/src/Http/Requests/ResourceHydratableRequest.php b/src/Http/Requests/ResourceHydratableRequest.php new file mode 100644 index 000000000..b08748197 --- /dev/null +++ b/src/Http/Requests/ResourceHydratableRequest.php @@ -0,0 +1,61 @@ +hydratableResource !== null || $this->customHydratableResource !== null; + } + + /** + * @return string|WrapperResource + */ + public function getHydratableResource() + { + if (! $this->isHydratable()) { + throw new \RuntimeException('Resource class is not set.'); + } + + return $this->customHydratableResource ?? $this->hydratableResource; + } + + /** + * @param string|WrapperResource $hydratableResource + */ + public function setHydratableResource($hydratableResource): self + { + $this->customHydratableResource = $hydratableResource; + + if (! $this->hydratableResource && $this->customHydratableResource instanceof WrapperResource) { + $this->hydratableResource = $this->customHydratableResource->getWrapper(); + } + + return $this; + } + + public function resetHydratableResource(): self + { + $this->customHydratableResource = null; + + return $this; + } +} diff --git a/src/Http/Requests/RevokeMandateRequest.php b/src/Http/Requests/RevokeMandateRequest.php new file mode 100644 index 000000000..f54e07d57 --- /dev/null +++ b/src/Http/Requests/RevokeMandateRequest.php @@ -0,0 +1,30 @@ +customerId = $customerId; + $this->mandateId = $mandateId; + } + + public function resolveResourcePath(): string + { + return "customers/{$this->customerId}/mandates/{$this->mandateId}"; + } +} diff --git a/src/Http/Requests/UpdateCustomerRequest.php b/src/Http/Requests/UpdateCustomerRequest.php new file mode 100644 index 000000000..3059034b9 --- /dev/null +++ b/src/Http/Requests/UpdateCustomerRequest.php @@ -0,0 +1,41 @@ +id = $id; + $this->payload = $payload; + } + + protected function defaultPayload(): array + { + return $this->payload->toArray(); + } + + public function resolveResourcePath(): string + { + return "customers/{$this->id}"; + } +} diff --git a/src/Http/Requests/UpdatePaymentLinkRequest.php b/src/Http/Requests/UpdatePaymentLinkRequest.php new file mode 100644 index 000000000..ee312fba8 --- /dev/null +++ b/src/Http/Requests/UpdatePaymentLinkRequest.php @@ -0,0 +1,42 @@ +id = $id; + $this->payload = $payload; + } + + protected function defaultPayload(): array + { + return $this->payload->toArray(); + } + + public function resolveResourcePath(): string + { + return "payment-links/{$this->id}"; + } +} diff --git a/src/Http/Requests/UpdatePaymentRequest.php b/src/Http/Requests/UpdatePaymentRequest.php new file mode 100644 index 000000000..83b7e6091 --- /dev/null +++ b/src/Http/Requests/UpdatePaymentRequest.php @@ -0,0 +1,42 @@ +id = $id; + $this->payload = $payload; + } + + protected function defaultPayload(): array + { + return $this->payload->toArray(); + } + + public function resolveResourcePath(): string + { + return "payments/{$this->id}"; + } +} diff --git a/src/Http/Requests/UpdatePaymentRouteRequest.php b/src/Http/Requests/UpdatePaymentRouteRequest.php new file mode 100644 index 000000000..9c282eee5 --- /dev/null +++ b/src/Http/Requests/UpdatePaymentRouteRequest.php @@ -0,0 +1,48 @@ +paymentId = $paymentId; + $this->routeId = $routeId; + $this->payload = $payload; + } + + protected function defaultPayload(): array + { + return $this->payload->toArray(); + } + + public function resolveResourcePath(): string + { + return "payments/{$this->paymentId}/routes/{$this->routeId}"; + } +} diff --git a/src/Http/Requests/UpdateProfileRequest.php b/src/Http/Requests/UpdateProfileRequest.php new file mode 100644 index 000000000..63340b4a8 --- /dev/null +++ b/src/Http/Requests/UpdateProfileRequest.php @@ -0,0 +1,41 @@ +id = $id; + $this->payload = $payload; + } + + protected function defaultPayload(): array + { + return $this->payload->toArray(); + } + + public function resolveResourcePath(): string + { + return "profiles/{$this->id}"; + } +} diff --git a/src/Http/Requests/UpdateSalesInvoiceRequest.php b/src/Http/Requests/UpdateSalesInvoiceRequest.php new file mode 100644 index 000000000..f03d8d1d1 --- /dev/null +++ b/src/Http/Requests/UpdateSalesInvoiceRequest.php @@ -0,0 +1,38 @@ +id = $id; + $this->payload = $payload; + } + + public function resolveResourcePath(): string + { + return "sales-invoices/{$this->id}"; + } + + public function defaultPayload(): array + { + return $this->payload->toArray(); + } +} diff --git a/src/Http/Requests/UpdateSessionRequest.php b/src/Http/Requests/UpdateSessionRequest.php new file mode 100644 index 000000000..33ff0c075 --- /dev/null +++ b/src/Http/Requests/UpdateSessionRequest.php @@ -0,0 +1,38 @@ +sessionId = $sessionId; + $this->payload = $payload; + } + + protected function defaultPayload(): array + { + return $this->payload->toArray(); + } + + public function resolveResourcePath(): string + { + return "sessions/{$this->sessionId}"; + } +} diff --git a/src/Http/Requests/UpdateSubscriptionRequest.php b/src/Http/Requests/UpdateSubscriptionRequest.php new file mode 100644 index 000000000..4c63bafa3 --- /dev/null +++ b/src/Http/Requests/UpdateSubscriptionRequest.php @@ -0,0 +1,54 @@ +customerId = $customerId; + $this->subscriptionId = $subscriptionId; + $this->payload = $payload; + } + + protected function defaultPayload(): array + { + return $this->payload->toArray(); + } + + /** + * The resource path. + */ + public function resolveResourcePath(): string + { + return "customers/{$this->customerId}/subscriptions/{$this->subscriptionId}"; + } +} diff --git a/src/Http/Response.php b/src/Http/Response.php new file mode 100644 index 000000000..0cf55c156 --- /dev/null +++ b/src/Http/Response.php @@ -0,0 +1,135 @@ +psrResponse = $psrResponse; + $this->psrRequest = $psrRequest; + $this->pendingRequest = $pendingRequest; + $this->senderException = $senderException; + } + + /** + * Get the JSON decoded body of the response as an array or scalar value. + */ + public function json(): stdClass + { + if (! $this->decoded) { + $this->decoded = (object) @json_decode($body = $this->body() ?: '{}'); + + if (json_last_error() !== JSON_ERROR_NONE) { + throw new ApiException("Unable to decode Mollie response: '{$body}'."); + } + } + + return $this->decoded; + } + + public function getConnector(): Connector + { + return $this->pendingRequest->getConnector(); + } + + public function getPendingRequest(): PendingRequest + { + return $this->pendingRequest; + } + + public function getRequest(): Request + { + return $this->pendingRequest->getRequest(); + } + + public function getPsrRequest(): RequestInterface + { + return $this->psrRequest; + } + + public function getPsrResponse(): ResponseInterface + { + return $this->psrResponse; + } + + public function getSenderException(): ?Throwable + { + return $this->senderException; + } + + /** + * Get the body of the response as string. + */ + public function body(): string + { + $stream = $this->stream(); + + $contents = $stream->getContents(); + + if ($stream->isSeekable()) { + $stream->rewind(); + } + + return $contents; + } + + /** + * Get the body as a stream. + */ + public function stream(): StreamInterface + { + $stream = $this->psrResponse->getBody(); + + if ($stream->isSeekable()) { + $stream->rewind(); + } + + return $stream; + } + + public function status(): int + { + return $this->psrResponse->getStatusCode(); + } + + public function successful(): bool + { + return $this->status() >= 200 && $this->status() < 300; + } + + public function isUnprocessable(): bool + { + return $this->status() === ResponseStatusCode::HTTP_UNPROCESSABLE_ENTITY; + } + + public function isEmpty(): bool + { + return empty($this->body()); + } +} diff --git a/src/Http/ResponseStatusCode.php b/src/Http/ResponseStatusCode.php new file mode 100644 index 000000000..6ccea9096 --- /dev/null +++ b/src/Http/ResponseStatusCode.php @@ -0,0 +1,132 @@ +attemptRequest($httpMethod, $url, $headers, $httpBody); - } catch (CurlConnectTimeoutException $e) { - // Nothing - } - } - - throw new CurlConnectTimeoutException( - "Unable to connect to Mollie. Maximum number of retries (". self::MAX_RETRIES .") reached." - ); - } - - /** - * @param string $httpMethod - * @param string $url - * @param array $headers - * @param string $httpBody - * @return \stdClass|void|null - * @throws \Mollie\Api\Exceptions\ApiException - */ - protected function attemptRequest($httpMethod, $url, $headers, $httpBody) - { - $curl = curl_init($url); - $headers["Content-Type"] = "application/json"; - - curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); - curl_setopt($curl, CURLOPT_HTTPHEADER, $this->parseHeaders($headers)); - curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, self::DEFAULT_CONNECT_TIMEOUT); - curl_setopt($curl, CURLOPT_TIMEOUT, self::DEFAULT_TIMEOUT); - curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, true); - curl_setopt($curl, CURLOPT_CAINFO, CaBundle::getBundledCaBundlePath()); - - switch ($httpMethod) { - case MollieApiClient::HTTP_POST: - curl_setopt($curl, CURLOPT_POST, true); - curl_setopt($curl, CURLOPT_POSTFIELDS, $httpBody); - - break; - case MollieApiClient::HTTP_GET: - break; - case MollieApiClient::HTTP_PATCH: - curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PATCH'); - curl_setopt($curl, CURLOPT_POSTFIELDS, $httpBody); - - break; - case MollieApiClient::HTTP_DELETE: - curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE'); - curl_setopt($curl, CURLOPT_POSTFIELDS, $httpBody); - - break; - default: - throw new \InvalidArgumentException("Invalid http method: ". $httpMethod); - } - - $startTime = microtime(true); - $response = curl_exec($curl); - $endTime = microtime(true); - - if ($response === false) { - $executionTime = $endTime - $startTime; - $curlErrorNumber = curl_errno($curl); - $curlErrorMessage = "Curl error: " . curl_error($curl); - - if ($this->isConnectTimeoutError($curlErrorNumber, $executionTime)) { - throw new CurlConnectTimeoutException("Unable to connect to Mollie. " . $curlErrorMessage); - } - - throw new ApiException($curlErrorMessage); - } - - $statusCode = curl_getinfo($curl, CURLINFO_RESPONSE_CODE); - curl_close($curl); - - return $this->parseResponseBody($response, $statusCode, $httpBody); - } - - /** - * The version number for the underlying http client, if available. - * @example Guzzle/6.3 - * - * @return string|null - */ - public function versionString() - { - return 'Curl/*'; - } - - /** - * Whether this http adapter provides a debugging mode. If debugging mode is enabled, the - * request will be included in the ApiException. - * - * @return false - */ - public function supportsDebugging() - { - return false; - } - - /** - * @param int $curlErrorNumber - * @param string|float $executionTime - * @return bool - */ - protected function isConnectTimeoutError($curlErrorNumber, $executionTime) - { - $connectErrors = [ - \CURLE_COULDNT_RESOLVE_HOST => true, - \CURLE_COULDNT_CONNECT => true, - \CURLE_SSL_CONNECT_ERROR => true, - \CURLE_GOT_NOTHING => true, - ]; - - if (isset($connectErrors[$curlErrorNumber])) { - return true; - }; - - if ($curlErrorNumber === \CURLE_OPERATION_TIMEOUTED) { - if ($executionTime > self::DEFAULT_TIMEOUT) { - return false; - } - - return true; - } - - return false; - } - - /** - * @param string $response - * @param int $statusCode - * @param string $httpBody - * @return \stdClass|null - * @throws \Mollie\Api\Exceptions\ApiException - */ - protected function parseResponseBody($response, $statusCode, $httpBody) - { - if (empty($response)) { - if ($statusCode === self::HTTP_NO_CONTENT) { - return null; - } - - throw new ApiException("No response body found."); - } - - $body = @json_decode($response); - - // GUARDS - if (json_last_error() !== JSON_ERROR_NONE) { - throw new ApiException("Unable to decode Mollie response: '{$response}'."); - } - - if (isset($body->error)) { - throw new ApiException($body->error->message); - } - - if ($statusCode >= 400) { - $message = "Error executing API call ({$body->status}: {$body->title}): {$body->detail}"; - - $field = null; - - if (! empty($body->field)) { - $field = $body->field; - } - - if (isset($body->_links, $body->_links->documentation)) { - $message .= ". Documentation: {$body->_links->documentation->href}"; - } - - if ($httpBody) { - $message .= ". Request body: {$httpBody}"; - } - - throw new ApiException($message, $statusCode, $field); - } - - return $body; - } - - protected function parseHeaders($headers) - { - $result = []; - - foreach ($headers as $key => $value) { - $result[] = $key .': ' . $value; - } - - return $result; - } -} diff --git a/src/HttpAdapter/Guzzle6And7MollieHttpAdapter.php b/src/HttpAdapter/Guzzle6And7MollieHttpAdapter.php deleted file mode 100644 index a9e27cdb3..000000000 --- a/src/HttpAdapter/Guzzle6And7MollieHttpAdapter.php +++ /dev/null @@ -1,198 +0,0 @@ -httpClient = $httpClient; - } - - /** - * Instantiate a default adapter with sane configuration for Guzzle 6 or 7. - * - * @return static - */ - public static function createDefault() - { - $retryMiddlewareFactory = new Guzzle6And7RetryMiddlewareFactory; - $handlerStack = HandlerStack::create(); - $handlerStack->push($retryMiddlewareFactory->retry()); - - $client = new Client([ - GuzzleRequestOptions::VERIFY => CaBundle::getBundledCaBundlePath(), - GuzzleRequestOptions::TIMEOUT => self::DEFAULT_TIMEOUT, - GuzzleRequestOptions::CONNECT_TIMEOUT => self::DEFAULT_CONNECT_TIMEOUT, - 'handler' => $handlerStack, - ]); - - return new Guzzle6And7MollieHttpAdapter($client); - } - - /** - * Send a request to the specified Mollie api url. - * - * @param string $httpMethod - * @param string $url - * @param array $headers - * @param string $httpBody - * @return \stdClass|null - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function send($httpMethod, $url, $headers, $httpBody) - { - $request = new Request($httpMethod, $url, $headers, $httpBody); - - try { - $response = $this->httpClient->send($request, ['http_errors' => false]); - } catch (GuzzleException $e) { - // Prevent sensitive request data from ending up in exception logs unintended - if (! $this->debugging) { - $request = null; - } - - // Not all Guzzle Exceptions implement hasResponse() / getResponse() - if (method_exists($e, 'hasResponse') && method_exists($e, 'getResponse')) { - if ($e->hasResponse()) { - throw ApiException::createFromResponse($e->getResponse(), $request); - } - } - - throw new ApiException($e->getMessage(), $e->getCode(), null, $request, null); - } - - return $this->parseResponseBody($response); - } - - /** - * Whether this http adapter provides a debugging mode. If debugging mode is enabled, the - * request will be included in the ApiException. - * - * @return true - */ - public function supportsDebugging() - { - return true; - } - - /** - * Whether debugging is enabled. If debugging mode is enabled, the request will - * be included in the ApiException. By default, debugging is disabled to prevent - * sensitive request data from leaking into exception logs. - * - * @return bool - */ - public function debugging() - { - return $this->debugging; - } - - /** - * Enable debugging. If debugging mode is enabled, the request will - * be included in the ApiException. By default, debugging is disabled to prevent - * sensitive request data from leaking into exception logs. - */ - public function enableDebugging() - { - $this->debugging = true; - } - - /** - * Disable debugging. If debugging mode is enabled, the request will - * be included in the ApiException. By default, debugging is disabled to prevent - * sensitive request data from leaking into exception logs. - */ - public function disableDebugging() - { - $this->debugging = false; - } - - /** - * Parse the PSR-7 Response body - * - * @param ResponseInterface $response - * @return \stdClass|null - * @throws ApiException - */ - private function parseResponseBody(ResponseInterface $response) - { - $body = (string) $response->getBody(); - if (empty($body)) { - if ($response->getStatusCode() === self::HTTP_NO_CONTENT) { - return null; - } - - throw new ApiException("No response body found."); - } - - $object = @json_decode($body); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw new ApiException("Unable to decode Mollie response: '{$body}'."); - } - - if ($response->getStatusCode() >= 400) { - throw ApiException::createFromResponse($response, null); - } - - return $object; - } - - /** - * The version number for the underlying http client, if available. This is used to report the UserAgent to Mollie, - * for convenient support. - * @example Guzzle/6.3 - * - * @return string|null - */ - public function versionString() - { - if (defined('\GuzzleHttp\ClientInterface::MAJOR_VERSION')) { // Guzzle 7 - return "Guzzle/" . ClientInterface::MAJOR_VERSION; - } elseif (defined('\GuzzleHttp\ClientInterface::VERSION')) { // Before Guzzle 7 - return "Guzzle/" . ClientInterface::VERSION; - } - - return null; - } -} diff --git a/src/HttpAdapter/MollieHttpAdapterInterface.php b/src/HttpAdapter/MollieHttpAdapterInterface.php deleted file mode 100644 index 226bbef85..000000000 --- a/src/HttpAdapter/MollieHttpAdapterInterface.php +++ /dev/null @@ -1,26 +0,0 @@ -length; diff --git a/src/Idempotency/FakeIdempotencyKeyGenerator.php b/src/Idempotency/FakeIdempotencyKeyGenerator.php index 95871939f..fa9a4587b 100644 --- a/src/Idempotency/FakeIdempotencyKeyGenerator.php +++ b/src/Idempotency/FakeIdempotencyKeyGenerator.php @@ -4,17 +4,18 @@ namespace Mollie\Api\Idempotency; +use Mollie\Api\Contracts\IdempotencyKeyGeneratorContract; + class FakeIdempotencyKeyGenerator implements IdempotencyKeyGeneratorContract { - /** @var string */ - private $fakeKey; + private string $fakeKey; - public function setFakeKey($fakeKey) + public function setFakeKey($fakeKey): void { $this->fakeKey = $fakeKey; } - public function generate() + public function generate(): string { return $this->fakeKey; } diff --git a/src/Idempotency/IdempotencyKeyGeneratorContract.php b/src/Idempotency/IdempotencyKeyGeneratorContract.php deleted file mode 100644 index 6ffe80ca6..000000000 --- a/src/Idempotency/IdempotencyKeyGeneratorContract.php +++ /dev/null @@ -1,7 +0,0 @@ -httpClient = $httpAdapterPicker->pickHttpAdapter($httpClient); - - $compatibilityChecker = new CompatibilityChecker; - $compatibilityChecker->checkCompatibility(); - - $this->initializeEndpoints(); - $this->initializeVersionStrings(); - $this->initializeIdempotencyKeyGenerator($idempotencyKeyGenerator); - } - - public function initializeEndpoints() - { - $this->balanceReports = new BalanceReportEndpoint($this); - $this->balanceTransactions = new BalanceTransactionEndpoint($this); - $this->balances = new BalanceEndpoint($this); - $this->chargebacks = new ChargebackEndpoint($this); - $this->clientLinks = new ClientLinkEndpoint($this); - $this->clients = new ClientEndpoint($this); - $this->customerPayments = new CustomerPaymentsEndpoint($this); - $this->customers = new CustomerEndpoint($this); - $this->invoices = new InvoiceEndpoint($this); - $this->mandates = new MandateEndpoint($this); - $this->methods = new MethodEndpoint($this); - $this->methodIssuers = new MethodIssuerEndpoint($this); - $this->onboarding = new OnboardingEndpoint($this); - $this->orderLines = new OrderLineEndpoint($this); - $this->orderPayments = new OrderPaymentEndpoint($this); - $this->orderRefunds = new OrderRefundEndpoint($this); - $this->orders = new OrderEndpoint($this); - $this->organizationPartners = new OrganizationPartnerEndpoint($this); - $this->organizations = new OrganizationEndpoint($this); - $this->paymentCaptures = new PaymentCaptureEndpoint($this); - $this->paymentChargebacks = new PaymentChargebackEndpoint($this); - $this->paymentLinkPayments = new PaymentLinkPaymentEndpoint($this); - $this->paymentLinks = new PaymentLinkEndpoint($this); - $this->paymentRefunds = new PaymentRefundEndpoint($this); - $this->paymentRoutes = new PaymentRouteEndpoint($this); - $this->payments = new PaymentEndpoint($this); - $this->permissions = new PermissionEndpoint($this); - $this->profileMethods = new ProfileMethodEndpoint($this); - $this->profiles = new ProfileEndpoint($this); - $this->refunds = new RefundEndpoint($this); - $this->settlementCaptures = new SettlementCaptureEndpoint($this); - $this->settlementChargebacks = new SettlementChargebackEndpoint($this); - $this->settlementPayments = new SettlementPaymentEndpoint($this); - $this->settlementRefunds = new SettlementRefundEndpoint($this); - $this->settlements = new SettlementsEndpoint($this); - $this->sessions = new SessionEndpoint($this); - $this->shipments = new ShipmentEndpoint($this); - $this->subscriptionPayments = new SubscriptionPaymentEndpoint($this); - $this->subscriptions = new SubscriptionEndpoint($this); - $this->terminals = new TerminalEndpoint($this); - $this->wallets = new WalletEndpoint($this); - } - - protected function initializeVersionStrings() - { - $this->addVersionString("Mollie/" . self::CLIENT_VERSION); - $this->addVersionString("PHP/" . phpversion()); - - $httpClientVersionString = $this->httpClient->versionString(); - if ($httpClientVersionString) { - $this->addVersionString($httpClientVersionString); - } - } - - /** - * @param \Mollie\Api\Idempotency\IdempotencyKeyGeneratorContract $generator - * @return void - */ - protected function initializeIdempotencyKeyGenerator($generator) - { - $this->idempotencyKeyGenerator = $generator ? $generator : new DefaultIdempotencyKeyGenerator; - } - - /** - * @param string $url - * - * @return MollieApiClient - */ - public function setApiEndpoint($url) - { - $this->apiEndpoint = rtrim(trim($url), '/'); - - return $this; - } - - /** - * @return string - */ - public function getApiEndpoint() - { - return $this->apiEndpoint; - } - - /** - * @return array - */ - public function getVersionStrings() - { - return $this->versionStrings; - } - - /** - * @param string $apiKey The Mollie API key, starting with 'test_' or 'live_' - * - * @return MollieApiClient - * @throws ApiException - */ - public function setApiKey($apiKey) - { - $apiKey = trim($apiKey); - - if (! preg_match('/^(live|test)_\w{30,}$/', $apiKey)) { - throw new ApiException("Invalid API key: '{$apiKey}'. An API key must start with 'test_' or 'live_' and must be at least 30 characters long."); - } - - $this->apiKey = $apiKey; - $this->oauthAccess = false; - - return $this; - } - - /** - * @param string $accessToken OAuth access token, starting with 'access_' - * - * @return MollieApiClient - * @throws ApiException - */ - public function setAccessToken($accessToken) - { - $accessToken = trim($accessToken); - - if (! preg_match('/^access_\w+$/', $accessToken)) { - throw new ApiException("Invalid OAuth access token: '{$accessToken}'. An access token must start with 'access_'."); - } - - $this->apiKey = $accessToken; - $this->oauthAccess = true; - - return $this; - } - - /** - * Returns null if no API key has been set yet. - * - * @return bool|null - */ - public function usesOAuth() - { - return $this->oauthAccess; - } - - /** - * @param string $versionString - * - * @return MollieApiClient - */ - public function addVersionString($versionString) - { - $this->versionStrings[] = str_replace([" ", "\t", "\n", "\r"], '-', $versionString); - - return $this; - } - - /** - * Enable debugging mode. If debugging mode is enabled, the attempted request will be included in the ApiException. - * By default, debugging is disabled to prevent leaking sensitive request data into exception logs. - * - * @throws \Mollie\Api\Exceptions\HttpAdapterDoesNotSupportDebuggingException - */ - public function enableDebugging() - { - if ( - ! method_exists($this->httpClient, 'supportsDebugging') - || ! $this->httpClient->supportsDebugging() - ) { - throw new HttpAdapterDoesNotSupportDebuggingException( - "Debugging is not supported by " . get_class($this->httpClient) . "." - ); - } + public function __construct( + $client = null, + ?MollieHttpAdapterPickerContract $adapterPicker = null, + ?IdempotencyKeyGeneratorContract $idempotencyKeyGenerator = null + ) { + $adapterPicker = $adapterPicker ?: new MollieHttpAdapterPicker; + $this->httpClient = $adapterPicker->pickHttpAdapter($client); - $this->httpClient->enableDebugging(); - } + CompatibilityChecker::make()->checkCompatibility(); - /** - * Disable debugging mode. If debugging mode is enabled, the attempted request will be included in the ApiException. - * By default, debugging is disabled to prevent leaking sensitive request data into exception logs. - * - * @throws \Mollie\Api\Exceptions\HttpAdapterDoesNotSupportDebuggingException - */ - public function disableDebugging() - { - if ( - ! method_exists($this->httpClient, 'supportsDebugging') - || ! $this->httpClient->supportsDebugging() - ) { - throw new HttpAdapterDoesNotSupportDebuggingException( - "Debugging is not supported by " . get_class($this->httpClient) . "." - ); - } + $this->idempotencyKeyGenerator = $idempotencyKeyGenerator ?? new DefaultIdempotencyKeyGenerator; - $this->httpClient->disableDebugging(); + $this->initializeTraits(); } - /** - * Set the idempotency key used on the next request. The idempotency key is a unique string ensuring a request to a - * mutating Mollie endpoint is processed only once. The idempotency key resets to null after each request. Using - * the setIdempotencyKey method supersedes the IdempotencyKeyGenerator. - * - * @param $key - * @return $this - */ - public function setIdempotencyKey($key) + protected function defaultHeaders(): array { - $this->idempotencyKey = $key; - - return $this; - } - - /** - * Retrieve the idempotency key. The idempotency key is a unique string ensuring a request to a - * mutating Mollie endpoint is processed only once. Note that the idempotency key gets reset to null after each - * request. - * - * @return string|null - */ - public function getIdempotencyKey() - { - return $this->idempotencyKey; - } - - /** - * Reset the idempotency key. Note that the idempotency key automatically resets to null after each request. - * @return $this - */ - public function resetIdempotencyKey() - { - $this->idempotencyKey = null; - - return $this; + return [ + 'X-Mollie-Client-Info' => php_uname(), + 'Accept' => 'application/json', + ]; } - /** - * @param \Mollie\Api\Idempotency\IdempotencyKeyGeneratorContract $generator - * @return \Mollie\Api\MollieApiClient - */ - public function setIdempotencyKeyGenerator($generator) + public function getHttpClient(): HttpAdapterContract { - $this->idempotencyKeyGenerator = $generator; - - return $this; + return $this->httpClient; } - /** - * @return \Mollie\Api\MollieApiClient - */ - public function clearIdempotencyKeyGenerator() + public function resolveBaseUrl(): string { - $this->idempotencyKeyGenerator = null; - - return $this; + return Url::join($this->apiEndpoint, self::API_VERSION); } - /** - * Perform a http call. This method is used by the resource specific classes. Please use the $payments property to - * perform operations on payments. - * - * @param string $httpMethod - * @param string $apiMethod - * @param string|null $httpBody - * - * @return \stdClass - * @throws ApiException - * - * @codeCoverageIgnore - */ - public function performHttpCall($httpMethod, $apiMethod, $httpBody = null) + public static function fake(array $expectedResponses = []): MockMollieClient { - $url = $this->apiEndpoint . "/" . self::API_VERSION . "/" . $apiMethod; - - return $this->performHttpCallToFullUrl($httpMethod, $url, $httpBody); + return new MockMollieClient($expectedResponses); } - /** - * Perform a http call to a full url. This method is used by the resource specific classes. - * - * @see $payments - * @see $isuers - * - * @param string $httpMethod - * @param string $url - * @param string|null $httpBody - * - * @return \stdClass|null - * @throws ApiException - * - * @codeCoverageIgnore - */ - public function performHttpCallToFullUrl($httpMethod, $url, $httpBody = null) + public function __serialize(): array { - if (empty($this->apiKey)) { - throw new ApiException("You have not set an API key or OAuth access token. Please use setApiKey() to set the API key."); - } - - $userAgent = implode(' ', $this->versionStrings); - - if ($this->usesOAuth()) { - $userAgent .= " OAuth/2.0"; - } - - $headers = [ - 'Accept' => "application/json", - 'Authorization' => "Bearer {$this->apiKey}", - 'User-Agent' => $userAgent, + return [ + 'apiEndpoint' => $this->apiEndpoint, + 'httpClient' => $this->httpClient, + 'idempotencyKeyGenerator' => $this->idempotencyKeyGenerator, + 'testmode' => $this->testmode, + 'versionStrings' => $this->versionStrings, ]; - - if ($httpBody !== null) { - $headers['Content-Type'] = "application/json"; - } - - if (function_exists("php_uname")) { - $headers['X-Mollie-Client-Info'] = php_uname(); - } - - $headers = $this->applyIdempotencyKey($headers, $httpMethod); - - $response = $this->httpClient->send($httpMethod, $url, $headers, $httpBody); - - $this->resetIdempotencyKey(); - - return $response; } - /** - * Conditionally apply the idempotency key to the request headers - * - * @param array $headers - * @param string $httpMethod - * @return array - */ - private function applyIdempotencyKey(array $headers, string $httpMethod) - { - if (! in_array($httpMethod, [self::HTTP_POST, self::HTTP_PATCH, self::HTTP_DELETE])) { - unset($headers['Idempotency-Key']); - - return $headers; - } - - if ($this->idempotencyKey) { - $headers['Idempotency-Key'] = $this->idempotencyKey; - - return $headers; - } - - if ($this->idempotencyKeyGenerator) { - $headers['Idempotency-Key'] = $this->idempotencyKeyGenerator->generate(); - - return $headers; - } - - unset($headers['Idempotency-Key']); - - return $headers; - } - - /** - * Serialization can be used for caching. Of course doing so can be dangerous but some like to live dangerously. - * - * \serialize() should be called on the collections or object you want to cache. - * - * We don't need any property that can be set by the constructor, only properties that are set by setters. - * - * Note that the API key is not serialized, so you need to set the key again after unserializing if you want to do - * more API calls. - * - * @deprecated - * @return string[] - */ - public function __sleep() - { - return ["apiEndpoint"]; - } - - /** - * When unserializing a collection or a resource, this class should restore itself. - * - * Note that if you have set an HttpAdapter, this adapter is lost on wakeup and reset to the default one. - * - * @throws IncompatiblePlatform If suddenly unserialized on an incompatible platform. - */ - public function __wakeup() + public function __unserialize(array $data): void { - $this->__construct(); + $this->apiEndpoint = $data['apiEndpoint']; + $this->httpClient = $data['httpClient']; + $this->idempotencyKeyGenerator = $data['idempotencyKeyGenerator']; + $this->testmode = $data['testmode']; + $this->versionStrings = $data['versionStrings']; } } diff --git a/src/Repositories/ArrayStore.php b/src/Repositories/ArrayStore.php new file mode 100644 index 000000000..6edbfafe1 --- /dev/null +++ b/src/Repositories/ArrayStore.php @@ -0,0 +1,68 @@ +store = $data; + } + + public function set(array $data): self + { + $this->store = $data; + + return $this; + } + + /** + * @param mixed $default + * @return mixed + */ + public function get(string $key, $default = null) + { + return Arr::get($this->store, $key, $default); + } + + public function add(string $key, $value): self + { + $this->store[$key] = $value; + + return $this; + } + + public function has(string $key): bool + { + return Arr::has($this->store, $key); + } + + public function merge(array ...$data): self + { + $this->store = array_merge($this->store, ...$data); + + return $this; + } + + public function remove(string $key): self + { + Arr::forget($this->store, $key); + + return $this; + } + + public function all(): array + { + return Arr::resolve($this->store); + } + + public function isEmpty(): bool + { + return empty($this->store); + } +} diff --git a/src/Repositories/JsonPayloadRepository.php b/src/Repositories/JsonPayloadRepository.php new file mode 100644 index 000000000..739d3a1d2 --- /dev/null +++ b/src/Repositories/JsonPayloadRepository.php @@ -0,0 +1,82 @@ +set($data); + } + + /** + * @param mixed $value + */ + public function set($value): self + { + $this->store = $value; + + return $this; + } + + public function all(): array + { + return Arr::resolve($this->store); + } + + public function add(string $key, $value): self + { + $this->store[$key] = $value; + + return $this; + } + + /** + * @return mixed + */ + public function get(string $key, $default = null) + { + return $this->store[$key] ?? $default; + } + + public function merge(array ...$arrays): self + { + $this->store = array_merge($this->store, ...$arrays); + + return $this; + } + + public function remove(string $key): self + { + unset($this->store[$key]); + + return $this; + } + + public function isEmpty(): bool + { + return empty($this->store); + } + + public function isNotEmpty(): bool + { + return ! $this->isEmpty(); + } + + public function __toString(): string + { + return @json_encode($this->store); + } + + public function toStream(StreamFactoryInterface $streamFactory): StreamInterface + { + return $streamFactory->createStream((string) $this); + } +} diff --git a/src/Resources/AnyResource.php b/src/Resources/AnyResource.php new file mode 100644 index 000000000..adaca3035 --- /dev/null +++ b/src/Resources/AnyResource.php @@ -0,0 +1,30 @@ +attributes, $name); + } + + /** + * @param array|stdClass $attributes + */ + public function fill($attributes): void + { + $this->attributes = $attributes instanceof stdClass ? (array) $attributes : $attributes; + } +} diff --git a/src/Resources/Balance.php b/src/Resources/Balance.php index c84ad5678..f011ff576 100644 --- a/src/Resources/Balance.php +++ b/src/Resources/Balance.php @@ -2,8 +2,18 @@ namespace Mollie\Api\Resources; +use Mollie\Api\Traits\HasMode; + +/** + * @property \Mollie\Api\MollieApiClient $connector + */ class Balance extends BaseResource { + use HasMode; + + /** + * Resource id prefix. Used to validate resource id's. + */ /** * Indicates this is a balance resource. The value will always be "balance" here. * @@ -23,6 +33,7 @@ class Balance extends BaseResource * The identifier uniquely referring this balance. Mollie assigns this identifier at balance creation. * * @example bal_gVMhHKqSSRYJyPsuoPABC + * * @var string */ public $id; @@ -31,6 +42,7 @@ class Balance extends BaseResource * UTC datetime the balance was created in ISO-8601 format. * * @example "2021-12-25T10:30:54+00:00" + * * @var string */ public $createdAt; @@ -67,6 +79,7 @@ class Balance extends BaseResource /** * The total amount that is in the process of being transferred from your balance to your verified bank account. + * * @var \stdClass */ public $outgoingAmount; diff --git a/src/Resources/BalanceCollection.php b/src/Resources/BalanceCollection.php index 04f07cb83..de4da2460 100644 --- a/src/Resources/BalanceCollection.php +++ b/src/Resources/BalanceCollection.php @@ -5,18 +5,12 @@ class BalanceCollection extends CursorCollection { /** - * @return string + * The name of the collection resource in Mollie's API. */ - public function getCollectionResourceName() - { - return "balances"; - } + public static string $collectionName = 'balances'; /** - * @return BaseResource + * Resource class name. */ - protected function createResourceObject() - { - return new Balance($this->client); - } + public static string $resource = Balance::class; } diff --git a/src/Resources/BalanceReport.php b/src/Resources/BalanceReport.php index 96479f742..505c2f699 100644 --- a/src/Resources/BalanceReport.php +++ b/src/Resources/BalanceReport.php @@ -4,6 +4,9 @@ namespace Mollie\Api\Resources; +/** + * @property \Mollie\Api\MollieApiClient $connector + */ class BalanceReport extends BaseResource { /** @@ -17,6 +20,7 @@ class BalanceReport extends BaseResource * The ID of the balance this report was generated for. * * @example bal_gVMhHKqSSRYJyPsuoPNFH + * * @var string */ public $balanceId; @@ -27,23 +31,25 @@ class BalanceReport extends BaseResource * * * @example Europe/Amsterdam + * * @var string */ public $timeZone; /** - * The start date of the report, in YYYY-MM-DD format. The "from" date is ‘inclusive’, and in Central European Time. + * The start date of the report, in YYYY-MM-DD format. The "from" date is 'inclusive', and in Central European Time. * This means a report with for example "from: 2020-01-01" will include movements of "2020-01-01 0:00:00 CET" and * onwards. * * * @example 2020-01-01 + * * @var string */ public $from; /** - * The end date of the report, in YYYY-MM-DD format. The "until" date is ‘exclusive’, and in Central European Time. + * The end date of the report, in YYYY-MM-DD format. The "until" date is 'exclusive', and in Central European Time. * This means a report with for example "until: 2020-02-01" will include movements up * until "2020-01-31 23:59:59 CET". * diff --git a/src/Resources/BalanceTransaction.php b/src/Resources/BalanceTransaction.php index 795d40062..288ffdd81 100644 --- a/src/Resources/BalanceTransaction.php +++ b/src/Resources/BalanceTransaction.php @@ -4,8 +4,15 @@ namespace Mollie\Api\Resources; +use Mollie\Api\Traits\HasMode; + +/** + * @property \Mollie\Api\MollieApiClient $connector + */ class BalanceTransaction extends BaseResource { + use HasMode; + /** * Indicates this is a balance transaction resource. The value will always be "balance_transaction" here. * @@ -25,6 +32,7 @@ class BalanceTransaction extends BaseResource * The identifier uniquely referring this balance transaction. Mollie assigns this identifier at creation. * * @example baltr_QM24QwzUWR4ev4Xfgyt29d + * * @var string */ public $id; @@ -40,6 +48,7 @@ class BalanceTransaction extends BaseResource * UTC datetime the balance transaction was created in ISO-8601 format. * * @example "2021-12-25T10:30:54+00:00" + * * @var string */ public $createdAt; @@ -49,6 +58,7 @@ class BalanceTransaction extends BaseResource * for example when it concerns a refund, the amount will be negative. * * @example {"currency":"EUR", "value":"100.00"} + * * @var \stdClass */ public $resultAmount; diff --git a/src/Resources/BalanceTransactionCollection.php b/src/Resources/BalanceTransactionCollection.php index 303de05c2..ceb6739a3 100644 --- a/src/Resources/BalanceTransactionCollection.php +++ b/src/Resources/BalanceTransactionCollection.php @@ -7,18 +7,12 @@ class BalanceTransactionCollection extends CursorCollection { /** - * @inheritDoc + * The name of the collection resource in Mollie's API. */ - public function getCollectionResourceName() - { - return "balance_transactions"; - } + public static string $collectionName = 'balance_transactions'; /** - * @inheritDoc + * Resource class name. */ - protected function createResourceObject() - { - return new BalanceTransaction($this->client); - } + public static string $resource = BalanceTransaction::class; } diff --git a/src/Resources/BaseCollection.php b/src/Resources/BaseCollection.php index fd43b87a6..75ba34e1d 100644 --- a/src/Resources/BaseCollection.php +++ b/src/Resources/BaseCollection.php @@ -2,33 +2,86 @@ namespace Mollie\Api\Resources; -abstract class BaseCollection extends \ArrayObject +use ArrayObject; +use Mollie\Api\Contracts\Connector; +use Mollie\Api\Contracts\IsResponseAware; +use Mollie\Api\Traits\HasResponse; +use Mollie\Api\Utils\Arr; + +abstract class BaseCollection extends ArrayObject implements IsResponseAware { - /** - * Total number of retrieved objects. - * - * @var int - */ - public $count; + use HasResponse; + + protected Connector $connector; /** - * @var \stdClass|null + * The name of the collection resource in Mollie's API. */ - public $_links; + public static string $collectionName = ''; + + public ?\stdClass $_links = null; /** - * @param int $count - * @param \stdClass|null $_links + * @param array|object $items */ - public function __construct($count, $_links) + public function __construct(Connector $connector, $items = [], ?\stdClass $_links = null) { - $this->count = $count; + parent::__construct($items); + $this->_links = $_links; - parent::__construct(); + $this->connector = $connector; + } + + public function contains(callable $callback): bool + { + foreach ($this as $item) { + if ($callback($item)) { + return true; + } + } + + return false; + } + + public function filter(callable $callback) + { + $filteredItems = array_filter($this->getArrayCopy(), $callback); + + /** @phpstan-ignore-next-line */ + return (new static($this->connector, $filteredItems, $this->_links))->setResponse($this->response); + } + + public function first() + { + return array_values($this->getArrayCopy())[0]; } /** - * @return string|null + * @param string|callable $key + * @param mixed $value + * @return mixed */ - abstract public function getCollectionResourceName(); + public function firstWhere($key, $value = true) + { + if (! is_string($key) && is_callable($key)) { + return $this->filter($key)->first(); + } + + return $this->filter(function ($item) use ($key, $value) { + if (is_array($item)) { + return Arr::get($item, $key) === $value; + } + + return $item->{$key} === $value; + })->first(); + } + + public static function getCollectionResourceName(): string + { + if (empty(static::$collectionName)) { + throw new \RuntimeException('Collection name not set'); + } + + return static::$collectionName; + } } diff --git a/src/Resources/BaseResource.php b/src/Resources/BaseResource.php index d5762ccfd..ccf46f598 100644 --- a/src/Resources/BaseResource.php +++ b/src/Resources/BaseResource.php @@ -2,30 +2,26 @@ namespace Mollie\Api\Resources; -use Mollie\Api\MollieApiClient; +use Mollie\Api\Contracts\Connector; +use Mollie\Api\Contracts\IsResponseAware; +use Mollie\Api\Traits\HasResponse; #[\AllowDynamicProperties] -abstract class BaseResource +abstract class BaseResource implements IsResponseAware { - /** - * @var MollieApiClient - */ - protected $client; + use HasResponse; + + protected Connector $connector; /** * Indicates the type of resource. * - * @example payment - * * @var string */ public $resource; - /** - * @param MollieApiClient $client - */ - public function __construct(MollieApiClient $client) + public function __construct(Connector $connector) { - $this->client = $client; + $this->connector = $connector; } } diff --git a/src/Resources/Capture.php b/src/Resources/Capture.php index 89cd86209..a3a65b1b5 100644 --- a/src/Resources/Capture.php +++ b/src/Resources/Capture.php @@ -2,8 +2,15 @@ namespace Mollie\Api\Resources; +use Mollie\Api\Traits\HasMode; + +/** + * @property \Mollie\Api\MollieApiClient $connector + */ class Capture extends BaseResource { + use HasMode; + /** * Always 'capture' for this object * @@ -13,6 +20,7 @@ class Capture extends BaseResource /** * Id of the capture + * * @var string */ public $id; @@ -24,6 +32,13 @@ class Capture extends BaseResource */ public $mode; + /** + * Description of the capture. + * + * @var string + */ + public $description; + /** * Status of the capture. * diff --git a/src/Resources/CaptureCollection.php b/src/Resources/CaptureCollection.php index 38a5d7d81..c943747b5 100644 --- a/src/Resources/CaptureCollection.php +++ b/src/Resources/CaptureCollection.php @@ -5,18 +5,12 @@ class CaptureCollection extends CursorCollection { /** - * @return string + * The name of the collection resource in Mollie's API. */ - public function getCollectionResourceName() - { - return "captures"; - } + public static string $collectionName = 'captures'; /** - * @return BaseResource + * Resource class name. */ - protected function createResourceObject() - { - return new Capture($this->client); - } + public static string $resource = Capture::class; } diff --git a/src/Resources/Chargeback.php b/src/Resources/Chargeback.php index c54bf7ad2..7ec1cb979 100644 --- a/src/Resources/Chargeback.php +++ b/src/Resources/Chargeback.php @@ -2,6 +2,9 @@ namespace Mollie\Api\Resources; +/** + * @property \Mollie\Api\MollieApiClient $connector + */ class Chargeback extends BaseResource { /** @@ -29,6 +32,7 @@ class Chargeback extends BaseResource * UTC datetime the payment was created in ISO-8601 format. * * @example "2013-12-25T10:30:54+00:00" + * * @var string|null */ public $createdAt; @@ -65,6 +69,7 @@ class Chargeback extends BaseResource * UTC datetime the date and time the chargeback was reversed in ISO-8601 format. * * @example "2013-12-25T10:30:54+00:00" + * * @var string|null */ public $reversedAt; diff --git a/src/Resources/ChargebackCollection.php b/src/Resources/ChargebackCollection.php index e8a8a2803..225fee3ac 100644 --- a/src/Resources/ChargebackCollection.php +++ b/src/Resources/ChargebackCollection.php @@ -5,18 +5,12 @@ class ChargebackCollection extends CursorCollection { /** - * @return string + * The name of the collection resource in Mollie's API. */ - public function getCollectionResourceName() - { - return "chargebacks"; - } + public static string $collectionName = 'chargebacks'; /** - * @return BaseResource + * Resource class name. */ - protected function createResourceObject() - { - return new Chargeback($this->client); - } + public static string $resource = Chargeback::class; } diff --git a/src/Resources/Client.php b/src/Resources/Client.php index ed226421b..958a03d3b 100644 --- a/src/Resources/Client.php +++ b/src/Resources/Client.php @@ -2,7 +2,12 @@ namespace Mollie\Api\Resources; -class Client extends BaseResource +use Mollie\Api\Contracts\EmbeddedResourcesContract; + +/** + * @property \Mollie\Api\MollieApiClient $connector + */ +class Client extends BaseResource implements EmbeddedResourcesContract { /** * The unique identifier of the client, which corresponds to the ID of the organization @@ -15,6 +20,7 @@ class Client extends BaseResource * UTC datetime the order was created in ISO-8601 format. * * @example "2018-03-21T13:13:37+00:00" + * * @var string|null */ public $organizationCreatedAt; @@ -33,4 +39,12 @@ class Client extends BaseResource * @var \stdClass|null */ public $commission; + + public function getEmbeddedResourcesMap(): array + { + return [ + 'organization' => Organization::class, + 'onboarding' => Onboarding::class, + ]; + } } diff --git a/src/Resources/ClientCollection.php b/src/Resources/ClientCollection.php index 707a16762..43827169e 100644 --- a/src/Resources/ClientCollection.php +++ b/src/Resources/ClientCollection.php @@ -5,18 +5,12 @@ class ClientCollection extends CursorCollection { /** - * @return string + * The name of the collection resource in Mollie's API. */ - public function getCollectionResourceName() - { - return "clients"; - } + public static string $collectionName = 'clients'; /** - * @return BaseResource + * Resource class name. */ - protected function createResourceObject() - { - return new Client($this->client); - } + public static string $resource = Client::class; } diff --git a/src/Resources/ClientLink.php b/src/Resources/ClientLink.php index 36ac0b7a3..a74f47c59 100644 --- a/src/Resources/ClientLink.php +++ b/src/Resources/ClientLink.php @@ -4,6 +4,9 @@ use Mollie\Api\Types\ApprovalPrompt; +/** + * @property \Mollie\Api\MollieApiClient $connector + */ class ClientLink extends BaseResource { /** @@ -15,6 +18,7 @@ class ClientLink extends BaseResource * Id of the client link. * * @example csr_vZCnNQsV2UtfXxYifWKWH + * * @var string */ public $id; diff --git a/src/Resources/CurrentProfile.php b/src/Resources/CurrentProfile.php index b351fa92e..de28f45c3 100644 --- a/src/Resources/CurrentProfile.php +++ b/src/Resources/CurrentProfile.php @@ -9,26 +9,22 @@ class CurrentProfile extends Profile /** * Enable a payment method for this profile. * - * @param string $methodId - * @param array $data - * @return Method + * * @throws ApiException */ - public function enableMethod($methodId, array $data = []) + public function enableMethod(string $methodId): Method { - return $this->client->profileMethods->createForCurrentProfile($methodId, $data); + return $this->connector->profileMethods->createForCurrentProfile($methodId); } /** * Disable a payment method for this profile. * - * @param string $methodId - * @param array $data - * @return Method + * * @throws ApiException */ - public function disableMethod($methodId, array $data = []) + public function disableMethod(string $methodId): void { - return $this->client->profileMethods->deleteForCurrentProfile($methodId, $data); + $this->connector->profileMethods->deleteForCurrentProfile($methodId); } } diff --git a/src/Resources/CursorCollection.php b/src/Resources/CursorCollection.php index 0f83c7e56..80f3398aa 100644 --- a/src/Resources/CursorCollection.php +++ b/src/Resources/CursorCollection.php @@ -3,110 +3,77 @@ namespace Mollie\Api\Resources; use Generator; -use Mollie\Api\MollieApiClient; +use Mollie\Api\Http\Requests\DynamicGetRequest; +use Mollie\Api\Http\Response; -abstract class CursorCollection extends BaseCollection +abstract class CursorCollection extends ResourceCollection { - /** - * @var MollieApiClient - */ - protected $client; - - /** - * @param MollieApiClient $client - * @param int $count - * @param \stdClass|null $_links - */ - final public function __construct(MollieApiClient $client, $count, $_links) - { - parent::__construct($count, $_links); - - $this->client = $client; - } - - /** - * @return BaseResource - */ - abstract protected function createResourceObject(); - /** * Return the next set of resources when available * - * @return CursorCollection|null + * @return null|CursorCollection|Response + * * @throws \Mollie\Api\Exceptions\ApiException */ - final public function next() + public function next() { if (! $this->hasNext()) { return null; } - $result = $this->client->performHttpCallToFullUrl(MollieApiClient::HTTP_GET, $this->_links->next->href); - - $collection = new static($this->client, $result->count, $result->_links); - - foreach ($result->_embedded->{$collection->getCollectionResourceName()} as $dataResult) { - $collection[] = ResourceFactory::createFromApiResult($dataResult, $this->createResourceObject()); - } - - return $collection; + return $this->fetchCollection($this->_links->next->href); } /** * Return the previous set of resources when available * - * @return CursorCollection|null + * @return null|CursorCollection|Response + * * @throws \Mollie\Api\Exceptions\ApiException */ - final public function previous() + public function previous() { if (! $this->hasPrevious()) { return null; } - $result = $this->client->performHttpCallToFullUrl(MollieApiClient::HTTP_GET, $this->_links->previous->href); - - $collection = new static($this->client, $result->count, $result->_links); - - foreach ($result->_embedded->{$collection->getCollectionResourceName()} as $dataResult) { - $collection[] = ResourceFactory::createFromApiResult($dataResult, $this->createResourceObject()); - } + return $this->fetchCollection($this->_links->previous->href); + } - return $collection; + /** + * @return CursorCollection|Response + */ + private function fetchCollection(string $url) + { + return $this + ->connector + ->send((new DynamicGetRequest($url))->setHydratableResource(static::class)); } /** * Determine whether the collection has a next page available. - * - * @return bool */ - public function hasNext() + public function hasNext(): bool { return isset($this->_links->next->href); } /** * Determine whether the collection has a previous page available. - * - * @return bool */ - public function hasPrevious() + public function hasPrevious(): bool { return isset($this->_links->previous->href); } /** * Iterate over a CursorCollection and yield its elements. - * - * @param bool $iterateBackwards - * - * @return LazyCollection */ public function getAutoIterator(bool $iterateBackwards = false): LazyCollection { $page = $this; - return new LazyCollection(function () use ($page, $iterateBackwards): Generator { + return (new LazyCollection(function () use ($page, $iterateBackwards): Generator { while (true) { foreach ($page as $item) { yield $item; @@ -120,6 +87,6 @@ public function getAutoIterator(bool $iterateBackwards = false): LazyCollection ? $page->previous() : $page->next(); } - }); + }))->setResponse($this->response); } } diff --git a/src/Resources/Customer.php b/src/Resources/Customer.php index 86238357b..58f99348e 100644 --- a/src/Resources/Customer.php +++ b/src/Resources/Customer.php @@ -3,10 +3,14 @@ namespace Mollie\Api\Resources; use Mollie\Api\Exceptions\ApiException; +use Mollie\Api\Traits\HasMode; +/** + * @property \Mollie\Api\MollieApiClient $connector + */ class Customer extends BaseResource { - use HasPresetOptions; + use HasMode; /** * Id of the customer. @@ -58,136 +62,133 @@ class Customer extends BaseResource public $_links; /** - * @return \Mollie\Api\Resources\Customer - * @throws \Mollie\Api\Exceptions\ApiException + * @throws ApiException */ - public function update() + public function update(): ?Customer { $body = [ - "name" => $this->name, - "email" => $this->email, - "locale" => $this->locale, - "metadata" => $this->metadata, + 'name' => $this->name, + 'email' => $this->email, + 'locale' => $this->locale, + 'metadata' => $this->metadata, ]; - $result = $this->client->customers->update($this->id, $body); - - return ResourceFactory::createFromApiResult($result, new Customer($this->client)); + /** @var null|Customer */ + return $this->connector->customers->update($this->id, $body); } /** - * @param array $options - * @param array $filters - * * @return Payment + * * @throws ApiException */ public function createPayment(array $options = [], array $filters = []) { - return $this->client->customerPayments->createFor($this, $this->withPresetOptions($options), $filters); + return $this->connector->customerPayments->createFor( + $this, + $options, + $filters, + $this->isInTestmode() + ); } /** * Get all payments for this customer * * @return PaymentCollection + * * @throws ApiException */ public function payments() { - return $this->client->customerPayments->listFor($this, null, null, $this->getPresetOptions()); + return $this->connector->customerPayments->pageFor($this, null, null, $this->withMode()); } /** - * @param array $options - * @param array $filters - * * @return Subscription + * * @throws ApiException */ public function createSubscription(array $options = [], array $filters = []) { - return $this->client->subscriptions->createFor($this, $this->withPresetOptions($options), $filters); + return $this->connector->subscriptions->createFor($this, $options, $this->isInTestmode()); } /** - * @param string $subscriptionId - * @param array $parameters - * + * @param string $subscriptionId * @return Subscription + * * @throws ApiException */ - public function getSubscription($subscriptionId, array $parameters = []) + public function getSubscription($subscriptionId) { - return $this->client->subscriptions->getFor($this, $subscriptionId, $this->withPresetOptions($parameters)); + return $this->connector->subscriptions->getFor($this, $subscriptionId, $this->isInTestmode()); } /** - * @param string $subscriptionId - * + * @param string $subscriptionId * @return \Mollie\Api\Resources\Subscription + * * @throws ApiException */ public function cancelSubscription($subscriptionId) { - return $this->client->subscriptions->cancelFor($this, $subscriptionId, $this->getPresetOptions()); + return $this->connector->subscriptions->cancelFor($this, $subscriptionId, $this->isInTestmode()); } /** * Get all subscriptions for this customer * * @return SubscriptionCollection + * * @throws ApiException */ public function subscriptions() { - return $this->client->subscriptions->listFor($this, null, null, $this->getPresetOptions()); + return $this->connector->subscriptions->pageFor($this, null, null, $this->withMode()); } /** - * @param array $options - * @param array $filters - * * @return Mandate + * * @throws ApiException */ - public function createMandate(array $options = [], array $filters = []) + public function createMandate(array $options = []) { - return $this->client->mandates->createFor($this, $this->withPresetOptions($options), $filters); + return $this->connector->mandates->createFor($this, $options, $this->isInTestmode()); } /** - * @param string $mandateId - * @param array $parameters - * + * @param string $mandateId * @return Mandate + * * @throws ApiException */ public function getMandate($mandateId, array $parameters = []) { - return $this->client->mandates->getFor($this, $mandateId, $parameters); + return $this->connector->mandates->getFor($this, $mandateId, $this->withMode($parameters)); } /** - * @param string $mandateId + * @param string $mandateId * - * @return null * @throws ApiException */ - public function revokeMandate($mandateId) + public function revokeMandate($mandateId): void { - return $this->client->mandates->revokeFor($this, $mandateId, $this->getPresetOptions()); + $this->connector->mandates->revokeFor($this, $mandateId, $this->withMode()); } /** * Get all mandates for this customer * * @return MandateCollection + * * @throws ApiException */ public function mandates() { - return $this->client->mandates->listFor($this, null, null, $this->getPresetOptions()); + return $this->connector->mandates->pageFor($this, null, null, $this->withMode()); } /** @@ -197,30 +198,16 @@ public function mandates() */ public function hasValidMandate() { - $mandates = $this->mandates(); - foreach ($mandates as $mandate) { - if ($mandate->isValid()) { - return true; - } - } - - return false; + return $this->mandates() + ->contains(fn (Mandate $mandate) => $mandate->isValid()); } /** * Helper function to check for specific payment method mandate with status valid - * - * @return bool */ - public function hasValidMandateForMethod($method) + public function hasValidMandateForMethod($method): bool { - $mandates = $this->mandates(); - foreach ($mandates as $mandate) { - if ($mandate->method === $method && $mandate->isValid()) { - return true; - } - } - - return false; + return $this->mandates() + ->contains(fn (Mandate $mandate) => $mandate->isValid() && $mandate->method === $method); } } diff --git a/src/Resources/CustomerCollection.php b/src/Resources/CustomerCollection.php index deece5770..31a204442 100644 --- a/src/Resources/CustomerCollection.php +++ b/src/Resources/CustomerCollection.php @@ -5,18 +5,12 @@ class CustomerCollection extends CursorCollection { /** - * @return string + * The name of the collection resource in Mollie's API. */ - public function getCollectionResourceName() - { - return "customers"; - } + public static string $collectionName = 'customers'; /** - * @return BaseResource + * Resource class name. */ - protected function createResourceObject() - { - return new Customer($this->client); - } + public static string $resource = Customer::class; } diff --git a/src/Resources/HasPresetOptions.php b/src/Resources/HasPresetOptions.php deleted file mode 100644 index 8a0e24e21..000000000 --- a/src/Resources/HasPresetOptions.php +++ /dev/null @@ -1,38 +0,0 @@ -client->usesOAuth()) { - $options["testmode"] = $this->mode === "test" ? true : false; - } - - return $options; - } - - /** - * Apply the preset options. - * - * @param array $options - * @return array - */ - protected function withPresetOptions(array $options) - { - return array_merge($this->getPresetOptions(), $options); - } -} diff --git a/src/Resources/Invoice.php b/src/Resources/Invoice.php index 70b86e775..2a9a26922 100644 --- a/src/Resources/Invoice.php +++ b/src/Resources/Invoice.php @@ -4,6 +4,9 @@ use Mollie\Api\Types\InvoiceStatus; +/** + * @property \Mollie\Api\MollieApiClient $connector + */ class Invoice extends BaseResource { /** @@ -72,6 +75,7 @@ class Invoice extends BaseResource * Array containing the invoice lines. * * @see https://docs.mollie.com/reference/v2/invoices-api/get-invoice + * * @var array */ public $lines; @@ -83,27 +87,18 @@ class Invoice extends BaseResource */ public $_links; - /** - * @return bool - */ - public function isPaid() + public function isPaid(): bool { - return $this->status == InvoiceStatus::STATUS_PAID; + return $this->status == InvoiceStatus::PAID; } - /** - * @return bool - */ - public function isOpen() + public function isOpen(): bool { - return $this->status == InvoiceStatus::STATUS_OPEN; + return $this->status == InvoiceStatus::OPEN; } - /** - * @return bool - */ - public function isOverdue() + public function isOverdue(): bool { - return $this->status == InvoiceStatus::STATUS_OVERDUE; + return $this->status == InvoiceStatus::OVERDUE; } } diff --git a/src/Resources/InvoiceCollection.php b/src/Resources/InvoiceCollection.php index 3278dd082..01dbbf29d 100644 --- a/src/Resources/InvoiceCollection.php +++ b/src/Resources/InvoiceCollection.php @@ -5,18 +5,12 @@ class InvoiceCollection extends CursorCollection { /** - * @return string + * The name of the collection resource in Mollie's API. */ - public function getCollectionResourceName() - { - return "invoices"; - } + public static string $collectionName = 'invoices'; /** - * @return BaseResource + * Resource class name. */ - protected function createResourceObject() - { - return new Invoice($this->client); - } + public static string $resource = Invoice::class; } diff --git a/src/Resources/Issuer.php b/src/Resources/Issuer.php index 357238c81..a3d77c731 100644 --- a/src/Resources/Issuer.php +++ b/src/Resources/Issuer.php @@ -2,6 +2,9 @@ namespace Mollie\Api\Resources; +/** + * @property \Mollie\Api\MollieApiClient $connector + */ class Issuer extends BaseResource { /** @@ -22,6 +25,7 @@ class Issuer extends BaseResource * The payment method this issuer belongs to. * * @see Mollie_API_Object_Method + * * @var string */ public $method; diff --git a/src/Resources/IssuerCollection.php b/src/Resources/IssuerCollection.php index ec4b7b794..b04a66758 100644 --- a/src/Resources/IssuerCollection.php +++ b/src/Resources/IssuerCollection.php @@ -2,13 +2,4 @@ namespace Mollie\Api\Resources; -class IssuerCollection extends BaseCollection -{ - /** - * @return string|null - */ - public function getCollectionResourceName() - { - return null; - } -} +class IssuerCollection extends BaseCollection {} diff --git a/src/Resources/LazyCollection.php b/src/Resources/LazyCollection.php index 94179a653..a994920d8 100644 --- a/src/Resources/LazyCollection.php +++ b/src/Resources/LazyCollection.php @@ -4,6 +4,8 @@ use Iterator; use IteratorAggregate; +use Mollie\Api\Contracts\IsResponseAware; +use Mollie\Api\Traits\HasResponse; /** * @template TKey of array-key @@ -11,15 +13,17 @@ * * @implements IteratorAggregate */ -class LazyCollection implements IteratorAggregate +class LazyCollection implements IsResponseAware, IteratorAggregate { + use HasResponse; + /** * @var callable */ private $source; /** - * @param callable $source + * @param callable $source */ public function __construct($source) { @@ -28,8 +32,6 @@ public function __construct($source) /** * Get all items in the collection. - * - * @return array */ public function all(): array { @@ -39,7 +41,7 @@ public function all(): array /** * Get an item from the collection by key. * - * @param TKey $key + * @param TKey $key * @return TValue|null */ public function get($key) @@ -56,24 +58,23 @@ public function get($key) /** * Run a filter over each of the items. * - * @param (callable(TValue, TKey): bool) $callback - * @return self + * @param (callable(TValue, TKey): bool) $callback */ public function filter(callable $callback): self { - return new self(function () use ($callback) { + return (new self(function () use ($callback) { foreach ($this as $key => $value) { if ($callback($value, $key)) { yield $key => $value; } } - }); + }))->setResponse($this->response); } /** * Get the first item from the collection passing the given truth test. * - * @param (callable(TValue, TKey): bool)|null $callback + * @param (callable(TValue, TKey): bool)|null $callback * @return TValue|null */ public function first(?callable $callback = null) @@ -102,27 +103,26 @@ public function first(?callable $callback = null) * * @template TMapValue * - * @param callable(TValue, TKey): TMapValue $callback + * @param callable(TValue, TKey): TMapValue $callback * @return static */ public function map(callable $callback): self { - return new self(function () use ($callback) { + return (new self(function () use ($callback) { foreach ($this as $key => $value) { yield $key => $callback($value, $key); } - }); + }))->setResponse($this->response); } /** * Take the first {$limit} items. * - * @param int $limit * @return static */ public function take(int $limit): self { - return new self(function () use ($limit) { + return (new self(function () use ($limit) { $iterator = $this->getIterator(); while ($limit--) { @@ -136,14 +136,13 @@ public function take(int $limit): self $iterator->next(); } } - }); + }))->setResponse($this->response); } /** * Determine if all items pass the given truth test. * - * @param (callable(TValue, TKey): bool) $callback - * @return bool + * @param (callable(TValue, TKey): bool) $callback */ public function every(callable $callback): bool { @@ -160,8 +159,6 @@ public function every(callable $callback): bool /** * Count the number of items in the collection. - * - * @return int */ public function count(): int { @@ -184,7 +181,7 @@ public function getIterator(): Iterator * @template TIteratorKey of array-key * @template TIteratorValue * - * @param IteratorAggregate|(callable(): \Generator) $source + * @param IteratorAggregate|(callable(): \Generator) $source * @return Iterator */ protected function makeIterator($source): Iterator diff --git a/src/Resources/Mandate.php b/src/Resources/Mandate.php index 24e56f684..06bab5762 100644 --- a/src/Resources/Mandate.php +++ b/src/Resources/Mandate.php @@ -2,9 +2,12 @@ namespace Mollie\Api\Resources; -use Mollie\Api\MollieApiClient; +use Mollie\Api\Http\Requests\RevokeMandateRequest; use Mollie\Api\Types\MandateStatus; +/** + * @property \Mollie\Api\MollieApiClient $connector + */ class Mandate extends BaseResource { /** @@ -33,7 +36,7 @@ class Mandate extends BaseResource public $details; /** - * @var string + * @var string|null */ public $customerId; @@ -59,54 +62,36 @@ class Mandate extends BaseResource */ public $_links; - /** - * @return bool - */ - public function isValid() + public function isValid(): bool { - return $this->status === MandateStatus::STATUS_VALID; + return $this->status === MandateStatus::VALID; } - /** - * @return bool - */ - public function isPending() + public function isPending(): bool { - return $this->status === MandateStatus::STATUS_PENDING; + return $this->status === MandateStatus::PENDING; } - /** - * @return bool - */ - public function isInvalid() + public function isInvalid(): bool { - return $this->status === MandateStatus::STATUS_INVALID; + return $this->status === MandateStatus::INVALID; } /** * Revoke the mandate - * - * @return null|\stdClass|\Mollie\Api\Resources\Mandate */ - public function revoke() + public function revoke(): ?Mandate { - if (! isset($this->_links->self->href)) { + if (! isset($this->customerId)) { return $this; } - $body = null; - if ($this->client->usesOAuth()) { - $body = json_encode([ - "testmode" => $this->mode === "test" ? true : false, - ]); - } - - $result = $this->client->performHttpCallToFullUrl( - MollieApiClient::HTTP_DELETE, - $this->_links->self->href, - $body - ); - - return $result; + return $this + ->connector + ->send((new RevokeMandateRequest( + $this->customerId, + $this->id, + ))->test($this->mode === 'test')) + ->toResource(); } } diff --git a/src/Resources/MandateCollection.php b/src/Resources/MandateCollection.php index 23d39d16c..5955bf1e7 100644 --- a/src/Resources/MandateCollection.php +++ b/src/Resources/MandateCollection.php @@ -5,36 +5,20 @@ class MandateCollection extends CursorCollection { /** - * @return string + * The name of the collection resource in Mollie's API. */ - public function getCollectionResourceName() - { - return "mandates"; - } + public static string $collectionName = 'mandates'; /** - * @return BaseResource + * Resource class name. */ - protected function createResourceObject() - { - return new Mandate($this->client); - } + public static string $resource = Mandate::class; /** - * @param string $status - * @return array|\Mollie\Api\Resources\MandateCollection + * @param string $status */ - public function whereStatus($status) + public function whereStatus($status): self { - $collection = new self($this->client, 0, $this->_links); - - foreach ($this as $item) { - if ($item->status === $status) { - $collection[] = $item; - $collection->count++; - } - } - - return $collection; + return $this->filter(fn (Mandate $mandate) => $mandate->status === $status); } } diff --git a/src/Resources/Method.php b/src/Resources/Method.php index fac587437..6805fdaab 100644 --- a/src/Resources/Method.php +++ b/src/Resources/Method.php @@ -2,6 +2,9 @@ namespace Mollie\Api\Resources; +/** + * @property \Mollie\Api\MollieApiClient $connector + */ class Method extends BaseResource { /** @@ -72,28 +75,28 @@ class Method extends BaseResource /** * Get the issuer value objects - * - * @return IssuerCollection */ - public function issuers() + public function issuers(): IssuerCollection { + /** @var IssuerCollection */ return ResourceFactory::createBaseResourceCollection( - $this->client, + $this->connector, Issuer::class, + $this->response, $this->issuers ); } /** * Get the method price value objects. - * - * @return MethodPriceCollection */ - public function pricing() + public function pricing(): MethodPriceCollection { + /** @var MethodPriceCollection */ return ResourceFactory::createBaseResourceCollection( - $this->client, + $this->connector, MethodPrice::class, + $this->response, $this->pricing ); } diff --git a/src/Resources/MethodCollection.php b/src/Resources/MethodCollection.php index a1f204109..32e5dd082 100644 --- a/src/Resources/MethodCollection.php +++ b/src/Resources/MethodCollection.php @@ -2,13 +2,12 @@ namespace Mollie\Api\Resources; -class MethodCollection extends BaseCollection +class MethodCollection extends ResourceCollection { /** - * @return string + * The name of the collection resource in Mollie's API. */ - public function getCollectionResourceName() - { - return "methods"; - } + public static string $collectionName = 'methods'; + + public static string $resource = Method::class; } diff --git a/src/Resources/MethodPrice.php b/src/Resources/MethodPrice.php index 366a2366d..697ee6a6a 100644 --- a/src/Resources/MethodPrice.php +++ b/src/Resources/MethodPrice.php @@ -2,12 +2,16 @@ namespace Mollie\Api\Resources; +/** + * @property \Mollie\Api\MollieApiClient $connector + */ class MethodPrice extends BaseResource { /** * The area or product-type where the pricing is applied for, translated in the optional locale passed. * * @example "The Netherlands" + * * @var string */ public $description; diff --git a/src/Resources/MethodPriceCollection.php b/src/Resources/MethodPriceCollection.php index ca81fc2f3..c34b17fb6 100644 --- a/src/Resources/MethodPriceCollection.php +++ b/src/Resources/MethodPriceCollection.php @@ -2,13 +2,4 @@ namespace Mollie\Api\Resources; -class MethodPriceCollection extends BaseCollection -{ - /** - * @return string|null - */ - public function getCollectionResourceName() - { - return null; - } -} +class MethodPriceCollection extends BaseCollection {} diff --git a/src/Resources/Onboarding.php b/src/Resources/Onboarding.php index a45326c67..4bb819560 100644 --- a/src/Resources/Onboarding.php +++ b/src/Resources/Onboarding.php @@ -4,6 +4,9 @@ use Mollie\Api\Types\OnboardingStatus; +/** + * @property \Mollie\Api\MollieApiClient $connector + */ class Onboarding extends BaseResource { /** @@ -39,26 +42,17 @@ class Onboarding extends BaseResource */ public $_links; - /** - * @return bool - */ - public function needsData() + public function needsData(): bool { return $this->status === OnboardingStatus::NEEDS_DATA; } - /** - * @return bool - */ - public function isInReview() + public function inReview(): bool { return $this->status === OnboardingStatus::IN_REVIEW; } - /** - * @return bool - */ - public function isCompleted() + public function isCompleted(): bool { return $this->status === OnboardingStatus::COMPLETED; } diff --git a/src/Resources/Order.php b/src/Resources/Order.php deleted file mode 100644 index f579c2aae..000000000 --- a/src/Resources/Order.php +++ /dev/null @@ -1,534 +0,0 @@ -status === OrderStatus::STATUS_CREATED; - } - - /** - * Is this order paid for? - * - * @return bool - */ - public function isPaid() - { - return $this->status === OrderStatus::STATUS_PAID; - } - - /** - * Is this order authorized? - * - * @return bool - */ - public function isAuthorized() - { - return $this->status === OrderStatus::STATUS_AUTHORIZED; - } - - /** - * Is this order canceled? - * - * @return bool - */ - public function isCanceled() - { - return $this->status === OrderStatus::STATUS_CANCELED; - } - - /** - * (Deprecated) Is this order refunded? - * @deprecated 2018-11-27 - * - * @return bool - */ - public function isRefunded() - { - return $this->status === OrderStatus::STATUS_REFUNDED; - } - - /** - * Is this order shipping? - * - * @return bool - */ - public function isShipping() - { - return $this->status === OrderStatus::STATUS_SHIPPING; - } - - /** - * Is this order completed? - * - * @return bool - */ - public function isCompleted() - { - return $this->status === OrderStatus::STATUS_COMPLETED; - } - - /** - * Is this order expired? - * - * @return bool - */ - public function isExpired() - { - return $this->status === OrderStatus::STATUS_EXPIRED; - } - - /** - * Is this order completed? - * - * @return bool - */ - public function isPending() - { - return $this->status === OrderStatus::STATUS_PENDING; - } - - /** - * Cancels this order. - * If the order was partially shipped, the status will be "completed" instead of - * "canceled". - * Will throw a ApiException if the order id is invalid or the resource cannot - * be found. - * - * @return Order - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function cancel() - { - return $this->client->orders->cancel($this->id, $this->getPresetOptions()); - } - - /** - * Cancel a line for this order. - * The data array must contain a lines array. - * You can pass an empty lines array if you want to cancel all eligible lines. - * Returns null if successful. - * - * @param array $data - * @return null - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function cancelLines(array $data) - { - return $this->client->orderLines->cancelFor($this, $data); - } - - /** - * Cancels all eligible lines for this order. - * Returns null if successful. - * - * @param array|null $data - * @return null - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function cancelAllLines($data = []) - { - $data['lines'] = []; - - return $this->client->orderLines->cancelFor($this, $data); - } - - /** - * Get the line value objects - * - * @return OrderLineCollection - */ - public function lines() - { - return ResourceFactory::createBaseResourceCollection( - $this->client, - OrderLine::class, - $this->lines - ); - } - - /** - * Create a shipment for some order lines. You can provide an empty array for the - * "lines" option to include all unshipped lines for this order. - * - * @param array $options - * - * @return Shipment - * @throws ApiException - */ - public function createShipment(array $options = []) - { - return $this->client->shipments->createFor($this, $this->withPresetOptions($options)); - } - - /** - * Create a shipment for all unshipped order lines. - * - * @param array $options - * - * @return Shipment - */ - public function shipAll(array $options = []) - { - $options['lines'] = []; - - return $this->createShipment($options); - } - - /** - * Retrieve a specific shipment for this order. - * - * @param string $shipmentId - * @param array $parameters - * - * @return Shipment - * @throws ApiException - */ - public function getShipment($shipmentId, array $parameters = []) - { - return $this->client->shipments->getFor($this, $shipmentId, $this->withPresetOptions($parameters)); - } - - /** - * Get all shipments for this order. - * - * @param array $parameters - * - * @return ShipmentCollection - * @throws ApiException - */ - public function shipments(array $parameters = []) - { - return $this->client->shipments->listFor($this, $this->withPresetOptions($parameters)); - } - - /** - * Get the checkout URL where the customer can complete the payment. - * - * @return string|null - */ - public function getCheckoutUrl() - { - if (empty($this->_links->checkout)) { - return null; - } - - return $this->_links->checkout->href; - } - - /** - * Refund specific order lines. - * - * @param array $data - * @return Refund - * @throws ApiException - */ - public function refund(array $data) - { - return $this->client->orderRefunds->createFor($this, $this->withPresetOptions($data)); - } - - /** - * Refund all eligible order lines. - * - * @param array $data - * @return Refund - */ - public function refundAll(array $data = []) - { - $data['lines'] = []; - - return $this->refund($data); - } - - /** - * Retrieves all refunds associated with this order - * - * @return RefundCollection - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function refunds() - { - return $this->client->orderRefunds->pageFor($this); - } - - /** - * Saves the order's updated billingAddress and/or shippingAddress. - * - * @return \Mollie\Api\Resources\Order - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function update() - { - $body = [ - "billingAddress" => $this->billingAddress, - "shippingAddress" => $this->shippingAddress, - "orderNumber" => $this->orderNumber, - "redirectUrl" => $this->redirectUrl, - "cancelUrl" => $this->cancelUrl, - "webhookUrl" => $this->webhookUrl, - ]; - - $result = $this->client->orders->update($this->id, $body); - - return ResourceFactory::createFromApiResult($result, new Order($this->client)); - } - - /** - * Create a new payment for this Order. - * - * @param array $data - * @param array $filters - * @return \Mollie\Api\Resources\Payment - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function createPayment($data, $filters = []) - { - return $this->client->orderPayments->createFor($this, $data, $filters); - } - - /** - * Retrieve the payments for this order. - * Requires the order to be retrieved using the embed payments parameter. - * - * @return null|\Mollie\Api\Resources\PaymentCollection - */ - public function payments() - { - if (! isset($this->_embedded, $this->_embedded->payments)) { - return null; - } - - return ResourceFactory::createCursorResourceCollection( - $this->client, - $this->_embedded->payments, - Payment::class - ); - } -} diff --git a/src/Resources/OrderCollection.php b/src/Resources/OrderCollection.php deleted file mode 100644 index ff5fad80c..000000000 --- a/src/Resources/OrderCollection.php +++ /dev/null @@ -1,22 +0,0 @@ -client); - } -} diff --git a/src/Resources/OrderLine.php b/src/Resources/OrderLine.php deleted file mode 100644 index aa700feb2..000000000 --- a/src/Resources/OrderLine.php +++ /dev/null @@ -1,420 +0,0 @@ -_links->productUrl)) { - return null; - } - - return $this->_links->productUrl; - } - - /** - * Get the image URL of the product sold. - * - * @return string|null - */ - public function getImageUrl() - { - if (empty($this->_links->imageUrl)) { - return null; - } - - return $this->_links->imageUrl; - } - - /** - * Is this order line created? - * - * @return bool - */ - public function isCreated() - { - return $this->status === OrderLineStatus::STATUS_CREATED; - } - - /** - * Is this order line paid for? - * - * @return bool - */ - public function isPaid() - { - return $this->status === OrderLineStatus::STATUS_PAID; - } - - /** - * Is this order line authorized? - * - * @return bool - */ - public function isAuthorized() - { - return $this->status === OrderLineStatus::STATUS_AUTHORIZED; - } - - /** - * Is this order line canceled? - * - * @return bool - */ - public function isCanceled() - { - return $this->status === OrderLineStatus::STATUS_CANCELED; - } - - /** - * (Deprecated) Is this order line refunded? - * @deprecated 2018-11-27 - * - * @return bool - */ - public function isRefunded() - { - return $this->status === OrderLineStatus::STATUS_REFUNDED; - } - - /** - * Is this order line shipping? - * - * @return bool - */ - public function isShipping() - { - return $this->status === OrderLineStatus::STATUS_SHIPPING; - } - - /** - * Is this order line completed? - * - * @return bool - */ - public function isCompleted() - { - return $this->status === OrderLineStatus::STATUS_COMPLETED; - } - - /** - * Is this order line for a physical product? - * - * @return bool - */ - public function isPhysical() - { - return $this->type === OrderLineType::TYPE_PHYSICAL; - } - - /** - * Is this order line for applying a discount? - * - * @return bool - */ - public function isDiscount() - { - return $this->type === OrderLineType::TYPE_DISCOUNT; - } - - /** - * Is this order line for a digital product? - * - * @return bool - */ - public function isDigital() - { - return $this->type === OrderLineType::TYPE_DIGITAL; - } - - /** - * Is this order line for applying a shipping fee? - * - * @return bool - */ - public function isShippingFee() - { - return $this->type === OrderLineType::TYPE_SHIPPING_FEE; - } - - /** - * Is this order line for store credit? - * - * @return bool - */ - public function isStoreCredit() - { - return $this->type === OrderLineType::TYPE_STORE_CREDIT; - } - - /** - * Is this order line for a gift card? - * - * @return bool - */ - public function isGiftCard() - { - return $this->type === OrderLineType::TYPE_GIFT_CARD; - } - - /** - * Is this order line for a surcharge? - * - * @return bool - */ - public function isSurcharge() - { - return $this->type === OrderLineType::TYPE_SURCHARGE; - } - - /** - * Update an orderline by supplying one or more parameters in the data array - * - * @return BaseResource - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function update() - { - $result = $this->client->orderLines->update($this->orderId, $this->id, $this->getUpdateData()); - - return ResourceFactory::createFromApiResult($result, new Order($this->client)); - } - - /** - * Get sanitized array of order line data - * - * @return array - */ - public function getUpdateData() - { - $data = [ - "name" => $this->name, - 'imageUrl' => $this->imageUrl, - 'productUrl' => $this->productUrl, - 'metadata' => $this->metadata, - 'sku' => $this->sku, - 'quantity' => $this->quantity, - 'unitPrice' => $this->unitPrice, - 'discountAmount' => $this->discountAmount, - 'totalAmount' => $this->totalAmount, - 'vatAmount' => $this->vatAmount, - 'vatRate' => $this->vatRate, - ]; - - // Explicitly filter only NULL values to keep "vatRate => 0" intact - return array_filter($data, function ($value) { - return $value !== null; - }); - } -} diff --git a/src/Resources/OrderLineCollection.php b/src/Resources/OrderLineCollection.php deleted file mode 100644 index d2f8bc285..000000000 --- a/src/Resources/OrderLineCollection.php +++ /dev/null @@ -1,32 +0,0 @@ -id === $lineId) { - return $line; - } - } - - return null; - } -} diff --git a/src/Resources/Organization.php b/src/Resources/Organization.php index 209f9e3af..37ea60545 100644 --- a/src/Resources/Organization.php +++ b/src/Resources/Organization.php @@ -2,8 +2,14 @@ namespace Mollie\Api\Resources; +/** + * @property \Mollie\Api\MollieApiClient $connector + */ class Organization extends BaseResource { + /** + * Resource id prefix. Used to validate resource id's. + */ /** * Id of the payment method. * diff --git a/src/Resources/OrganizationCollection.php b/src/Resources/OrganizationCollection.php deleted file mode 100644 index 1b2add379..000000000 --- a/src/Resources/OrganizationCollection.php +++ /dev/null @@ -1,22 +0,0 @@ -client); - } -} diff --git a/src/Resources/Partner.php b/src/Resources/Partner.php index 2c00ac1f1..0767fbd23 100644 --- a/src/Resources/Partner.php +++ b/src/Resources/Partner.php @@ -2,6 +2,9 @@ namespace Mollie\Api\Resources; +/** + * @property \Mollie\Api\MollieApiClient $connector + */ class Partner extends BaseResource { /** diff --git a/src/Resources/Payment.php b/src/Resources/Payment.php index e912341eb..7963264b8 100644 --- a/src/Resources/Payment.php +++ b/src/Resources/Payment.php @@ -2,14 +2,23 @@ namespace Mollie\Api\Resources; +use Mollie\Api\Contracts\EmbeddedResourcesContract; use Mollie\Api\Exceptions\ApiException; -use Mollie\Api\MollieApiClient; +use Mollie\Api\Http\Data\Metadata; +use Mollie\Api\Http\Data\UpdatePaymentPayload; +use Mollie\Api\Http\Requests\DynamicGetRequest; +use Mollie\Api\Http\Requests\UpdatePaymentRequest; +use Mollie\Api\Traits\HasMode; +use Mollie\Api\Types\PaymentMethod; use Mollie\Api\Types\PaymentStatus; use Mollie\Api\Types\SequenceType; -class Payment extends BaseResource +/** + * @property \Mollie\Api\MollieApiClient $connector + */ +class Payment extends BaseResource implements EmbeddedResourcesContract { - use HasPresetOptions; + use HasMode; /** * Id of the payment (on the Mollie platform). @@ -81,6 +90,7 @@ class Payment extends BaseResource * method. * * @see Method + * * @var string|null */ public $method; @@ -90,12 +100,13 @@ class Payment extends BaseResource * * @var string */ - public $status = PaymentStatus::STATUS_OPEN; + public $status = PaymentStatus::OPEN; /** * UTC datetime the payment was created in ISO-8601 format. * * @example "2013-12-25T10:30:54+00:00" + * * @var string|null */ public $createdAt; @@ -104,6 +115,7 @@ class Payment extends BaseResource * UTC datetime the payment was paid in ISO-8601 format. * * @example "2013-12-25T10:30:54+00:00" + * * @var string|null */ public $paidAt; @@ -112,6 +124,7 @@ class Payment extends BaseResource * UTC datetime the payment was canceled in ISO-8601 format. * * @example "2013-12-25T10:30:54+00:00" + * * @var string|null */ public $canceledAt; @@ -136,6 +149,7 @@ class Payment extends BaseResource * UTC due date for the banktransfer payment in ISO-8601 format. * * @example "2021-01-19" + * * @var string|null */ public $dueDate; @@ -145,7 +159,9 @@ class Payment extends BaseResource * Please note: the payment instructions will be sent immediately when creating the payment. * * @example "user@mollie.com" + * * @var string|null + * * @deprecated 2024-06-01 The billingEmail field is deprecated. Use the "billingAddress" field instead. */ public $billingEmail; @@ -154,6 +170,7 @@ class Payment extends BaseResource * The profile ID this payment belongs to. * * @example pfl_xH2kP6Nc6X + * * @var string */ public $profileId; @@ -190,6 +207,7 @@ class Payment extends BaseResource * The mandate ID this payment is performed with. * * @example mdt_pXm1g3ND + * * @var string|null */ public $mandateId; @@ -198,6 +216,7 @@ class Payment extends BaseResource * The subscription ID this payment belongs to. * * @example sub_rVKGtNd6s3 + * * @var string|null */ public $subscriptionId; @@ -206,6 +225,7 @@ class Payment extends BaseResource * The order ID this payment belongs to. * * @example ord_pbjz8x + * * @var string|null */ public $orderId; @@ -235,6 +255,7 @@ class Payment extends BaseResource * The settlement ID this payment belongs to. * * @example stl_jDk30akdN + * * @var string|null */ public $settlementId; @@ -265,7 +286,7 @@ class Payment extends BaseResource /** * Used to restrict the payment methods available to your customer to those from a single country. * - * @var string|null; + * @var string|null */ public $restrictPaymentMethodsToCountry; @@ -310,7 +331,9 @@ class Payment extends BaseResource * will be added to the date and time the payment became authorized. * * Possible values: ... hours ... days + * * @example 8 hours + * * @var string|null */ public $captureDelay; @@ -320,6 +343,7 @@ class Payment extends BaseResource * ISO-8601 format. This parameter is omitted if the payment is not authorized (yet). * * @example "2013-12-25T10:30:54+00:00" + * * @var string|null */ public $captureBefore; @@ -347,6 +371,7 @@ class Payment extends BaseResource * parameter is omitted if the payment is not authorized (yet). * * @example "2013-12-25T10:30:54+00:00" + * * @var string|null */ public $authorizedAt; @@ -356,6 +381,7 @@ class Payment extends BaseResource * parameter is omitted if the payment did not expire (yet). * * @example "2013-12-25T10:30:54+00:00" + * * @var string|null */ public $expiredAt; @@ -365,6 +391,7 @@ class Payment extends BaseResource * be available here as well. * * @example cst_XPn78q9CfT + * * @var string|null */ public $customerId; @@ -378,126 +405,111 @@ class Payment extends BaseResource */ public $countryCode; + public function getEmbeddedResourcesMap(): array + { + return [ + 'captures' => CaptureCollection::class, + 'refunds' => RefundCollection::class, + 'chargebacks' => ChargebackCollection::class, + ]; + } + /** * Is this payment canceled? - * - * @return bool */ - public function isCanceled() + public function isCanceled(): bool { - return $this->status === PaymentStatus::STATUS_CANCELED; + return $this->status === PaymentStatus::CANCELED; } /** * Is this payment expired? - * - * @return bool */ - public function isExpired() + public function isExpired(): bool { - return $this->status === PaymentStatus::STATUS_EXPIRED; + return $this->status === PaymentStatus::EXPIRED; } /** * Is this payment still open / ongoing? - * - * @return bool */ - public function isOpen() + public function isOpen(): bool { - return $this->status === PaymentStatus::STATUS_OPEN; + return $this->status === PaymentStatus::OPEN; } /** * Is this payment pending? - * - * @return bool */ - public function isPending() + public function isPending(): bool { - return $this->status === PaymentStatus::STATUS_PENDING; + return $this->status === PaymentStatus::PENDING; } /** * Is this payment authorized? - * - * @return bool */ - public function isAuthorized() + public function isAuthorized(): bool { - return $this->status === PaymentStatus::STATUS_AUTHORIZED; + return $this->status === PaymentStatus::AUTHORIZED; } /** * Is this payment paid for? - * - * @return bool */ - public function isPaid() + public function isPaid(): bool { return ! empty($this->paidAt); } /** * Does the payment have refunds - * - * @return bool */ - public function hasRefunds() + public function hasRefunds(): bool { return ! empty($this->_links->refunds); } /** * Does this payment has chargebacks - * - * @return bool */ - public function hasChargebacks() + public function hasChargebacks(): bool { return ! empty($this->_links->chargebacks); } /** * Is this payment failing? - * - * @return bool */ - public function isFailed() + public function isFailed(): bool { - return $this->status === PaymentStatus::STATUS_FAILED; + return $this->status === PaymentStatus::FAILED; } /** * Check whether 'sequenceType' is set to 'first'. If a 'first' payment has been * completed successfully, the consumer's account may be charged automatically * using recurring payments. - * - * @return bool */ - public function hasSequenceTypeFirst() + public function hasSequenceTypeFirst(): bool { - return $this->sequenceType === SequenceType::SEQUENCETYPE_FIRST; + return $this->sequenceType === SequenceType::FIRST; } /** * Check whether 'sequenceType' is set to 'recurring'. This type of payment is * processed without involving * the consumer. - * - * @return bool */ - public function hasSequenceTypeRecurring() + public function hasSequenceTypeRecurring(): bool { - return $this->sequenceType === SequenceType::SEQUENCETYPE_RECURRING; + return $this->sequenceType === SequenceType::RECURRING; } /** * Get the checkout URL where the customer can complete the payment. - * - * @return string|null */ - public function getCheckoutUrl() + public function getCheckoutUrl(): ?string { if (empty($this->_links->checkout)) { return null; @@ -508,10 +520,8 @@ public function getCheckoutUrl() /** * Get the mobile checkout URL where the customer can complete the payment. - * - * @return string|null */ - public function getMobileAppCheckoutUrl() + public function getMobileAppCheckoutUrl(): ?string { if (empty($this->_links->mobileAppCheckout)) { return null; @@ -520,31 +530,23 @@ public function getMobileAppCheckoutUrl() return $this->_links->mobileAppCheckout->href; } - /** - * @return bool - */ - public function canBeRefunded() + public function canBeRefunded(): bool { return $this->amountRemaining !== null; } - /** - * @return bool - */ - public function canBePartiallyRefunded() + public function canBePartiallyRefunded(): bool { return $this->canBeRefunded(); } /** * Get the amount that is already refunded - * - * @return float */ - public function getAmountRefunded() + public function getAmountRefunded(): float { if ($this->amountRefunded) { - return (float)$this->amountRefunded->value; + return (float) $this->amountRefunded->value; } return 0.0; @@ -554,13 +556,11 @@ public function getAmountRefunded() * Get the remaining amount that can be refunded. For some payment methods this * amount can be higher than the payment amount. This is possible to reimburse * the costs for a return shipment to your customer for example. - * - * @return float */ - public function getAmountRemaining() + public function getAmountRemaining(): float { if ($this->amountRemaining) { - return (float)$this->amountRemaining->value; + return (float) $this->amountRemaining->value; } return 0.0; @@ -569,13 +569,11 @@ public function getAmountRemaining() /** * Get the total amount that was charged back for this payment. Only available when the * total charged back amount is not zero. - * - * @return float */ - public function getAmountChargedBack() + public function getAmountChargedBack(): float { if ($this->amountChargedBack) { - return (float)$this->amountChargedBack->value; + return (float) $this->amountChargedBack->value; } return 0.0; @@ -583,10 +581,8 @@ public function getAmountChargedBack() /** * Does the payment have split payments - * - * @return bool */ - public function hasSplitPayments() + public function hasSplitPayments(): bool { return ! empty($this->routing); } @@ -594,183 +590,156 @@ public function hasSplitPayments() /** * Retrieves all refunds associated with this payment * - * @return RefundCollection * @throws ApiException */ - public function refunds() + public function refunds(): RefundCollection { if (! isset($this->_links->refunds->href)) { - return new RefundCollection($this->client, 0, null); + return new RefundCollection($this->connector, $this->response); } - $result = $this->client->performHttpCallToFullUrl( - MollieApiClient::HTTP_GET, - $this->_links->refunds->href - ); - - return ResourceFactory::createCursorResourceCollection( - $this->client, - $result->_embedded->refunds, - Refund::class, - $result->_links - ); + return $this + ->connector + ->send((new DynamicGetRequest($this->_links->refunds->href))->setHydratableResource(RefundCollection::class)); } /** - * @param string $refundId - * @param array $parameters + * @param string $refundId * - * @return Refund * @throws ApiException */ - public function getRefund($refundId, array $parameters = []) + public function getRefund($refundId, array $parameters = []): Refund { - return $this->client->paymentRefunds->getFor($this, $refundId, $this->withPresetOptions($parameters)); + return $this->connector->paymentRefunds->getFor($this, $refundId, $parameters, $this->isInTestmode()); } /** - * @param array $parameters - * - * @return Refund * @throws ApiException */ - public function listRefunds(array $parameters = []) + public function listRefunds(array $parameters = []): RefundCollection { - return $this->client->paymentRefunds->listFor($this, $this->withPresetOptions($parameters)); + return $this + ->connector + ->paymentRefunds + ->pageFor( + $this, + null, + null, + $this->withMode($parameters), + ); } /** * Retrieves all captures associated with this payment * - * @return CaptureCollection * @throws ApiException */ - public function captures() + public function captures(): CaptureCollection { if (! isset($this->_links->captures->href)) { - return new CaptureCollection($this->client, 0, null); + return new CaptureCollection($this->connector, $this->response); } - $result = $this->client->performHttpCallToFullUrl( - MollieApiClient::HTTP_GET, - $this->_links->captures->href - ); - - return ResourceFactory::createCursorResourceCollection( - $this->client, - $result->_embedded->captures, - Capture::class, - $result->_links - ); + return $this + ->connector + ->send((new DynamicGetRequest($this->_links->captures->href))->setHydratableResource(CaptureCollection::class)); } /** - * @param string $captureId - * @param array $parameters + * @param string $captureId * - * @return Capture * @throws ApiException */ - public function getCapture($captureId, array $parameters = []) + public function getCapture($captureId, array $parameters = []): Capture { - return $this->client->paymentCaptures->getFor( + return $this->connector->paymentCaptures->getFor( $this, $captureId, - $this->withPresetOptions($parameters) + $parameters, + $this->isInTestmode() ); } /** * Retrieves all chargebacks associated with this payment * - * @return ChargebackCollection * @throws ApiException */ - public function chargebacks() + public function chargebacks(): ChargebackCollection { if (! isset($this->_links->chargebacks->href)) { - return new ChargebackCollection($this->client, 0, null); + return new ChargebackCollection($this->connector, $this->response); } - $result = $this->client->performHttpCallToFullUrl( - MollieApiClient::HTTP_GET, - $this->_links->chargebacks->href - ); - - return ResourceFactory::createCursorResourceCollection( - $this->client, - $result->_embedded->chargebacks, - Chargeback::class, - $result->_links - ); + return $this + ->connector + ->send((new DynamicGetRequest($this->_links->chargebacks->href))->setHydratableResource(ChargebackCollection::class)); } /** * Retrieves a specific chargeback for this payment. * - * @param string $chargebackId - * @param array $parameters + * @param string $chargebackId * - * @return Chargeback * @throws ApiException */ - public function getChargeback($chargebackId, array $parameters = []) + public function getChargeback($chargebackId, array $parameters = []): Chargeback { - return $this->client->paymentChargebacks->getFor( + return $this->connector->paymentChargebacks->getFor( $this, $chargebackId, - $this->withPresetOptions($parameters) + $parameters, + $this->isInTestmode() ); } /** * Issue a refund for this payment. * - * @param array $data + * @param array $data * - * @return \Mollie\Api\Resources\Refund * @throws ApiException */ - public function refund($data) + public function refund($data): Refund { - return $this->client->paymentRefunds->createFor($this, $data); + return $this->connector->paymentRefunds->createFor($this, $data); } /** - * @return \Mollie\Api\Resources\Payment * @throws \Mollie\Api\Exceptions\ApiException */ - public function update() - { - $body = [ - "description" => $this->description, - "cancelUrl" => $this->cancelUrl, - "redirectUrl" => $this->redirectUrl, - "webhookUrl" => $this->webhookUrl, - "metadata" => $this->metadata, - "restrictPaymentMethodsToCountry" => $this->restrictPaymentMethodsToCountry, - "locale" => $this->locale, - "dueDate" => $this->dueDate, - ]; + public function update(): ?Payment + { + $additional = []; + if ($this->method === PaymentMethod::BANKTRANSFER) { + $additional['dueDate'] = $this->dueDate; + } - $result = $this->client->payments->update( - $this->id, - $this->withPresetOptions($body) + $payload = new UpdatePaymentPayload( + $this->description, + $this->redirectUrl, + $this->cancelUrl, + $this->webhookUrl, + new Metadata($this->metadata), + $this->method, + $this->locale, + $this->restrictPaymentMethodsToCountry, + $additional ); - return ResourceFactory::createFromApiResult($result, new Payment($this->client)); + return $this + ->connector + ->send((new UpdatePaymentRequest($this->id, $payload))->test($this->isInTestmode())); } /** * The total amount that is already captured for this payment. Only available * when this payment supports captures. - * - * @return float */ - public function getAmountCaptured() + public function getAmountCaptured(): float { if ($this->amountCaptured) { - return (float)$this->amountCaptured->value; + return (float) $this->amountCaptured->value; } return 0.0; @@ -778,13 +747,11 @@ public function getAmountCaptured() /** * The amount that has been settled. - * - * @return float */ - public function getSettlementAmount() + public function getSettlementAmount(): float { if ($this->settlementAmount) { - return (float)$this->settlementAmount->value; + return (float) $this->settlementAmount->value; } return 0.0; @@ -793,13 +760,11 @@ public function getSettlementAmount() /** * The total amount that is already captured for this payment. Only available * when this payment supports captures. - * - * @return float */ - public function getApplicationFeeAmount() + public function getApplicationFeeAmount(): float { if ($this->applicationFee) { - return (float)$this->applicationFee->amount->value; + return (float) $this->applicationFee->amount->value; } return 0.0; diff --git a/src/Resources/PaymentCollection.php b/src/Resources/PaymentCollection.php index 892deb1be..b1ebca308 100644 --- a/src/Resources/PaymentCollection.php +++ b/src/Resources/PaymentCollection.php @@ -5,18 +5,12 @@ class PaymentCollection extends CursorCollection { /** - * @return string + * The name of the collection resource in Mollie's API. */ - public function getCollectionResourceName() - { - return "payments"; - } + public static string $collectionName = 'payments'; /** - * @return BaseResource + * Resource class name. */ - protected function createResourceObject() - { - return new Payment($this->client); - } + public static string $resource = Payment::class; } diff --git a/src/Resources/PaymentLink.php b/src/Resources/PaymentLink.php index c37776a58..397de6c19 100644 --- a/src/Resources/PaymentLink.php +++ b/src/Resources/PaymentLink.php @@ -2,6 +2,9 @@ namespace Mollie\Api\Resources; +/** + * @property \Mollie\Api\MollieApiClient $connector + */ class PaymentLink extends BaseResource { /** @@ -23,6 +26,7 @@ class PaymentLink extends BaseResource * The profile ID this payment link belongs to. * * @example pfl_QkEhN94Ba + * * @var string */ public $profileId; @@ -31,6 +35,7 @@ class PaymentLink extends BaseResource * UTC datetime the payment link was created in ISO-8601 format. * * @example "2013-12-25T10:30:54+00:00" + * * @var string|null */ public $createdAt; @@ -39,6 +44,7 @@ class PaymentLink extends BaseResource * UTC datetime the payment was paid in ISO-8601 format. * * @example "2013-12-25T10:30:54+00:00" + * * @var string|null */ public $paidAt; @@ -50,11 +56,12 @@ class PaymentLink extends BaseResource * @var bool */ public $archived; - + /** * UTC datetime the payment link was updated in ISO-8601 format. * * @example "2013-12-25T10:30:54+00:00" + * * @var string|null */ public $updatedAt; @@ -63,6 +70,7 @@ class PaymentLink extends BaseResource * UTC datetime - the expiry date of the payment link in ISO-8601 format. * * @example "2013-12-25T10:30:54+00:00" + * * @var string|null */ public $expiresAt; @@ -103,20 +111,16 @@ class PaymentLink extends BaseResource /** * Is this payment paid for? - * - * @return bool */ - public function isPaid() + public function isPaid(): bool { return ! empty($this->paidAt); } /** * Get the checkout URL where the customer can complete the payment. - * - * @return string|null */ - public function getCheckoutUrl() + public function getCheckoutUrl(): ?string { if (empty($this->_links->paymentLink)) { return null; @@ -128,77 +132,58 @@ public function getCheckoutUrl() /** * Persist the current local Payment Link state to the Mollie API. * - * @return mixed|\Mollie\Api\Resources\BaseResource * @throws \Mollie\Api\Exceptions\ApiException */ - public function update() + public function update(): ?PaymentLink { - $body = $this->withPresetOptions([ + $body = $this->withTestmode([ 'description' => $this->description, 'archived' => $this->archived, ]); - $result = $this->client->paymentLinks->update($this->id, $body); - - return ResourceFactory::createFromApiResult($result, new PaymentLink($this->client)); + return $this->connector->paymentLinks->update($this->id, $body); } /** * Archive this Payment Link. * * @return \Mollie\Api\Resources\PaymentLink + * * @throws \Mollie\Api\Exceptions\ApiException */ public function archive() { - $data = $this->withPresetOptions([ + $data = $this->withTestmode([ 'archived' => true, ]); - return $this->client->paymentLinks->update($this->id, $data); + return $this->connector->paymentLinks->update($this->id, $data); } /** * Retrieve a paginated list of payments associated with this payment link. * - * @param string|null $from - * @param int|null $limit - * @param array $filters * @return mixed|\Mollie\Api\Resources\BaseCollection */ public function payments(?string $from = null, ?int $limit = null, array $filters = []) { - return $this->client->paymentLinkPayments->pageFor( + return $this->connector->paymentLinkPayments->pageFor( $this, $from, $limit, - $this->withPresetOptions($filters) + $this->withTestmode($filters) ); } - /** - * When accessed by oAuth we want to pass the testmode by default - * - * @return array - */ - private function getPresetOptions() - { - $options = []; - if ($this->client->usesOAuth()) { - $options["testmode"] = $this->mode === "test"; - } - - return $options; - } - /** * Apply the preset options. * - * @param array $options * @return array */ - private function withPresetOptions(array $options) + private function withTestmode(array $options) { - return array_merge($this->getPresetOptions(), $options); + return array_merge([ + 'testmode' => $this->mode === 'test', + ], $options); } } diff --git a/src/Resources/PaymentLinkCollection.php b/src/Resources/PaymentLinkCollection.php index 061f1f665..ea70210e6 100644 --- a/src/Resources/PaymentLinkCollection.php +++ b/src/Resources/PaymentLinkCollection.php @@ -5,18 +5,12 @@ class PaymentLinkCollection extends CursorCollection { /** - * @return string + * The name of the collection resource in Mollie's API. */ - public function getCollectionResourceName() - { - return "payment_links"; - } + public static string $collectionName = 'payment_links'; /** - * @return BaseResource + * Resource class name. */ - protected function createResourceObject() - { - return new PaymentLink($this->client); - } + public static string $resource = PaymentLink::class; } diff --git a/src/Resources/Permission.php b/src/Resources/Permission.php index fe0761d0a..e1a380ce1 100644 --- a/src/Resources/Permission.php +++ b/src/Resources/Permission.php @@ -2,10 +2,14 @@ namespace Mollie\Api\Resources; +/** + * @property \Mollie\Api\MollieApiClient $connector + */ class Permission extends BaseResource { /** * @var string + * * @example payments.read */ public $id; diff --git a/src/Resources/PermissionCollection.php b/src/Resources/PermissionCollection.php index 510cc64a7..709a44c5e 100644 --- a/src/Resources/PermissionCollection.php +++ b/src/Resources/PermissionCollection.php @@ -2,13 +2,12 @@ namespace Mollie\Api\Resources; -class PermissionCollection extends BaseCollection +class PermissionCollection extends ResourceCollection { /** - * @return string + * The name of the collection resource in Mollie's API. */ - public function getCollectionResourceName() - { - return "permissions"; - } + public static string $collectionName = 'permissions'; + + public static string $resource = Permission::class; } diff --git a/src/Resources/Profile.php b/src/Resources/Profile.php index 1c87d9d65..e4ab49c54 100644 --- a/src/Resources/Profile.php +++ b/src/Resources/Profile.php @@ -3,9 +3,12 @@ namespace Mollie\Api\Resources; use Mollie\Api\Exceptions\ApiException; -use Mollie\Api\MollieApiClient; +use Mollie\Api\Http\Requests\DynamicGetRequest; use Mollie\Api\Types\ProfileStatus; +/** + * @property \Mollie\Api\MollieApiClient $connector + */ class Profile extends BaseResource { /** @@ -45,6 +48,7 @@ class Profile extends BaseResource * This parameter is deprecated and will be removed in 2022. Please use the businessCategory parameter instead. * * @deprecated + * * @var int|null */ public $categoryCode; @@ -70,6 +74,7 @@ class Profile extends BaseResource * UTC datetime the profile was created in ISO-8601 format. * * @example "2013-12-25T10:30:54+00:00" + * * @var string */ public $createdAt; @@ -79,161 +84,121 @@ class Profile extends BaseResource */ public $_links; - /** - * @return bool - */ - public function isUnverified() + public function isUnverified(): bool { - return $this->status == ProfileStatus::STATUS_UNVERIFIED; + return $this->status == ProfileStatus::UNVERIFIED; } - /** - * @return bool - */ - public function isVerified() + public function isVerified(): bool { - return $this->status == ProfileStatus::STATUS_VERIFIED; + return $this->status == ProfileStatus::VERIFIED; } - /** - * @return bool - */ - public function isBlocked() + public function isBlocked(): bool { - return $this->status == ProfileStatus::STATUS_BLOCKED; + return $this->status == ProfileStatus::BLOCKED; } /** - * @return \Mollie\Api\Resources\Profile * @throws ApiException */ - public function update() + public function update(): ?Profile { $body = [ - "name" => $this->name, - "website" => $this->website, - "email" => $this->email, - "phone" => $this->phone, - "businessCategory" => $this->businessCategory, - "mode" => $this->mode, + 'name' => $this->name, + 'website' => $this->website, + 'email' => $this->email, + 'phone' => $this->phone, + 'businessCategory' => $this->businessCategory, + 'mode' => $this->mode, ]; - $result = $this->client->profiles->update($this->id, $body); - - return ResourceFactory::createFromApiResult($result, new Profile($this->client)); + return $this->connector->profiles->update($this->id, $body); } /** * Retrieves all chargebacks associated with this profile * - * @return ChargebackCollection * @throws ApiException */ - public function chargebacks() + public function chargebacks(): ChargebackCollection { if (! isset($this->_links->chargebacks->href)) { - return new ChargebackCollection($this->client, 0, null); + return new ChargebackCollection($this->connector, $this->response); } - $result = $this->client->performHttpCallToFullUrl(MollieApiClient::HTTP_GET, $this->_links->chargebacks->href); - - return ResourceFactory::createCursorResourceCollection( - $this->client, - $result->_embedded->chargebacks, - Chargeback::class, - $result->_links - ); + return $this + ->connector + ->send((new DynamicGetRequest($this->_links->chargebacks->href))->setHydratableResource(ChargebackCollection::class)); } /** * Retrieves all methods activated on this profile * - * @return MethodCollection * @throws ApiException */ - public function methods() + public function methods(): MethodCollection { if (! isset($this->_links->methods->href)) { - return new MethodCollection(0, null); + return new MethodCollection($this->connector, $this->response); } - $result = $this->client->performHttpCallToFullUrl(MollieApiClient::HTTP_GET, $this->_links->methods->href); - - return ResourceFactory::createCursorResourceCollection( - $this->client, - $result->_embedded->methods, - Method::class, - $result->_links - ); + return $this + ->connector + ->send((new DynamicGetRequest($this->_links->methods->href))->setHydratableResource(MethodCollection::class)); } /** * Enable a payment method for this profile. * - * @param string $methodId - * @param array $data - * @return Method + * * @throws ApiException */ - public function enableMethod($methodId, array $data = []) + public function enableMethod(string $methodId): Method { - return $this->client->profileMethods->createFor($this, $methodId, $data); + return $this->connector->profileMethods->createFor($this, $methodId); } /** * Disable a payment method for this profile. * - * @param string $methodId - * @param array $data - * @return Method + * * @throws ApiException */ - public function disableMethod($methodId, array $data = []) + public function disableMethod(string $methodId): void { - return $this->client->profileMethods->deleteFor($this, $methodId, $data); + $this->connector->profileMethods->deleteFor($this, $methodId); } /** * Retrieves all payments associated with this profile * - * @return PaymentCollection * @throws ApiException */ - public function payments() + public function payments(): PaymentCollection { if (! isset($this->_links->payments->href)) { - return new PaymentCollection($this->client, 0, null); + return new PaymentCollection($this->connector, $this->response); } - $result = $this->client->performHttpCallToFullUrl(MollieApiClient::HTTP_GET, $this->_links->payments->href); - - return ResourceFactory::createCursorResourceCollection( - $this->client, - $result->_embedded->methods, - Method::class, - $result->_links - ); + return $this + ->connector + ->send((new DynamicGetRequest($this->_links->payments->href))->setHydratableResource(PaymentCollection::class)); } /** * Retrieves all refunds associated with this profile * - * @return RefundCollection * @throws ApiException */ - public function refunds() + public function refunds(): RefundCollection { if (! isset($this->_links->refunds->href)) { - return new RefundCollection($this->client, 0, null); + return new RefundCollection($this->connector, $this->response); } - $result = $this->client->performHttpCallToFullUrl(MollieApiClient::HTTP_GET, $this->_links->refunds->href); - - return ResourceFactory::createCursorResourceCollection( - $this->client, - $result->_embedded->refunds, - Refund::class, - $result->_links - ); + return $this + ->connector + ->send((new DynamicGetRequest($this->_links->refunds->href))->setHydratableResource(RefundCollection::class)); } } diff --git a/src/Resources/ProfileCollection.php b/src/Resources/ProfileCollection.php index 536926b37..e8fe21133 100644 --- a/src/Resources/ProfileCollection.php +++ b/src/Resources/ProfileCollection.php @@ -5,18 +5,12 @@ class ProfileCollection extends CursorCollection { /** - * @return string + * The name of the collection resource in Mollie's API. */ - public function getCollectionResourceName() - { - return "profiles"; - } + public static string $collectionName = 'profiles'; /** - * @return BaseResource + * Resource class name. */ - protected function createResourceObject() - { - return new Profile($this->client); - } + public static string $resource = Profile::class; } diff --git a/src/Resources/Refund.php b/src/Resources/Refund.php index 88f3e4ae2..4b04186b0 100644 --- a/src/Resources/Refund.php +++ b/src/Resources/Refund.php @@ -2,11 +2,16 @@ namespace Mollie\Api\Resources; +use Mollie\Api\Http\Requests\CancelPaymentRefundRequest; +use Mollie\Api\Traits\HasMode; use Mollie\Api\Types\RefundStatus; +/** + * @property \Mollie\Api\MollieApiClient $connector + */ class Refund extends BaseResource { - use HasPresetOptions; + use HasMode; /** * Id of the payment method. @@ -33,6 +38,7 @@ class Refund extends BaseResource * UTC datetime the payment was created in ISO-8601 format. * * @example "2013-12-25T10:30:54+00:00" + * * @var string */ public $createdAt; @@ -98,87 +104,71 @@ class Refund extends BaseResource */ public $metadata; - /** - * @return bool - */ - public function canBeCanceled() + public function canBeCanceled(): bool { return $this->isQueued() || $this->isPending(); } /** * Is this refund queued? - * - * @return bool */ - public function isQueued() + public function isQueued(): bool { - return $this->status === RefundStatus::STATUS_QUEUED; + return $this->status === RefundStatus::QUEUED; } /** * Is this refund pending? - * - * @return bool */ - public function isPending() + public function isPending(): bool { - return $this->status === RefundStatus::STATUS_PENDING; + return $this->status === RefundStatus::PENDING; } /** * Is this refund processing? - * - * @return bool */ - public function isProcessing() + public function isProcessing(): bool { - return $this->status === RefundStatus::STATUS_PROCESSING; + return $this->status === RefundStatus::PROCESSING; } /** * Is this refund transferred to consumer? - * - * @return bool */ - public function isTransferred() + public function isTransferred(): bool { - return $this->status === RefundStatus::STATUS_REFUNDED; + return $this->status === RefundStatus::REFUNDED; } /** * Is this refund failed? - * - * @return bool */ - public function isFailed() + public function isFailed(): bool { - return $this->status === RefundStatus::STATUS_FAILED; + return $this->status === RefundStatus::FAILED; } /** * Is this refund canceled? - * - * @return bool */ - public function isCanceled() + public function isCanceled(): bool { - return $this->status === RefundStatus::STATUS_CANCELED; + return $this->status === RefundStatus::CANCELED; } /** * Cancel the refund. - * Returns null if successful. * - * @return null * @throws \Mollie\Api\Exceptions\ApiException */ - public function cancel() + public function cancel(): void { - return $this->client->paymentRefunds->cancelForId( - $this->paymentId, - $this->id, - $this->getPresetOptions() - ); + $this + ->connector + ->send((new CancelPaymentRefundRequest( + $this->paymentId, + $this->id + ))->test($this->isInTestmode())); } } diff --git a/src/Resources/RefundCollection.php b/src/Resources/RefundCollection.php index 01b55a3ce..1ab9eecfd 100644 --- a/src/Resources/RefundCollection.php +++ b/src/Resources/RefundCollection.php @@ -5,18 +5,12 @@ class RefundCollection extends CursorCollection { /** - * @return string + * The name of the collection resource in Mollie's API. */ - public function getCollectionResourceName() - { - return "refunds"; - } + public static string $collectionName = 'refunds'; /** - * @return BaseResource + * Resource class name. */ - protected function createResourceObject() - { - return new Refund($this->client); - } + public static string $resource = Refund::class; } diff --git a/src/Resources/ResourceCollection.php b/src/Resources/ResourceCollection.php new file mode 100644 index 000000000..d7dba9a51 --- /dev/null +++ b/src/Resources/ResourceCollection.php @@ -0,0 +1,20 @@ + $value) { - $resource->{$property} = $value; + if ($data instanceof Response) { + $response = $data; + $data = $response->json(); + } elseif ($response === null) { + throw new \InvalidArgumentException('Response is required'); + } + + /** @var BaseResource $resource */ + $resource = (new $resourceClass($connector))->setResponse($response); + + if ($resource instanceof AnyResource) { + $resource->fill($data); + } else { + foreach ($data as $property => $value) { + $resource->{$property} = self::holdsEmbeddedResources($resource, $property, $value) + ? self::parseEmbeddedResources($connector, $resource, $value, $response) + : $value; + } } return $resource; } /** - * @param MollieApiClient $client - * @param string $resourceClass - * @param array $data - * @param null $_links - * @param string $resourceCollectionClass - * @return mixed + * @param null|array|\ArrayObject $data */ public static function createBaseResourceCollection( - MollieApiClient $client, - $resourceClass, - $data, - $_links = null, - $resourceCollectionClass = null - ) { - $resourceCollectionClass = $resourceCollectionClass ?: $resourceClass . 'Collection'; - $data = $data ?: []; - - $result = new $resourceCollectionClass(count($data), $_links); - foreach ($data as $item) { - $result[] = static::createFromApiResult($item, new $resourceClass($client)); + Connector $connector, + string $resourceClass, + Response $response, + $data = null, + ?object $_links = null, + ?string $resourceCollectionClass = null + ): BaseCollection { + return self::instantiateBaseCollection( + $connector, + self::determineCollectionClass($resourceClass, $resourceCollectionClass), + self::mapToResourceObjects($connector, $data ?? [], $resourceClass, $response), + $response, + $_links + ); + } + + /** + * Create a decorated resource from a response or existing resource. + * + * @param Response|BaseResource|BaseCollection|LazyCollection $response + */ + public static function createDecoratedResource($response, string $decorator): IsWrapper + { + if (! is_subclass_of($decorator, IsWrapper::class)) { + throw new \InvalidArgumentException("The decorator class '{$decorator}' does not implement the ResourceDecorator interface."); } - return $result; + return $decorator::fromResource($response); } /** - * @param MollieApiClient $client - * @param array $input - * @param string $resourceClass - * @param null $_links - * @param null $resourceCollectionClass - * @return mixed + * Check if the resource holds embedded resources + * + * @param array|\ArrayAccess $value */ - public static function createCursorResourceCollection( - $client, - array $input, - $resourceClass, - $_links = null, - $resourceCollectionClass = null - ) { - if (null === $resourceCollectionClass) { - $resourceCollectionClass = $resourceClass.'Collection'; - } + private static function holdsEmbeddedResources(object $resource, string $key, $value): bool + { + return $key === '_embedded' + && ! is_null($value) + && $resource instanceof EmbeddedResourcesContract; + } - $data = new $resourceCollectionClass($client, count($input), $_links); - foreach ($input as $item) { - $data[] = static::createFromApiResult($item, new $resourceClass($client)); + /** + * Parses embedded resources into their respective resource objects or collections. + */ + private static function parseEmbeddedResources(Connector $connector, object $resource, object $embedded, Response $response): object + { + $result = new \stdClass; + + foreach ($embedded as $resourceKey => $resourceData) { + $collectionOrResourceClass = $resource->getEmbeddedResourcesMap()[$resourceKey] ?? null; + + if (is_null($collectionOrResourceClass)) { + throw new EmbeddedResourcesNotParseableException( + 'Resource '.get_class($resource)." does not have a mapping for embedded resource {$resourceKey}" + ); + } + + $result->{$resourceKey} = is_subclass_of($collectionOrResourceClass, BaseResource::class) + ? self::createFromApiResult( + $connector, + $resourceData, + $collectionOrResourceClass, + $response + ) + : self::createEmbeddedResourceCollection( + $connector, + $collectionOrResourceClass, + $resourceData, + $response + ); } - return $data; + return $result; + } + + /** + * @param array|\ArrayObject $data + */ + private static function createEmbeddedResourceCollection( + Connector $connector, + string $collectionClass, + $data, + Response $response + ): BaseCollection { + return self::instantiateBaseCollection( + $connector, + $collectionClass, + self::mapToResourceObjects( + $connector, + $data, + $collectionClass::getResourceClass(), + $response + ), + $response + ); + } + + private static function instantiateBaseCollection( + Connector $connector, + string $collectionClass, + array $items, + Response $response, + ?object $_links = null + ): BaseCollection { + return (new $collectionClass($connector, $items, $_links))->setResponse($response); + } + + /** + * @param array|\ArrayObject $data + */ + private static function mapToResourceObjects(Connector $connector, $data, string $resourceClass, Response $response): array + { + return array_map( + fn ($item) => static::createFromApiResult( + $connector, + $item, + $resourceClass, + $response, + ), + (array) $data + ); + } + + private static function determineCollectionClass(string $resourceClass, ?string $resourceCollectionClass): string + { + return $resourceCollectionClass ?: $resourceClass.'Collection'; } } diff --git a/src/Resources/ResourceHydrator.php b/src/Resources/ResourceHydrator.php new file mode 100644 index 000000000..3c3bb283d --- /dev/null +++ b/src/Resources/ResourceHydrator.php @@ -0,0 +1,81 @@ +getHydratableResource(); + + if ($targetResourceClass instanceof WrapperResource) { + $response = $this->hydrate( + // Reset the hydratable resource to the original resource class. + $request->resetHydratableResource(), + $response, + ); + + return ResourceFactory::createDecoratedResource($response, $targetResourceClass->getWrapper()); + } + + if ($this->isCollectionTarget($targetResourceClass)) { + $collection = $this->buildResultCollection($response, $targetResourceClass); + + return $this->unwrapIterator($request, $collection); + } + + if ($this->isResourceTarget($targetResourceClass)) { + return ResourceFactory::createFromApiResult($response->getConnector(), $response, $targetResourceClass); + } + + return $response; + } + + /** + * @return BaseCollection|LazyCollection + */ + private function unwrapIterator(Request $request, BaseCollection $collection) + { + if ($request instanceof IsIteratable && $request->iteratorEnabled()) { + /** @var CursorCollection $collection */ + return $collection->getAutoIterator($request->iteratesBackwards()); + } + + return $collection; + } + + private function buildResultCollection(Response $response, string $targetCollectionClass): BaseCollection + { + $result = $response->json(); + + return ResourceFactory::createBaseResourceCollection( + $response->getConnector(), + ($targetCollectionClass)::getResourceClass(), + $response, + $result->_embedded->{$targetCollectionClass::getCollectionResourceName()}, + $result->_links, + $targetCollectionClass, + ); + } + + private function isCollectionTarget(string $targetResourceClass): bool + { + return is_subclass_of($targetResourceClass, BaseCollection::class); + } + + private function isResourceTarget(string $targetResourceClass): bool + { + return is_subclass_of($targetResourceClass, BaseResource::class); + } +} diff --git a/src/Resources/ResourceWrapper.php b/src/Resources/ResourceWrapper.php new file mode 100644 index 000000000..4827c9230 --- /dev/null +++ b/src/Resources/ResourceWrapper.php @@ -0,0 +1,51 @@ +wrapped = $wrapped; + + return $this; + } + + /** + * @param mixed $resource + * @return static + */ + public function wrap($resource) + { + return $this->setWrapped($resource); + } + + /** + * @return mixed + */ + public function getWrapped() + { + return $this->wrapped; + } + + public function __get($name) + { + return $this->wrapped->{$name}; + } + + public function __call($name, $arguments) + { + return $this->forwardDecoratedCallTo($this->wrapped, $name, $arguments); + } +} diff --git a/src/Resources/Route.php b/src/Resources/Route.php index 20b119d34..30c12743f 100644 --- a/src/Resources/Route.php +++ b/src/Resources/Route.php @@ -2,6 +2,9 @@ namespace Mollie\Api\Resources; +/** + * @property \Mollie\Api\MollieApiClient $connector + */ class Route extends BaseResource { /** @@ -29,6 +32,7 @@ class Route extends BaseResource * A UTC date. The settlement of a routed payment can be delayed on payment level, by specifying a release Date * * @example "2013-12-25" + * * @var string */ public $releaseDate; diff --git a/src/Resources/RouteCollection.php b/src/Resources/RouteCollection.php deleted file mode 100644 index 34e797366..000000000 --- a/src/Resources/RouteCollection.php +++ /dev/null @@ -1,22 +0,0 @@ -client); - } -} diff --git a/src/Resources/SalesInvoice.php b/src/Resources/SalesInvoice.php new file mode 100644 index 000000000..58b489176 --- /dev/null +++ b/src/Resources/SalesInvoice.php @@ -0,0 +1,168 @@ +status === SalesInvoiceStatus::DRAFT; + } + + /** + * Returns whether the sales invoice is issued. + * + * @return bool + */ + public function isIssued() + { + return $this->status === SalesInvoiceStatus::ISSUED; + } + + /** + * Returns whether the sales invoice is paid. + * + * @return bool + */ + public function isPaid() + { + return $this->status === SalesInvoiceStatus::PAID; + } +} diff --git a/src/Resources/SalesInvoiceCollection.php b/src/Resources/SalesInvoiceCollection.php new file mode 100644 index 000000000..4123f8b82 --- /dev/null +++ b/src/Resources/SalesInvoiceCollection.php @@ -0,0 +1,16 @@ + $this->shippingAddress, ]; - $result = $this->client->sessions->update($this->id, $this->withPresetOptions($body)); - - return ResourceFactory::createFromApiResult($result, new Session($this->client)); + return $this->connector->sessions->update($this->id, $this->withMode($body)); } /** * Cancels this session. * - * @return Session * @throws \Mollie\Api\Exceptions\ApiException */ - public function cancel() + public function cancel(): void { - return $this->client->sessions->cancel($this->id, $this->getPresetOptions()); + $this->connector->sessions->cancel($this->id); } /** diff --git a/src/Resources/SessionCollection.php b/src/Resources/SessionCollection.php index b1414c36b..be1eeb9cd 100644 --- a/src/Resources/SessionCollection.php +++ b/src/Resources/SessionCollection.php @@ -5,18 +5,12 @@ class SessionCollection extends CursorCollection { /** - * @return string + * The name of the collection resource in Mollie's API. */ - public function getCollectionResourceName() - { - return "sessions"; - } + public static string $collectionName = 'sessions'; /** - * @return BaseResource + * Resource class name. */ - protected function createResourceObject() - { - return new Session($this->client); - } + public static string $resource = Session::class; } diff --git a/src/Resources/Settlement.php b/src/Resources/Settlement.php index d3b77ddeb..5d5f96fef 100644 --- a/src/Resources/Settlement.php +++ b/src/Resources/Settlement.php @@ -5,6 +5,9 @@ use Mollie\Api\Exceptions\ApiException; use Mollie\Api\Types\SettlementStatus; +/** + * @property \Mollie\Api\MollieApiClient $connector + */ class Settlement extends BaseResource { /** @@ -25,6 +28,7 @@ class Settlement extends BaseResource * UTC datetime the payment was created in ISO-8601 format. * * @example "2013-12-25T10:30:54+00:00" + * * @var string */ public $createdAt; @@ -33,6 +37,7 @@ class Settlement extends BaseResource * The date on which the settlement was settled, in ISO 8601 format. When requesting the open settlement or next settlement the return value is null. * * @example "2013-12-25T10:30:54+00:00" + * * @var string|null */ public $settledAt; @@ -72,113 +77,85 @@ class Settlement extends BaseResource /** * Is this settlement still open? - * - * @return bool */ - public function isOpen() + public function isOpen(): bool { - return $this->status === SettlementStatus::STATUS_OPEN; + return $this->status === SettlementStatus::OPEN; } /** * Is this settlement pending? - * - * @return bool */ - public function isPending() + public function isPending(): bool { - return $this->status === SettlementStatus::STATUS_PENDING; + return $this->status === SettlementStatus::PENDING; } /** * Is this settlement paid out? - * - * @return bool */ - public function isPaidout() + public function isPaidout(): bool { - return $this->status === SettlementStatus::STATUS_PAIDOUT; + return $this->status === SettlementStatus::PAIDOUT; } /** * Has this settlement failed? - * - * @return bool */ - public function isFailed() + public function isFailed(): bool { - return $this->status === SettlementStatus::STATUS_FAILED; + return $this->status === SettlementStatus::FAILED; } /** * Retrieve the first page of payments associated with this settlement. * - * @param int|null $limit - * @param array $parameters - * @return PaymentCollection * @throws \Mollie\Api\Exceptions\ApiException */ public function payments(?int $limit = null, array $parameters = []): PaymentCollection { - return $this->client->settlementPayments->pageForId( + return $this->connector->settlementPayments->pageForId( $this->id, - null, - $limit, - $parameters + array_merge($parameters, ['limit' => $limit]) ); } /** * Retrieve the first page of refunds associated with this settlement. * - * @param int|null $limit - * @param array $parameters - * @return RefundCollection * @throws ApiException */ - public function refunds(?int $limit = null, array $parameters = []) + public function refunds(?int $limit = null, array $parameters = []): RefundCollection { - return $this->client->settlementRefunds->pageForId( + return $this->connector->settlementRefunds->pageForId( $this->id, - null, - $limit, - $parameters + array_merge($parameters, ['limit' => $limit]) ); } /** * Retrieve the first page of chargebacks associated with this settlement. * - * @param int|null $limit - * @param array $parameters - * @return ChargebackCollection * @throws ApiException */ - public function chargebacks(?int $limit = null, array $parameters = []) + public function chargebacks(?int $limit = null, array $parameters = []): ChargebackCollection { - return $this->client->settlementChargebacks->pageForId( + return $this->connector->settlementChargebacks->pageForId( $this->id, - null, - $limit, - $parameters + array_merge($parameters, ['limit' => $limit]) ); } /** * Retrieve the first page of cap associated with this settlement. * - * @param int|null $limit - * @param array $parameters - * @return CaptureCollection * @throws ApiException */ - public function captures(?int $limit = null, array $parameters = []) + public function captures(?int $limit = null, array $parameters = []): CaptureCollection { - return $this->client->settlementCaptures->pageForId( + return $this->connector->settlementCaptures->pageForId( $this->id, - null, - $limit, - $parameters + array_merge($parameters, ['limit' => $limit]) ); } } diff --git a/src/Resources/SettlementCollection.php b/src/Resources/SettlementCollection.php index f8910b6f6..186128237 100644 --- a/src/Resources/SettlementCollection.php +++ b/src/Resources/SettlementCollection.php @@ -5,18 +5,12 @@ class SettlementCollection extends CursorCollection { /** - * @return string + * The name of the collection resource in Mollie's API. */ - public function getCollectionResourceName() - { - return "settlements"; - } + public static string $collectionName = 'settlements'; /** - * @return BaseResource + * Resource class name. */ - protected function createResourceObject() - { - return new Settlement($this->client); - } + public static string $resource = Settlement::class; } diff --git a/src/Resources/Shipment.php b/src/Resources/Shipment.php deleted file mode 100644 index 01c1e9ae4..000000000 --- a/src/Resources/Shipment.php +++ /dev/null @@ -1,124 +0,0 @@ -tracking !== null; - } - - /** - * Does this shipment offer a track and trace code? - * - * @return bool - */ - public function hasTrackingUrl() - { - return $this->hasTracking() && ! empty($this->tracking->url); - } - - /** - * Retrieve the track and trace url. Returns null if there is no url available. - * - * @return string|null - */ - public function getTrackingUrl() - { - if (! $this->hasTrackingUrl()) { - return null; - } - - return $this->tracking->url; - } - - /** - * Get the line value objects - * - * @return OrderLineCollection - */ - public function lines() - { - return ResourceFactory::createBaseResourceCollection( - $this->client, - OrderLine::class, - $this->lines - ); - } - - /** - * Get the Order object for this shipment - * - * @return Order - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function order() - { - return $this->client->orders->get($this->orderId); - } - - /** - * Save changes made to this shipment. - * - * @return BaseResource|Shipment - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function update() - { - $body = [ - "tracking" => $this->tracking, - ]; - - $result = $this->client->shipments->update($this->orderId, $this->id, $body); - - return ResourceFactory::createFromApiResult($result, new Shipment($this->client)); - } -} diff --git a/src/Resources/ShipmentCollection.php b/src/Resources/ShipmentCollection.php index b87f3453e..028c2ee6e 100644 --- a/src/Resources/ShipmentCollection.php +++ b/src/Resources/ShipmentCollection.php @@ -5,10 +5,7 @@ class ShipmentCollection extends BaseCollection { /** - * @return string + * The name of the collection resource in Mollie's API. */ - public function getCollectionResourceName() - { - return 'shipments'; - } + public static string $collectionName = 'shipments'; } diff --git a/src/Resources/Subscription.php b/src/Resources/Subscription.php index 62d085039..1066f97de 100644 --- a/src/Resources/Subscription.php +++ b/src/Resources/Subscription.php @@ -2,9 +2,13 @@ namespace Mollie\Api\Resources; -use Mollie\Api\MollieApiClient; +use Mollie\Api\Http\Requests\CancelSubscriptionRequest; +use Mollie\Api\Http\Requests\DynamicGetRequest; use Mollie\Api\Types\SubscriptionStatus; +/** + * @property \Mollie\Api\MollieApiClient $connector + */ class Subscription extends BaseResource { /** @@ -110,127 +114,96 @@ class Subscription extends BaseResource public $_links; /** - * @return Subscription * @throws \Mollie\Api\Exceptions\ApiException */ - public function update() + public function update(): ?Subscription { $body = [ - "amount" => $this->amount, - "times" => $this->times, - "startDate" => $this->startDate, - "webhookUrl" => $this->webhookUrl, - "description" => $this->description, - "mandateId" => $this->mandateId, - "metadata" => $this->metadata, - "interval" => $this->interval, + 'amount' => $this->amount, + 'times' => $this->times, + 'startDate' => $this->startDate, + 'webhookUrl' => $this->webhookUrl, + 'description' => $this->description, + 'mandateId' => $this->mandateId, + 'metadata' => $this->metadata, + 'interval' => $this->interval, ]; - $result = $this->client->subscriptions->update($this->customerId, $this->id, $body); - - return ResourceFactory::createFromApiResult($result, new Subscription($this->client)); + return $this->connector->subscriptions->update($this->customerId, $this->id, $body); } /** * Returns whether the Subscription is active or not. - * - * @return bool */ - public function isActive() + public function isActive(): bool { - return $this->status === SubscriptionStatus::STATUS_ACTIVE; + return $this->status === SubscriptionStatus::ACTIVE; } /** * Returns whether the Subscription is pending or not. - * - * @return bool */ - public function isPending() + public function isPending(): bool { - return $this->status === SubscriptionStatus::STATUS_PENDING; + return $this->status === SubscriptionStatus::PENDING; } /** * Returns whether the Subscription is canceled or not. - * - * @return bool */ - public function isCanceled() + public function isCanceled(): bool { - return $this->status === SubscriptionStatus::STATUS_CANCELED; + return $this->status === SubscriptionStatus::CANCELED; } /** * Returns whether the Subscription is suspended or not. - * - * @return bool */ - public function isSuspended() + public function isSuspended(): bool { - return $this->status === SubscriptionStatus::STATUS_SUSPENDED; + return $this->status === SubscriptionStatus::SUSPENDED; } /** * Returns whether the Subscription is completed or not. - * - * @return bool */ - public function isCompleted() + public function isCompleted(): bool { - return $this->status === SubscriptionStatus::STATUS_COMPLETED; + return $this->status === SubscriptionStatus::COMPLETED; } /** * Cancels this subscription * - * @return Subscription * @throws \Mollie\Api\Exceptions\ApiException */ - public function cancel() + public function cancel(): ?Subscription { if (! isset($this->_links->self->href)) { return $this; } - $body = null; - if ($this->client->usesOAuth()) { - $body = json_encode([ - "testmode" => $this->mode === "test" ? true : false, - ]); - } - - $result = $this->client->performHttpCallToFullUrl( - MollieApiClient::HTTP_DELETE, - $this->_links->self->href, - $body - ); - - return ResourceFactory::createFromApiResult($result, new Subscription($this->client)); + return $this + ->connector + ->send((new CancelSubscriptionRequest( + $this->customerId, + $this->id + ))->test($this->mode === 'test')); } /** * Get subscription payments * - * @return \Mollie\Api\Resources\PaymentCollection * @throws \Mollie\Api\Exceptions\ApiException */ - public function payments() + public function payments(): PaymentCollection { if (! isset($this->_links->payments->href)) { - return new PaymentCollection($this->client, 0, null); + return new PaymentCollection($this->connector, $this->response); } - $result = $this->client->performHttpCallToFullUrl( - MollieApiClient::HTTP_GET, - $this->_links->payments->href - ); - - return ResourceFactory::createCursorResourceCollection( - $this->client, - $result->_embedded->payments, - Payment::class, - $result->_links - ); + return $this + ->connector + ->send((new DynamicGetRequest($this->_links->payments->href))->setHydratableResource(PaymentCollection::class)); } } diff --git a/src/Resources/SubscriptionCollection.php b/src/Resources/SubscriptionCollection.php index 848130895..eb0541ec0 100644 --- a/src/Resources/SubscriptionCollection.php +++ b/src/Resources/SubscriptionCollection.php @@ -5,18 +5,12 @@ class SubscriptionCollection extends CursorCollection { /** - * @return string + * The name of the collection resource in Mollie's API. */ - public function getCollectionResourceName() - { - return "subscriptions"; - } + public static string $collectionName = 'subscriptions'; /** - * @return BaseResource + * Resource class name. */ - protected function createResourceObject() - { - return new Subscription($this->client); - } + public static string $resource = Subscription::class; } diff --git a/src/Resources/Terminal.php b/src/Resources/Terminal.php index a2fd3b436..b1c7baf9e 100644 --- a/src/Resources/Terminal.php +++ b/src/Resources/Terminal.php @@ -4,6 +4,9 @@ use Mollie\Api\Types\TerminalStatus; +/** + * @property \Mollie\Api\MollieApiClient $connector + */ class Terminal extends BaseResource { /** @@ -15,6 +18,7 @@ class Terminal extends BaseResource * Id of the terminal (on the Mollie platform). * * @example term_7MgL4wea46qkRcoTZjWEH + * * @var string */ public $id; @@ -23,6 +27,7 @@ class Terminal extends BaseResource * The profile ID this terminal belongs to. * * @example pfl_QkEhN94Ba + * * @var string */ public $profileId; @@ -33,6 +38,7 @@ class Terminal extends BaseResource * active means payments are accepted, and inactive means it is deactivated. * * @example active + * * @var string */ public $status; @@ -62,6 +68,7 @@ class Terminal extends BaseResource * The currency which is set for the terminal, in ISO 4217 format. * * @example EUR + * * @var string */ public $currency; @@ -78,6 +85,7 @@ class Terminal extends BaseResource * The timezone of the terminal. * * @example Europe/Brussels + * * @var string */ public $timezone; @@ -86,6 +94,7 @@ class Terminal extends BaseResource * This will be a full locale provided by the user. * * @example nl_NL + * * @var string */ public $locale; @@ -94,6 +103,7 @@ class Terminal extends BaseResource * UTC datetime the terminal was created, in ISO 8601 format. * * @example "2021-12-25T10:30:54+00:00" + * * @var string */ public $createdAt; @@ -102,6 +112,7 @@ class Terminal extends BaseResource * UTC datetime the terminal was last updated, in ISO 8601 format. * * @example "2021-12-25T10:30:54+00:00" + * * @var string */ public $updatedAt; @@ -111,6 +122,7 @@ class Terminal extends BaseResource * This parameter is omitted if the terminal is not disabled yet. * * @example "2021-12-25T10:30:54+00:00" + * * @var string */ public $disabledAt; @@ -120,6 +132,7 @@ class Terminal extends BaseResource * This parameter is omitted if the terminal is not active yet. * * @example "2021-12-25T10:30:54+00:00" + * * @var string */ public $activatedAt; @@ -131,27 +144,18 @@ class Terminal extends BaseResource */ public $_links; - /** - * @return bool - */ - public function isPending() + public function isPending(): bool { - return $this->status === TerminalStatus::STATUS_PENDING; + return $this->status === TerminalStatus::PENDING; } - /** - * @return bool - */ - public function isActive() + public function isActive(): bool { - return $this->status === TerminalStatus::STATUS_ACTIVE; + return $this->status === TerminalStatus::ACTIVE; } - /** - * @return bool - */ - public function isInactive() + public function isInactive(): bool { - return $this->status === TerminalStatus::STATUS_INACTIVE; + return $this->status === TerminalStatus::INACTIVE; } } diff --git a/src/Resources/TerminalCollection.php b/src/Resources/TerminalCollection.php index af785a6e2..fa78a655f 100644 --- a/src/Resources/TerminalCollection.php +++ b/src/Resources/TerminalCollection.php @@ -5,18 +5,12 @@ class TerminalCollection extends CursorCollection { /** - * @return string + * The name of the collection resource in Mollie's API. */ - public function getCollectionResourceName() - { - return "terminals"; - } + public static string $collectionName = 'terminals'; /** - * @return BaseResource + * Resource class name. */ - protected function createResourceObject() - { - return new Terminal($this->client); - } + public static string $resource = Terminal::class; } diff --git a/src/Resources/WrapperResource.php b/src/Resources/WrapperResource.php new file mode 100644 index 000000000..6446ecc7c --- /dev/null +++ b/src/Resources/WrapperResource.php @@ -0,0 +1,24 @@ +wrapper = $wrapper; + } + + public function getWrapper(): ?string + { + return $this->wrapper; + } +} diff --git a/src/Traits/ComposableFromArray.php b/src/Traits/ComposableFromArray.php new file mode 100644 index 000000000..6ddad919c --- /dev/null +++ b/src/Traits/ComposableFromArray.php @@ -0,0 +1,12 @@ +{$method}(...$parameters); + } + + /** + * Forward a method call to the given object, returning $this if the forwarded call returned itself. + * + * @param mixed $object + * @param string $method + * @param array $parameters + * @return mixed + * + * @throws \BadMethodCallException + */ + protected function forwardDecoratedCallTo($object, $method, $parameters) + { + $result = $this->forwardCallTo($object, $method, $parameters); + + return $result === $object ? $this : $result; + } +} diff --git a/src/Traits/GetAllConstants.php b/src/Traits/GetAllConstants.php new file mode 100644 index 000000000..01e9f57fa --- /dev/null +++ b/src/Traits/GetAllConstants.php @@ -0,0 +1,13 @@ +getConstants()); + } +} diff --git a/src/Traits/HandlesAuthentication.php b/src/Traits/HandlesAuthentication.php new file mode 100644 index 000000000..f97b16958 --- /dev/null +++ b/src/Traits/HandlesAuthentication.php @@ -0,0 +1,42 @@ +authenticator = new ApiKeyAuthenticator($apiKey); + + return $this; + } + + /** + * @param string $accessToken OAuth access token, starting with 'access_' + * + * @throws ApiException + */ + public function setAccessToken(string $accessToken): self + { + $this->authenticator = new AccessTokenAuthenticator($accessToken); + + return $this; + } + + public function getAuthenticator(): ?Authenticator + { + return $this->authenticator; + } +} diff --git a/src/Traits/HandlesDebugging.php b/src/Traits/HandlesDebugging.php new file mode 100644 index 000000000..9cd4bec07 --- /dev/null +++ b/src/Traits/HandlesDebugging.php @@ -0,0 +1,58 @@ +setDebugging(true); + + return $this; + } + + /** + * Disable debugging mode. + * + * @throws \Mollie\Api\Exceptions\HttpAdapterDoesNotSupportDebuggingException + */ + public function disableDebugging(): Connector + { + $this->setDebugging(false); + + return $this; + } + + /** + * Toggle debugging mode. If debugging mode is enabled, the attempted request will be included in the ApiException. + * By default, debugging is disabled to prevent leaking sensitive request data into exception logs. + * + * @throws \Mollie\Api\Exceptions\HttpAdapterDoesNotSupportDebuggingException + */ + public function setDebugging(bool $enable) + { + if (! $this->httpClient instanceof SupportsDebuggingContract) { + throw new HttpAdapterDoesNotSupportDebuggingException( + 'Debugging is not supported by '.get_class($this->httpClient).'.' + ); + } + + if ($enable) { + $this->httpClient->enableDebugging(); + } else { + $this->httpClient->disableDebugging(); + } + } +} diff --git a/src/Traits/HandlesIdempotency.php b/src/Traits/HandlesIdempotency.php new file mode 100644 index 000000000..aa9251cde --- /dev/null +++ b/src/Traits/HandlesIdempotency.php @@ -0,0 +1,80 @@ +idempotencyKey = $key; + + return $this; + } + + /** + * Retrieve the idempotency key. The idempotency key is a unique string ensuring a request to a + * mutating Mollie endpoint is processed only once. Note that the idempotency key gets reset to null after each + * request. + */ + public function getIdempotencyKey(): ?string + { + return $this->idempotencyKey; + } + + public function getIdempotencyKeyGenerator(): ?IdempotencyKeyGeneratorContract + { + return $this->idempotencyKeyGenerator; + } + + /** + * Reset the idempotency key. Note that the idempotency key automatically resets to null after each request. + * + * @return $this + */ + public function resetIdempotencyKey(): self + { + $this->idempotencyKey = null; + + return $this; + } + + /** + * @return $this + */ + public function setIdempotencyKeyGenerator(IdempotencyKeyGeneratorContract $generator): self + { + $this->idempotencyKeyGenerator = $generator; + + return $this; + } + + /** + * @return $this + */ + public function clearIdempotencyKeyGenerator(): self + { + $this->idempotencyKeyGenerator = null; + + return $this; + } +} diff --git a/src/Traits/HandlesTestmode.php b/src/Traits/HandlesTestmode.php new file mode 100644 index 000000000..e7f547afb --- /dev/null +++ b/src/Traits/HandlesTestmode.php @@ -0,0 +1,20 @@ +testmode = $testmode; + + return $this; + } + + public function getTestmode(): ?bool + { + return $this->testmode; + } +} diff --git a/src/Traits/HandlesVersions.php b/src/Traits/HandlesVersions.php new file mode 100644 index 000000000..7f2c15a9b --- /dev/null +++ b/src/Traits/HandlesVersions.php @@ -0,0 +1,38 @@ +addVersionString('Mollie/'.MollieApiClient::CLIENT_VERSION); + $this->addVersionString('PHP/'.phpversion()); + + if ($clientVersion = $this->httpClient->version()) { + $this->addVersionString($clientVersion); + } + } + + /** + * @param string $versionString + */ + public function addVersionString($versionString): self + { + $this->versionStrings[] = str_replace([' ', "\t", "\n", "\r"], '-', $versionString); + + return $this; + } + + public function getVersionStrings(): array + { + return $this->versionStrings; + } +} diff --git a/src/Traits/HasDefaultFactories.php b/src/Traits/HasDefaultFactories.php new file mode 100644 index 000000000..00336a0e9 --- /dev/null +++ b/src/Traits/HasDefaultFactories.php @@ -0,0 +1,27 @@ + BalanceEndpointCollection::class, + 'balanceReports' => BalanceReportEndpointCollection::class, + 'balanceTransactions' => BalanceTransactionEndpointCollection::class, + 'chargebacks' => ChargebackEndpointCollection::class, + 'clients' => ClientEndpointCollection::class, + 'clientLinks' => ClientLinkEndpointCollection::class, + 'customerPayments' => CustomerPaymentsEndpointCollection::class, + 'customers' => CustomerEndpointCollection::class, + 'invoices' => InvoiceEndpointCollection::class, + 'mandates' => MandateEndpointCollection::class, + 'methods' => MethodEndpointCollection::class, + 'methodIssuers' => MethodIssuerEndpointCollection::class, + 'onboarding' => OnboardingEndpointCollection::class, + 'organizationPartners' => OrganizationPartnerEndpointCollection::class, + 'organizations' => OrganizationEndpointCollection::class, + 'payments' => PaymentEndpointCollection::class, + 'paymentRefunds' => PaymentRefundEndpointCollection::class, + 'paymentCaptures' => PaymentCaptureEndpointCollection::class, + 'paymentChargebacks' => PaymentChargebackEndpointCollection::class, + 'paymentLinks' => PaymentLinkEndpointCollection::class, + 'paymentLinkPayments' => PaymentLinkPaymentEndpointCollection::class, + 'paymentRoutes' => PaymentRouteEndpointCollection::class, + 'permissions' => PermissionEndpointCollection::class, + 'profiles' => ProfileEndpointCollection::class, + 'profileMethods' => ProfileMethodEndpointCollection::class, + 'refunds' => RefundEndpointCollection::class, + 'salesInvoices' => SalesInvoiceEndpointCollection::class, + 'sessions' => SessionEndpointCollection::class, + 'settlementCaptures' => SettlementCaptureEndpointCollection::class, + 'settlementChargebacks' => SettlementChargebackEndpointCollection::class, + 'settlementPayments' => SettlementPaymentEndpointCollection::class, + 'settlementRefunds' => SettlementRefundEndpointCollection::class, + 'settlements' => SettlementEndpointCollection::class, + 'subscriptions' => SubscriptionEndpointCollection::class, + 'subscriptionPayments' => SubscriptionPaymentEndpointCollection::class, + 'terminals' => TerminalEndpointCollection::class, + 'wallets' => WalletEndpointCollection::class, + ]; + + foreach ($endpointClasses as $name => $class) { + static::$endpoints[$name] = $class; + } + } + + /** + * @param string $url + */ + public function setApiEndpoint($url): self + { + $this->apiEndpoint = rtrim(trim($url), '/'); + + return $this; + } + + public function getApiEndpoint(): string + { + return $this->apiEndpoint; + } + + /** + * Magic getter to access the endpoints. + * + * + * @return mixed + * + * @throws \Exception + */ + public function __get(string $name) + { + if (isset(static::$endpoints[$name])) { + return new static::$endpoints[$name]($this); + } + + throw new \Exception("Undefined endpoint: $name"); + } +} diff --git a/src/Traits/HasHeaders.php b/src/Traits/HasHeaders.php new file mode 100644 index 000000000..e7c5b8534 --- /dev/null +++ b/src/Traits/HasHeaders.php @@ -0,0 +1,21 @@ +headers ??= new ArrayStore($this->defaultHeaders()); + } + + protected function defaultHeaders(): array + { + return []; + } +} diff --git a/src/Traits/HasJsonPayload.php b/src/Traits/HasJsonPayload.php new file mode 100644 index 000000000..1b25d3e66 --- /dev/null +++ b/src/Traits/HasJsonPayload.php @@ -0,0 +1,20 @@ +body ??= new JsonPayloadRepository($this->defaultPayload()); + } + + protected function defaultPayload(): array + { + return []; + } +} diff --git a/src/Traits/HasMiddleware.php b/src/Traits/HasMiddleware.php new file mode 100644 index 000000000..444c95ed1 --- /dev/null +++ b/src/Traits/HasMiddleware.php @@ -0,0 +1,15 @@ +middleware ??= new Middleware; + } +} diff --git a/src/Traits/HasMode.php b/src/Traits/HasMode.php new file mode 100644 index 000000000..85b44257e --- /dev/null +++ b/src/Traits/HasMode.php @@ -0,0 +1,19 @@ +mode === 'test'; + } + + public function withMode(array $options = []): array + { + return array_merge($options, ['testmode' => $this->isInTestmode()]); + } +} diff --git a/src/Traits/HasQuery.php b/src/Traits/HasQuery.php new file mode 100644 index 000000000..45a632237 --- /dev/null +++ b/src/Traits/HasQuery.php @@ -0,0 +1,21 @@ +queryStore ??= new ArrayStore($this->defaultQuery()); + } + + protected function defaultQuery(): array + { + return []; + } +} diff --git a/src/Traits/HasRequestProperties.php b/src/Traits/HasRequestProperties.php new file mode 100644 index 000000000..8e50e688b --- /dev/null +++ b/src/Traits/HasRequestProperties.php @@ -0,0 +1,9 @@ +response; + } + + public function setResponse(?Response $response): self + { + $this->response = $response; + + return $this; + } + + public function getPendingRequest(): PendingRequest + { + return $this->response->getPendingRequest(); + } +} diff --git a/src/Traits/Initializable.php b/src/Traits/Initializable.php new file mode 100644 index 000000000..b4610978e --- /dev/null +++ b/src/Traits/Initializable.php @@ -0,0 +1,22 @@ +getShortName(); + + if (method_exists($this, $method)) { + $this->{$method}(); + } + } + } +} diff --git a/src/Traits/IsDebuggableAdapter.php b/src/Traits/IsDebuggableAdapter.php new file mode 100644 index 000000000..d57c1469a --- /dev/null +++ b/src/Traits/IsDebuggableAdapter.php @@ -0,0 +1,47 @@ +debug = true; + + return $this; + } + + /** + * Disable debugging. If debugging mode is enabled, the request will + * be included in the ApiException. By default, debugging is disabled to prevent + * sensitive request data from leaking into exception logs. + */ + public function disableDebugging(): HttpAdapterContract + { + $this->debug = false; + + return $this; + } + + /** + * Whether debugging is enabled. If debugging mode is enabled, the request will + * be included in the ApiException. By default, debugging is disabled to prevent + * sensitive request data from leaking into exception logs. + */ + public function debuggingIsActive(): bool + { + return $this->debug; + } +} diff --git a/src/Traits/IsIteratableRequest.php b/src/Traits/IsIteratableRequest.php new file mode 100644 index 000000000..01ebad43b --- /dev/null +++ b/src/Traits/IsIteratableRequest.php @@ -0,0 +1,39 @@ +iteratorEnabled; + } + + public function iteratesBackwards(): bool + { + return $this->iterateBackwards; + } + + public function useIterator(): self + { + $this->iteratorEnabled = true; + + return $this; + } + + public function setIterationDirection(bool $iterateBackwards = false): self + { + $this->iterateBackwards = $iterateBackwards; + + return $this; + } +} diff --git a/src/Traits/ManagesPsrRequests.php b/src/Traits/ManagesPsrRequests.php new file mode 100644 index 000000000..3ed95bda0 --- /dev/null +++ b/src/Traits/ManagesPsrRequests.php @@ -0,0 +1,60 @@ +factoryCollection; + + $request = $factories->requestFactory->createRequest( + $this->method(), + $this->getUri(), + ); + + foreach ($this->headers()->all() as $headerName => $headerValue) { + $request = $request->withHeader($headerName, $headerValue); + } + + if ($this->payload() instanceof PayloadRepository) { + $request = $request->withBody($this->payload()->toStream($factories->streamFactory)); + } + + return $request; + } + + public function getUri(): UriInterface + { + $uri = $this + ->factoryCollection + ->uriFactory + ->createUri($this->url()); + + $existingQuery = Url::parseQuery($uri->getQuery()); + + return $uri->withQuery( + http_build_query(array_merge($existingQuery, $this->query()->all())) + ); + } + + /** + * Get the factory collection + */ + public function getFactoryCollection(): Factories + { + return $this->factoryCollection; + } +} diff --git a/src/Traits/SendsRequests.php b/src/Traits/SendsRequests.php new file mode 100644 index 000000000..62b3cf4d8 --- /dev/null +++ b/src/Traits/SendsRequests.php @@ -0,0 +1,24 @@ +executeRequestHandlers(); + + return $pendingRequest->executeResponseHandlers( + $this->httpClient->sendRequest($pendingRequest) + ); + } +} diff --git a/src/Types/ApprovalPrompt.php b/src/Types/ApprovalPrompt.php index 3aff39844..f9be2c843 100644 --- a/src/Types/ApprovalPrompt.php +++ b/src/Types/ApprovalPrompt.php @@ -4,11 +4,11 @@ class ApprovalPrompt { - const AUTO = "auto"; + const AUTO = 'auto'; /** * Force showing the consent screen to the merchant, even when it is not necessary. * Note that already active authorizations will be revoked when the user creates the new authorization. */ - const FORCE = "force"; + const FORCE = 'force'; } diff --git a/src/Types/BalanceTransferFrequency.php b/src/Types/BalanceTransferFrequency.php index f949ae2c2..94c1bf385 100644 --- a/src/Types/BalanceTransferFrequency.php +++ b/src/Types/BalanceTransferFrequency.php @@ -4,15 +4,25 @@ class BalanceTransferFrequency { - const DAILY = "daily"; - const TWICE_A_WEEK = "twice-a-week"; - const EVERY_MONDAY = "every-monday"; - const EVERY_TUESDAY = "every-tuesday"; - const EVERY_WEDNESDAY = "every-wednesday"; - const EVERY_THURSDAY = "every-thursday"; - const EVERY_FRIDAY = "every-friday"; - const EVERY_SATURDAY = "every-saturday"; - const EVERY_SUNDAY = "every-sunday"; - const TWICE_A_MONTH = "twice-a-month"; - const NEVER = "never"; + const DAILY = 'daily'; + + const TWICE_A_WEEK = 'twice-a-week'; + + const EVERY_MONDAY = 'every-monday'; + + const EVERY_TUESDAY = 'every-tuesday'; + + const EVERY_WEDNESDAY = 'every-wednesday'; + + const EVERY_THURSDAY = 'every-thursday'; + + const EVERY_FRIDAY = 'every-friday'; + + const EVERY_SATURDAY = 'every-saturday'; + + const EVERY_SUNDAY = 'every-sunday'; + + const TWICE_A_MONTH = 'twice-a-month'; + + const NEVER = 'never'; } diff --git a/src/Types/BusinessCategory.php b/src/Types/BusinessCategory.php new file mode 100644 index 000000000..9bd847374 --- /dev/null +++ b/src/Types/BusinessCategory.php @@ -0,0 +1,302 @@ + $key + * @param mixed $value + * + * @example includes(['includes' => ['payment']], 'includes', 'payment') => true + * @example includes(['includes' => ['refund']], 'includes', 'payment') => false + * @example includes(['includes' => ['payment' => 'foo']], 'includes.payment', 'foo') => true + */ + public static function includes(array $array, $key, $value): bool + { + $keys = (array) $key; + + foreach ($keys as $k) { + if (Arr::has($array, $k) && in_array($value, Arr::wrap(Arr::get($array, $k, [])))) { + return true; + } + } + + return false; + } + + /** + * Resolve the values of the given array. + * + * @param mixed $values + */ + public static function resolve($values): array + { + return DataCollection::wrap($values) + ->map(function ($value) { + if ($value instanceof Resolvable) { + return static::resolve($value->toArray()); + } + + if ($value instanceof Arrayable) { + return $value->toArray(); + } + + if ($value instanceof Stringable) { + return $value->__toString(); + } + + if ($value instanceof DateTimeInterface) { + return $value->format('Y-m-d'); + } + + return $value; + }) + ->filter() + ->toArray(); + } +} diff --git a/src/Utils/Factories.php b/src/Utils/Factories.php new file mode 100644 index 000000000..310d89379 --- /dev/null +++ b/src/Utils/Factories.php @@ -0,0 +1,31 @@ +requestFactory = $requestFactory; + $this->responseFactory = $responseFactory; + $this->streamFactory = $streamFactory; + $this->uriFactory = $uriFactory; + } +} diff --git a/src/Utils/Url.php b/src/Utils/Url.php new file mode 100644 index 000000000..965f28a7c --- /dev/null +++ b/src/Utils/Url.php @@ -0,0 +1,53 @@ + + */ + public static function parseQuery(string $query): array + { + if ($query === '') { + return []; + } + + $parameters = []; + + foreach (explode('&', $query) as $parameter) { + $name = urldecode((string) strtok($parameter, '=')); + $value = urldecode((string) strtok('=')); + + if (! $name || str_starts_with($parameter, '=')) { + continue; + } + + $parameters[$name] = $value; + } + + return $parameters; + } +} diff --git a/src/Utils/Utility.php b/src/Utils/Utility.php new file mode 100644 index 000000000..9176b5cb0 --- /dev/null +++ b/src/Utils/Utility.php @@ -0,0 +1,115 @@ + + */ + public static function classUsesRecursive($class): array + { + if (is_object($class)) { + $class = get_class($class); + } + + $results = []; + + foreach (array_reverse(class_parents($class)) + [$class => $class] as $class) { + $results += static::traitUsesRecursive($class); + } + + return array_unique($results); + } + + /** + * Returns all traits used by a trait and its traits. + * + * @param class-string $trait + * @return array + */ + public static function traitUsesRecursive(string $trait): array + { + /** @var array $traits */ + $traits = class_uses($trait) ?: []; + + foreach ($traits as $trait) { + $traits += static::traitUsesRecursive($trait); + } + + return $traits; + } + + /** + * Get the properties of a class. + * + * @param string|class-string $class + * @param int $flag + * @return ReflectionProperty[] + */ + public static function getProperties($class, $flag = ReflectionProperty::IS_PUBLIC | ReflectionProperty::IS_PROTECTED | ReflectionProperty::IS_PRIVATE): array + { + $reflection = new ReflectionClass($class); + + return $reflection->getProperties($flag); + } + + /** + * Filter out the properties that are not part of the given class. + * + * @param string|class-string $class + */ + public static function filterByProperties($class, array $array): array + { + $properties = array_map( + fn (ReflectionProperty $prop) => $prop->getName(), + static::getProperties($class) + ); + + return array_filter( + $array, + fn ($key) => ! in_array($key, $properties, true), + ARRAY_FILTER_USE_KEY + ); + } + + /** + * Compose a value to a new form if it is truthy. + * + * @param mixed $value + * @param string|callable $composable + * @param mixed $default + * @return mixed + */ + public static function compose($value, $composable, $default = null) + { + // If the value is an instance of the composable class, return it. + if (is_string($composable) && $value instanceof $composable) { + return $value; + } + + $composable = is_string($composable) + ? fn ($value) => new $composable($value) + : $composable; + + return (bool) $value ? $composable($value) : $default; + } + + /** + * Extract a boolean value if not already a boolean. + * + * @param mixed $value + */ + public static function extractBool($value, string $key, bool $default = false): bool + { + return is_bool($value) + ? $value + : Arr::get($value, $key, $default); + } +} diff --git a/tests/Mollie/API/CompatibilityCheckerTest.php b/tests/CompatibilityCheckerTest.php similarity index 68% rename from tests/Mollie/API/CompatibilityCheckerTest.php rename to tests/CompatibilityCheckerTest.php index ede16fa8b..8520753dc 100644 --- a/tests/Mollie/API/CompatibilityCheckerTest.php +++ b/tests/CompatibilityCheckerTest.php @@ -1,7 +1,8 @@ checker = $this->getMockBuilder(CompatibilityChecker::class) ->setMethods([ - "satisfiesPhpVersion", - "satisfiesJsonExtension", + 'satisfiesPhpVersion', + 'satisfiesJsonExtension', ]) ->getMock(); } - public function testCheckCompatibilityThrowsExceptionOnPhpVersion() + public function test_check_compatibility_throws_exception_on_php_version() { $this->expectException(\Mollie\Api\Exceptions\IncompatiblePlatform::class); $this->checker->expects($this->once()) - ->method("satisfiesPhpVersion") + ->method('satisfiesPhpVersion') ->will($this->returnValue(false)); // Fail $this->checker->expects($this->never()) - ->method("satisfiesJsonExtension"); + ->method('satisfiesJsonExtension'); $this->checker->checkCompatibility(); } - public function testCheckCompatibilityThrowsExceptionOnJsonExtension() + public function test_check_compatibility_throws_exception_on_json_extension() { $this->expectException(\Mollie\Api\Exceptions\IncompatiblePlatform::class); $this->checker->expects($this->once()) - ->method("satisfiesPhpVersion") + ->method('satisfiesPhpVersion') ->will($this->returnValue(true)); $this->checker->expects($this->once()) - ->method("satisfiesJsonExtension") + ->method('satisfiesJsonExtension') ->will($this->returnValue(false)); // Fail $this->checker->checkCompatibility(); diff --git a/tests/EndpointCollection/BalanceEndpointCollectionTest.php b/tests/EndpointCollection/BalanceEndpointCollectionTest.php new file mode 100644 index 000000000..6d21d32df --- /dev/null +++ b/tests/EndpointCollection/BalanceEndpointCollectionTest.php @@ -0,0 +1,133 @@ + MockResponse::ok('balance'), + ]); + + /** @var Balance $balance */ + $balance = $client->balances->get('bal_gVMhHKqSSRYJyPsuoPNFH'); + + $this->assertBalance( + $balance, + 'bal_gVMhHKqSSRYJyPsuoPNFH', + ); + } + + /** @test */ + public function primary() + { + $client = new MockMollieClient([ + GetBalanceRequest::class => MockResponse::ok('balance'), + ]); + + /** @var Balance $balance */ + $balance = $client->balances->primary(); + + $this->assertBalance( + $balance, + 'bal_gVMhHKqSSRYJyPsuoPNFH', + ); + } + + /** @test */ + public function page() + { + $client = new MockMollieClient([ + GetPaginatedBalanceRequest::class => MockResponse::ok('balance-list'), + ]); + + /** @var BalanceCollection $balances */ + $balances = $client->balances->page(); + + $this->assertInstanceOf(BalanceCollection::class, $balances); + $this->assertEquals(2, $balances->count()); + $this->assertCount(2, $balances); + + $this->assertLinkObject( + '...', + 'text/html', + $balances->_links->documentation + ); + + $this->assertLinkObject( + 'https://api.mollie.com/v2/balances?limit=5', + 'application/hal+json', + $balances->_links->self + ); + + $this->assertLinkObject( + '...', + 'application/hal+json', + $balances->_links->next + ); + + $this->assertBalance( + $balances[0], + 'bal_gVMhHKqSSRYJyPsuoPNFH', + ); + $this->assertBalance( + $balances[1], + 'bal_gVMhHKqSSRYJyPsuoPABC', + ); + } + + /** @test */ + public function iterate() + { + $client = new MockMollieClient([ + GetPaginatedBalanceRequest::class => MockResponse::ok('balance-list'), + DynamicGetRequest::class => MockResponse::ok('empty-list', 'balances'), + ]); + + foreach ($client->balances->iterator() as $balance) { + $this->assertInstanceOf(Balance::class, $balance); + } + } + + /** + * @return void + */ + protected function assertBalance( + Balance $balance, + string $balanceId + ) { + $this->assertInstanceOf(Balance::class, $balance); + $this->assertEquals('balance', $balance->resource); + $this->assertEquals($balanceId, $balance->id); + + $this->assertNotEmpty($balance->mode); + $this->assertNotEmpty($balance->createdAt); + $this->assertNotEmpty($balance->currency); + $this->assertNotNull($balance->availableAmount); + $this->assertNotNull($balance->incomingAmount); + $this->assertNotNull($balance->outgoingAmount); + $this->assertNotEmpty($balance->transferFrequency); + $this->assertNotNull($balance->transferThreshold); + $this->assertNotEmpty($balance->transferReference); + $this->assertNotNull($balance->transferDestination); + $this->assertNotNull($balance->_links->self); + } +} diff --git a/tests/EndpointCollection/BalanceReportEndpointCollectionTest.php b/tests/EndpointCollection/BalanceReportEndpointCollectionTest.php new file mode 100644 index 000000000..7fd8fb7a3 --- /dev/null +++ b/tests/EndpointCollection/BalanceReportEndpointCollectionTest.php @@ -0,0 +1,90 @@ + MockResponse::ok('balance-report', 'bal_gVMhHKqSSRYJyPsuoPNFH'), + ]); + + /** @var BalanceReport $report */ + $report = $client->balanceReports->getForId('bal_gVMhHKqSSRYJyPsuoPNFH', [ + 'from' => '2021-01-01', + 'until' => '2021-02-01', + 'grouping' => 'transaction-categories', + ]); + + $this->assertBalanceReport($report, 'bal_gVMhHKqSSRYJyPsuoPNFH'); + } + + /** @test */ + public function get_for_balance() + { + $client = new MockMollieClient([ + GetBalanceReportRequest::class => MockResponse::ok('balance-report', 'bal_gVMhHKqSSRYJyPsuoPNFH'), + ]); + + $balance = new Balance($client); + $balance->id = 'bal_gVMhHKqSSRYJyPsuoPNFH'; + + /** @var BalanceReport $report */ + $report = $client->balanceReports->getFor($balance, [ + 'from' => '2021-01-01', + 'until' => '2021-02-01', + 'grouping' => 'transaction-categories', + ]); + + $this->assertBalanceReport($report, 'bal_gVMhHKqSSRYJyPsuoPNFH'); + } + + /** @test */ + public function get_for_primary() + { + $client = new MockMollieClient([ + GetBalanceReportRequest::class => MockResponse::ok('balance-report', 'bal_primary'), + ]); + + /** @var BalanceReport $report */ + $report = $client->balanceReports->getForPrimary([ + 'from' => '2024-01-01', + 'until' => '2024-01-31', + 'grouping' => 'transaction-categories', + ]); + + $this->assertBalanceReport($report, 'bal_primary'); + } + + protected function assertBalanceReport(BalanceReport $report, string $balanceId) + { + $this->assertInstanceOf(BalanceReport::class, $report); + $this->assertEquals('balance-report', $report->resource); + $this->assertEquals($balanceId, $report->balanceId); + $this->assertNotEmpty($report->timeZone); + $this->assertNotEmpty($report->from); + $this->assertNotEmpty($report->until); + $this->assertNotEmpty($report->grouping); + + $this->assertNotNull($report->totals->open->available->amount); + $this->assertNotNull($report->totals->open->pending->amount); + $this->assertNotNull($report->totals->payments->immediatelyAvailable->amount); + $this->assertNotNull($report->totals->payments->pending->amount); + } +} diff --git a/tests/EndpointCollection/BalanceTransactionEndpointCollectionTest.php b/tests/EndpointCollection/BalanceTransactionEndpointCollectionTest.php new file mode 100644 index 000000000..2a773362f --- /dev/null +++ b/tests/EndpointCollection/BalanceTransactionEndpointCollectionTest.php @@ -0,0 +1,64 @@ + MockResponse::ok('balance-transactions'), + ]); + + $balance = new Balance($client); + $balance->id = 'bal_gVMhHKqSSRYJyPsuoPNFH'; + + /** @var BalanceTransactionCollection $transactions */ + $transactions = $client->balanceTransactions->pageFor($balance); + + $this->assertInstanceOf(BalanceTransactionCollection::class, $transactions); + $this->assertGreaterThan(0, $transactions->count()); + + foreach ($transactions as $transaction) { + $this->assertBalanceTransaction($transaction); + } + } + + /** @test */ + public function iterator_for() + { + $client = new MockMollieClient([ + GetPaginatedBalanceTransactionRequest::class => MockResponse::ok('balance-transactions'), + DynamicGetRequest::class => MockResponse::ok('empty-list', 'balance_transactions'), + ]); + + $balance = new Balance($client); + $balance->id = 'bal_gVMhHKqSSRYJyPsuoPNFH'; + + foreach ($client->balanceTransactions->iteratorFor($balance) as $transaction) { + $this->assertBalanceTransaction($transaction); + } + } + + protected function assertBalanceTransaction(BalanceTransaction $transaction) + { + $this->assertInstanceOf(BalanceTransaction::class, $transaction); + $this->assertEquals('balance_transaction', $transaction->resource); + $this->assertNotEmpty($transaction->id); + $this->assertNotEmpty($transaction->type); + $this->assertNotEmpty($transaction->resultAmount); + $this->assertNotEmpty($transaction->initialAmount); + $this->assertNotEmpty($transaction->deductions); + $this->assertNotEmpty($transaction->context); + } +} diff --git a/tests/EndpointCollection/ChargebackEndpointCollectionTest.php b/tests/EndpointCollection/ChargebackEndpointCollectionTest.php new file mode 100644 index 000000000..4a0c896b2 --- /dev/null +++ b/tests/EndpointCollection/ChargebackEndpointCollectionTest.php @@ -0,0 +1,56 @@ + MockResponse::ok('chargeback-list'), + ]); + + /** @var ChargebackCollection $chargebacks */ + $chargebacks = $client->chargebacks->page(); + + $this->assertInstanceOf(ChargebackCollection::class, $chargebacks); + $this->assertGreaterThan(0, $chargebacks->count()); + + foreach ($chargebacks as $chargeback) { + $this->assertChargeback($chargeback); + } + } + + /** @test */ + public function iterator() + { + $client = new MockMollieClient([ + GetPaginatedChargebacksRequest::class => MockResponse::ok('chargeback-list'), + DynamicGetRequest::class => MockResponse::ok('empty-list', 'chargebacks'), + ]); + + foreach ($client->chargebacks->iterator() as $chargeback) { + $this->assertChargeback($chargeback); + } + } + + protected function assertChargeback(Chargeback $chargeback) + { + $this->assertInstanceOf(Chargeback::class, $chargeback); + $this->assertEquals('chargeback', $chargeback->resource); + $this->assertNotEmpty($chargeback->id); + $this->assertNotEmpty($chargeback->amount); + $this->assertNotEmpty($chargeback->settlementAmount); + $this->assertNotEmpty($chargeback->createdAt); + $this->assertNotEmpty($chargeback->paymentId); + } +} diff --git a/tests/EndpointCollection/ClientEndpointCollectionTest.php b/tests/EndpointCollection/ClientEndpointCollectionTest.php new file mode 100644 index 000000000..d6d2cbe11 --- /dev/null +++ b/tests/EndpointCollection/ClientEndpointCollectionTest.php @@ -0,0 +1,68 @@ + MockResponse::ok('client'), + ]); + + /** @var Client $clientResource */ + $clientResource = $client->clients->get('org_12345678'); + + $this->assertClient($clientResource); + } + + /** @test */ + public function page() + { + $client = new MockMollieClient([ + GetPaginatedClientRequest::class => MockResponse::ok('client-list'), + ]); + + /** @var ClientCollection $clients */ + $clients = $client->clients->page(); + + $this->assertInstanceOf(ClientCollection::class, $clients); + $this->assertGreaterThan(0, $clients->count()); + + foreach ($clients as $clientResource) { + $this->assertClient($clientResource); + } + } + + /** @test */ + public function iterator() + { + $client = new MockMollieClient([ + GetPaginatedClientRequest::class => MockResponse::ok('client-list'), + DynamicGetRequest::class => MockResponse::ok('empty-list', 'clients'), + ]); + + foreach ($client->clients->iterator() as $clientResource) { + $this->assertClient($clientResource); + } + } + + protected function assertClient(Client $client) + { + $this->assertInstanceOf(Client::class, $client); + $this->assertEquals('client', $client->resource); + $this->assertNotEmpty($client->id); + $this->assertNotEmpty($client->organizationCreatedAt); + $this->assertNotEmpty($client->_links); + } +} diff --git a/tests/EndpointCollection/ClientLinkEndpointCollectionTest.php b/tests/EndpointCollection/ClientLinkEndpointCollectionTest.php new file mode 100644 index 000000000..5ee8aec38 --- /dev/null +++ b/tests/EndpointCollection/ClientLinkEndpointCollectionTest.php @@ -0,0 +1,35 @@ + MockResponse::created('client-link'), + ]); + + /** @var ClientLink $clientLink */ + $clientLink = $client->clientLinks->create(new CreateClientLinkPayload( + new Owner('test@example.com', 'John', 'Doe'), + 'Test Client Link', + new OwnerAddress('NL'), + )); + + $this->assertInstanceOf(ClientLink::class, $clientLink); + $this->assertEquals('client-link', $clientLink->resource); + $this->assertNotEmpty($clientLink->id); + $this->assertNotEmpty($clientLink->_links); + } +} diff --git a/tests/EndpointCollection/CustomerEndpointCollectionTest.php b/tests/EndpointCollection/CustomerEndpointCollectionTest.php new file mode 100644 index 000000000..98498f213 --- /dev/null +++ b/tests/EndpointCollection/CustomerEndpointCollectionTest.php @@ -0,0 +1,119 @@ + MockResponse::created('customer'), + ]); + + /** @var Customer $customer */ + $customer = $client->customers->create([ + 'name' => 'John Doe', + 'email' => 'john@example.org', + ]); + + $this->assertCustomer($customer); + } + + /** @test */ + public function get() + { + $client = new MockMollieClient([ + GetCustomerRequest::class => MockResponse::ok('customer'), + ]); + + /** @var Customer $customer */ + $customer = $client->customers->get('cst_kEn1PlbGa'); + + $this->assertCustomer($customer); + } + + /** @test */ + public function update() + { + $client = new MockMollieClient([ + UpdateCustomerRequest::class => MockResponse::ok('customer'), + ]); + + /** @var Customer $customer */ + $customer = $client->customers->update('cst_kEn1PlbGa', [ + 'name' => 'Updated Name', + 'email' => 'updated@example.org', + ]); + + $this->assertCustomer($customer); + } + + /** @test */ + public function delete() + { + $client = new MockMollieClient([ + DeleteCustomerRequest::class => MockResponse::noContent(), + ]); + + $client->customers->delete('cst_kEn1PlbGa'); + + // Test passes if no exception is thrown + $this->assertTrue(true); + } + + /** @test */ + public function page() + { + $client = new MockMollieClient([ + GetPaginatedCustomerRequest::class => MockResponse::ok('customer-list'), + ]); + + /** @var CustomerCollection $customers */ + $customers = $client->customers->page(); + + $this->assertInstanceOf(CustomerCollection::class, $customers); + $this->assertGreaterThan(0, $customers->count()); + + foreach ($customers as $customer) { + $this->assertCustomer($customer); + } + } + + /** @test */ + public function iterator() + { + $client = new MockMollieClient([ + GetPaginatedCustomerRequest::class => MockResponse::ok('customer-list'), + DynamicGetRequest::class => MockResponse::ok('empty-list', 'customers'), + ]); + + foreach ($client->customers->iterator() as $customer) { + $this->assertCustomer($customer); + } + } + + protected function assertCustomer(Customer $customer) + { + $this->assertInstanceOf(Customer::class, $customer); + $this->assertEquals('customer', $customer->resource); + $this->assertNotEmpty($customer->id); + $this->assertNotEmpty($customer->mode); + $this->assertNotEmpty($customer->name); + $this->assertNotEmpty($customer->email); + $this->assertNotEmpty($customer->createdAt); + $this->assertNotEmpty($customer->_links); + } +} diff --git a/tests/EndpointCollection/CustomerPaymentsEndpointCollectionTest.php b/tests/EndpointCollection/CustomerPaymentsEndpointCollectionTest.php new file mode 100644 index 000000000..36cfb9c31 --- /dev/null +++ b/tests/EndpointCollection/CustomerPaymentsEndpointCollectionTest.php @@ -0,0 +1,91 @@ + MockResponse::created('payment'), + ]); + + $customer = new Customer($client); + $customer->id = 'cst_kEn1PlbGa'; + + /** @var Payment $payment */ + $payment = $client->customerPayments->createFor($customer, new CreatePaymentPayload( + 'Test payment', + new Money('10.00', 'EUR'), + 'https://example.org/redirect', + )); + + $this->assertPayment($payment); + } + + /** @test */ + public function page_for() + { + $client = new MockMollieClient([ + GetPaginatedCustomerPaymentsRequest::class => MockResponse::ok('payment-list'), + ]); + + $customer = new Customer($client); + $customer->id = 'cst_kEn1PlbGa'; + + /** @var PaymentCollection $payments */ + $payments = $client->customerPayments->pageFor($customer); + + $this->assertInstanceOf(PaymentCollection::class, $payments); + $this->assertGreaterThan(0, $payments->count()); + + foreach ($payments as $payment) { + $this->assertPayment($payment); + } + } + + /** @test */ + public function iterator_for() + { + $client = new MockMollieClient([ + GetPaginatedCustomerPaymentsRequest::class => MockResponse::ok('payment-list'), + DynamicGetRequest::class => MockResponse::ok('empty-list', 'payments'), + ]); + + $customer = new Customer($client); + $customer->id = 'cst_kEn1PlbGa'; + + foreach ($client->customerPayments->iteratorFor($customer) as $payment) { + $this->assertPayment($payment); + } + } + + protected function assertPayment(Payment $payment) + { + $this->assertInstanceOf(Payment::class, $payment); + $this->assertEquals('payment', $payment->resource); + $this->assertNotEmpty($payment->id); + $this->assertNotEmpty($payment->mode); + $this->assertNotEmpty($payment->createdAt); + $this->assertNotEmpty($payment->status); + $this->assertNotEmpty($payment->amount); + $this->assertNotEmpty($payment->description); + $this->assertNotEmpty($payment->method); + $this->assertNotEmpty($payment->metadata); + $this->assertNotEmpty($payment->profileId); + $this->assertNotEmpty($payment->_links); + } +} diff --git a/tests/EndpointCollection/InvoiceEndpointCollectionTest.php b/tests/EndpointCollection/InvoiceEndpointCollectionTest.php new file mode 100644 index 000000000..359b13ca6 --- /dev/null +++ b/tests/EndpointCollection/InvoiceEndpointCollectionTest.php @@ -0,0 +1,75 @@ + MockResponse::ok('invoice'), + ]); + + /** @var Invoice $invoice */ + $invoice = $client->invoices->get('inv_xBEbP9rvAq'); + + $this->assertInvoice($invoice); + } + + /** @test */ + public function page() + { + $client = new MockMollieClient([ + GetPaginatedInvoiceRequest::class => MockResponse::ok('invoice-list'), + ]); + + /** @var InvoiceCollection $invoices */ + $invoices = $client->invoices->page(); + + $this->assertInstanceOf(InvoiceCollection::class, $invoices); + $this->assertEquals(1, $invoices->count()); + $this->assertCount(1, $invoices); + + $this->assertInvoice($invoices[0]); + } + + /** @test */ + public function iterator() + { + $client = new MockMollieClient([ + GetPaginatedInvoiceRequest::class => MockResponse::ok('invoice-list'), + DynamicGetRequest::class => MockResponse::ok('empty-list', 'invoices'), + ]); + + foreach ($client->invoices->iterator() as $invoice) { + $this->assertInstanceOf(Invoice::class, $invoice); + $this->assertInvoice($invoice); + } + } + + protected function assertInvoice(Invoice $invoice) + { + $this->assertInstanceOf(Invoice::class, $invoice); + $this->assertEquals('invoice', $invoice->resource); + $this->assertEquals('2023.10000', $invoice->reference); + $this->assertEquals('NL001234567B01', $invoice->vatNumber); + $this->assertEquals('open', $invoice->status); + $this->assertEquals('45.00', $invoice->netAmount->value); + $this->assertEquals('EUR', $invoice->netAmount->currency); + $this->assertEquals('9.45', $invoice->vatAmount->value); + $this->assertEquals('54.45', $invoice->grossAmount->value); + $this->assertNotEmpty($invoice->lines); + $this->assertEquals('2023-09-01', $invoice->issuedAt); + $this->assertEquals('2023-09-14', $invoice->dueAt); + } +} diff --git a/tests/EndpointCollection/MandateEndpointCollectionTest.php b/tests/EndpointCollection/MandateEndpointCollectionTest.php new file mode 100644 index 000000000..4423d780a --- /dev/null +++ b/tests/EndpointCollection/MandateEndpointCollectionTest.php @@ -0,0 +1,108 @@ + MockResponse::created('mandate'), + ]); + + $customer = new Customer($client); + $customer->id = 'cst_4qqhO89gsT'; + + /** @var Mandate $mandate */ + $mandate = $client->mandates->createFor($customer, new CreateMandatePayload( + 'directdebit', + 'John Doe', + 'NL55INGB0000000000', + 'INGBNL2A', + 'john.doe@example.com', + new DateTimeImmutable('2023-05-07'), + 'EXAMPLE-CORP-MD13804', + )); + + $this->assertMandate($mandate); + } + + /** @test */ + public function get_for() + { + $client = new MockMollieClient([ + GetMandateRequest::class => MockResponse::ok('mandate'), + ]); + + $customer = new Customer($client); + $customer->id = 'cst_4qqhO89gsT'; + + /** @var Mandate $mandate */ + $mandate = $client->mandates->getFor($customer, 'mdt_h3gAaD5zP'); + + $this->assertMandate($mandate); + } + + /** @test */ + public function revoke_for() + { + $client = new MockMollieClient([ + RevokeMandateRequest::class => MockResponse::noContent(), + ]); + + $customer = new Customer($client); + $customer->id = 'cst_4qqhO89gsT'; + + $client->mandates->revokeFor($customer, 'mdt_h3gAaD5zP'); + + // Test passes if no exception is thrown + $this->assertTrue(true); + } + + /** @test */ + public function page_for() + { + $client = new MockMollieClient([ + GetPaginatedMandateRequest::class => MockResponse::ok('mandate-list'), + ]); + + $customer = new Customer($client); + $customer->id = 'cst_4qqhO89gsT'; + + /** @var MandateCollection $mandates */ + $mandates = $client->mandates->pageFor($customer); + + $this->assertInstanceOf(MandateCollection::class, $mandates); + $this->assertEquals(1, $mandates->count()); + $this->assertCount(1, $mandates); + + $this->assertMandate($mandates[0]); + } + + protected function assertMandate(Mandate $mandate) + { + $this->assertInstanceOf(Mandate::class, $mandate); + $this->assertEquals('mandate', $mandate->resource); + $this->assertEquals('live', $mandate->mode); + $this->assertEquals('valid', $mandate->status); + $this->assertEquals('directdebit', $mandate->method); + $this->assertEquals('EXAMPLE-CORP-MD13804', $mandate->mandateReference); + $this->assertEquals('2023-05-07', $mandate->signatureDate); + $this->assertEquals('cst_4qqhO89gsT', $mandate->customerId); + $this->assertNotEmpty($mandate->createdAt); + } +} diff --git a/tests/EndpointCollection/MethodEndpointCollectionTest.php b/tests/EndpointCollection/MethodEndpointCollectionTest.php new file mode 100644 index 000000000..84c47a179 --- /dev/null +++ b/tests/EndpointCollection/MethodEndpointCollectionTest.php @@ -0,0 +1,77 @@ + MockResponse::ok('method', 'ideal'), + ]); + + /** @var Method $method */ + $method = $client->methods->get('ideal'); + + $this->assertMethod($method); + } + + /** @test */ + public function all() + { + $client = new MockMollieClient([ + GetAllMethodsRequest::class => MockResponse::ok('method-list'), + ]); + + /** @var MethodCollection $methods */ + $methods = $client->methods->all(); + + $this->assertInstanceOf(MethodCollection::class, $methods); + $this->assertEquals(2, $methods->count()); + $this->assertCount(2, $methods); + + foreach ($methods as $method) { + $this->assertInstanceOf(Method::class, $method); + $this->assertNotEmpty($method->id); + $this->assertNotEmpty($method->description); + $this->assertNotEmpty($method->status); + } + } + + /** @test */ + public function all_enabled() + { + $client = new MockMollieClient([ + GetEnabledMethodsRequest::class => MockResponse::ok('method-list'), + ]); + + /** @var MethodCollection $methods */ + $methods = $client->methods->allEnabled(); + + $this->assertInstanceOf(MethodCollection::class, $methods); + $this->assertEquals(2, $methods->count()); + $this->assertCount(2, $methods); + } + + protected function assertMethod(Method $method) + { + $this->assertInstanceOf(Method::class, $method); + $this->assertEquals('method', $method->resource); + $this->assertEquals('iDEAL', $method->description); + $this->assertEquals('0.01', $method->minimumAmount->value); + $this->assertEquals('EUR', $method->minimumAmount->currency); + $this->assertEquals('50000.00', $method->maximumAmount->value); + $this->assertEquals('activated', $method->status); + $this->assertNotEmpty($method->image); + } +} diff --git a/tests/EndpointCollection/MethodIssuerEndpointCollectionTest.php b/tests/EndpointCollection/MethodIssuerEndpointCollectionTest.php new file mode 100644 index 000000000..3eac5e94b --- /dev/null +++ b/tests/EndpointCollection/MethodIssuerEndpointCollectionTest.php @@ -0,0 +1,58 @@ + MockResponse::ok('issuer'), + ]); + + /** @var Issuer $issuer */ + $issuer = $client->methodIssuers->enable( + 'pfl_v9hTwCvYqw', + 'ideal', + 'ideal_INGBNL2A', + 'ctr_123xyz' + ); + + $this->assertIssuer($issuer); + } + + /** @test */ + public function disable() + { + $client = new MockMollieClient([ + DisableMethodIssuerRequest::class => MockResponse::noContent(), + ]); + + $client->methodIssuers->disable( + 'pfl_v9hTwCvYqw', + 'ideal', + 'ideal_INGBNL2A' + ); + + // Test passes if no exception is thrown + $this->assertTrue(true); + } + + protected function assertIssuer(Issuer $issuer) + { + $this->assertInstanceOf(Issuer::class, $issuer); + $this->assertEquals('issuer', $issuer->resource); + $this->assertNotEmpty($issuer->id); + $this->assertNotEmpty($issuer->description); + $this->assertNotEmpty($issuer->status); + $this->assertNotEmpty($issuer->_links); + } +} diff --git a/tests/EndpointCollection/OnboardingEndpointCollectionTest.php b/tests/EndpointCollection/OnboardingEndpointCollectionTest.php new file mode 100644 index 000000000..734cd838b --- /dev/null +++ b/tests/EndpointCollection/OnboardingEndpointCollectionTest.php @@ -0,0 +1,30 @@ + MockResponse::ok('onboarding'), + ]); + + /** @var Onboarding $onboarding */ + $onboarding = $client->onboarding->status(); + + $this->assertInstanceOf(Onboarding::class, $onboarding); + $this->assertEquals('onboarding', $onboarding->resource); + $this->assertNotEmpty($onboarding->name); + $this->assertNotEmpty($onboarding->status); + $this->assertNotEmpty($onboarding->canReceivePayments); + $this->assertNotEmpty($onboarding->canReceiveSettlements); + } +} diff --git a/tests/EndpointCollection/OrganizationEndpointCollectionTest.php b/tests/EndpointCollection/OrganizationEndpointCollectionTest.php new file mode 100644 index 000000000..88d4e7e4b --- /dev/null +++ b/tests/EndpointCollection/OrganizationEndpointCollectionTest.php @@ -0,0 +1,69 @@ + MockResponse::ok('organization', 'org_12345678'), + ]); + + /** @var Organization $organization */ + $organization = $client->organizations->get('org_12345678'); + + $this->assertOrganization($organization); + } + + /** @test */ + public function current() + { + $client = new MockMollieClient([ + GetOrganizationRequest::class => MockResponse::ok('organization'), + ]); + + /** @var Organization $organization */ + $organization = $client->organizations->current(); + + $this->assertOrganization($organization); + } + + /** @test */ + public function partner_status() + { + $client = new MockMollieClient([ + GetOrganizationPartnerStatusRequest::class => MockResponse::ok('partner-status'), + ]); + + /** @var Partner $partner */ + $partner = $client->organizations->partnerStatus(); + + $this->assertInstanceOf(Partner::class, $partner); + $this->assertEquals('partner', $partner->resource); + $this->assertNotEmpty($partner->partnerType); + $this->assertNotEmpty($partner->partnerContractSignedAt); + $this->assertNotEmpty($partner->_links); + } + + protected function assertOrganization(Organization $organization) + { + $this->assertInstanceOf(Organization::class, $organization); + $this->assertEquals('organization', $organization->resource); + $this->assertNotEmpty($organization->id); + $this->assertNotEmpty($organization->name); + $this->assertNotEmpty($organization->email); + $this->assertNotEmpty($organization->locale); + $this->assertNotEmpty($organization->address); + $this->assertNotEmpty($organization->registrationNumber); + } +} diff --git a/tests/EndpointCollection/OrganizationPartnerEndpointCollectionTest.php b/tests/EndpointCollection/OrganizationPartnerEndpointCollectionTest.php new file mode 100644 index 000000000..db1d5daf1 --- /dev/null +++ b/tests/EndpointCollection/OrganizationPartnerEndpointCollectionTest.php @@ -0,0 +1,29 @@ + MockResponse::ok('partner-status'), + ]); + + /** @var Partner $partner */ + $partner = $client->organizationPartners->status(); + + $this->assertInstanceOf(Partner::class, $partner); + $this->assertEquals('partner', $partner->resource); + $this->assertNotEmpty($partner->partnerType); + $this->assertNotEmpty($partner->partnerContractSignedAt); + $this->assertNotEmpty($partner->_links); + } +} diff --git a/tests/EndpointCollection/PaymentCaptureEndpointCollectionTest.php b/tests/EndpointCollection/PaymentCaptureEndpointCollectionTest.php new file mode 100644 index 000000000..f3386a332 --- /dev/null +++ b/tests/EndpointCollection/PaymentCaptureEndpointCollectionTest.php @@ -0,0 +1,92 @@ + MockResponse::created('capture'), + ]); + + /** @var Capture $capture */ + $capture = $client->paymentCaptures->createForId('tr_7UhSN1zuXS', new CreatePaymentCapturePayload( + 'Capture for cart #12345', + new Money('EUR', '35.95') + )); + + $this->assertCapture($capture); + } + + /** @test */ + public function get_for_id() + { + $client = new MockMollieClient([ + GetPaymentCaptureRequest::class => MockResponse::ok('capture'), + ]); + + /** @var Capture $capture */ + $capture = $client->paymentCaptures->getForId('tr_7UhSN1zuXS', 'cpt_mNepDkEtco6ah3QNPUGYH'); + + $this->assertCapture($capture); + } + + /** @test */ + public function page_for_id() + { + $client = new MockMollieClient([ + GetPaginatedPaymentCapturesRequest::class => MockResponse::ok('capture-list'), + ]); + + /** @var CaptureCollection $captures */ + $captures = $client->paymentCaptures->pageForId('tr_7UhSN1zuXS'); + + $this->assertInstanceOf(CaptureCollection::class, $captures); + $this->assertEquals(1, $captures->count()); + $this->assertCount(1, $captures); + + $this->assertCapture($captures[0]); + } + + /** @test */ + public function iterator_for_id() + { + $client = new MockMollieClient([ + GetPaginatedPaymentCapturesRequest::class => MockResponse::ok('capture-list'), + DynamicGetRequest::class => MockResponse::ok('empty-list', 'captures'), + ]); + + foreach ($client->paymentCaptures->iteratorForId('tr_7UhSN1zuXS') as $capture) { + $this->assertInstanceOf(Capture::class, $capture); + $this->assertCapture($capture); + } + } + + protected function assertCapture(Capture $capture) + { + $this->assertInstanceOf(Capture::class, $capture); + $this->assertEquals('capture', $capture->resource); + $this->assertNotEmpty($capture->id); + $this->assertEquals('live', $capture->mode); + $this->assertEquals('Capture for cart #12345', $capture->description); + $this->assertEquals('35.95', $capture->amount->value); + $this->assertEquals('EUR', $capture->amount->currency); + $this->assertEquals('tr_7UhSN1zuXS', $capture->paymentId); + $this->assertNotEmpty($capture->createdAt); + $this->assertNotEmpty($capture->_links); + } +} diff --git a/tests/EndpointCollection/PaymentChargebackEndpointCollectionTest.php b/tests/EndpointCollection/PaymentChargebackEndpointCollectionTest.php new file mode 100644 index 000000000..a91f23a66 --- /dev/null +++ b/tests/EndpointCollection/PaymentChargebackEndpointCollectionTest.php @@ -0,0 +1,73 @@ + MockResponse::ok('chargeback'), + ]); + + /** @var Chargeback $chargeback */ + $chargeback = $client->paymentChargebacks->getForId('tr_7UhSN1zuXS', 'chb_n9z0tp'); + + $this->assertChargeback($chargeback); + } + + /** @test */ + public function page_for_id() + { + $client = new MockMollieClient([ + GetPaginatedPaymentChargebacksRequest::class => MockResponse::ok('chargeback-list'), + ]); + + /** @var ChargebackCollection $chargebacks */ + $chargebacks = $client->paymentChargebacks->pageForId('tr_7UhSN1zuXS'); + + $this->assertInstanceOf(ChargebackCollection::class, $chargebacks); + $this->assertGreaterThan(0, $chargebacks->count()); + $this->assertGreaterThan(0, count($chargebacks)); + + foreach ($chargebacks as $chargeback) { + $this->assertChargeback($chargeback); + } + } + + /** @test */ + public function iterator_for_id() + { + $client = new MockMollieClient([ + GetPaginatedPaymentChargebacksRequest::class => MockResponse::ok('chargeback-list'), + DynamicGetRequest::class => MockResponse::ok('empty-list', 'chargebacks'), + ]); + + foreach ($client->paymentChargebacks->iteratorForId('tr_7UhSN1zuXS') as $chargeback) { + $this->assertInstanceOf(Chargeback::class, $chargeback); + $this->assertChargeback($chargeback); + } + } + + protected function assertChargeback(Chargeback $chargeback) + { + $this->assertInstanceOf(Chargeback::class, $chargeback); + $this->assertEquals('chargeback', $chargeback->resource); + $this->assertNotEmpty($chargeback->id); + $this->assertNotEmpty($chargeback->amount); + $this->assertNotEmpty($chargeback->settlementAmount); + $this->assertNotEmpty($chargeback->createdAt); + $this->assertStringStartsWith('tr_', $chargeback->paymentId); + $this->assertNotEmpty($chargeback->_links); + } +} diff --git a/tests/EndpointCollection/PaymentEndpointCollectionTest.php b/tests/EndpointCollection/PaymentEndpointCollectionTest.php new file mode 100644 index 000000000..c6b9e0c58 --- /dev/null +++ b/tests/EndpointCollection/PaymentEndpointCollectionTest.php @@ -0,0 +1,154 @@ + MockResponse::created('payment'), + ]); + + /** @var Payment $payment */ + $payment = $client->payments->create(new CreatePaymentPayload( + 'Test payment', + new Money('10.00', 'EUR'), + 'https://example.org/redirect', + 'https://example.org/webhook', + )); + + $this->assertPayment($payment); + } + + /** @test */ + public function get() + { + $client = new MockMollieClient([ + GetPaymentRequest::class => MockResponse::ok('payment'), + ]); + + /** @var Payment $payment */ + $payment = $client->payments->get('tr_WDqYK6vllg'); + + $this->assertPayment($payment); + } + + /** @test */ + public function update() + { + $client = new MockMollieClient([ + UpdatePaymentRequest::class => MockResponse::ok('payment'), + ]); + + /** @var Payment $payment */ + $payment = $client->payments->update('tr_WDqYK6vllg', new UpdatePaymentPayload( + 'Updated description', + 'https://example.org/updated-redirect', + )); + + $this->assertPayment($payment); + } + + /** @test */ + public function cancel() + { + $client = new MockMollieClient([ + CancelPaymentRequest::class => MockResponse::noContent(), + ]); + + $payment = $client->payments->cancel('tr_WDqYK6vllg'); + + $this->assertTrue($payment->getResponse()->successful()); + } + + /** @test */ + public function refund() + { + $client = new MockMollieClient([ + CreatePaymentRefundRequest::class => MockResponse::created('refund'), + ]); + + $payment = new Payment($client); + $payment->id = 'tr_WDqYK6vllg'; + + /** @var Refund $refund */ + $refund = $client->payments->refund($payment, new CreateRefundPaymentPayload( + 'Test refund', + new Money('5.95', 'EUR'), + )); + + $this->assertInstanceOf(Refund::class, $refund); + $this->assertEquals('refund', $refund->resource); + $this->assertNotEmpty($refund->id); + $this->assertEquals('5.95', $refund->amount->value); + $this->assertEquals('EUR', $refund->amount->currency); + } + + /** @test */ + public function page() + { + $client = new MockMollieClient([ + GetPaginatedPaymentsRequest::class => MockResponse::ok('payment-list'), + ]); + + /** @var PaymentCollection $payments */ + $payments = $client->payments->page(); + + $this->assertInstanceOf(PaymentCollection::class, $payments); + $this->assertGreaterThan(0, $payments->count()); + $this->assertGreaterThan(0, count($payments)); + + foreach ($payments as $payment) { + $this->assertPayment($payment); + } + } + + /** @test */ + public function iterator() + { + $client = new MockMollieClient([ + GetPaginatedPaymentsRequest::class => MockResponse::ok('payment-list'), + DynamicGetRequest::class => MockResponse::ok('empty-list', 'payments'), + ]); + + foreach ($client->payments->iterator() as $payment) { + $this->assertInstanceOf(Payment::class, $payment); + $this->assertPayment($payment); + } + } + + protected function assertPayment(Payment $payment) + { + $this->assertInstanceOf(Payment::class, $payment); + $this->assertEquals('payment', $payment->resource); + $this->assertNotEmpty($payment->id); + $this->assertNotEmpty($payment->mode); + $this->assertNotEmpty($payment->createdAt); + $this->assertNotEmpty($payment->status); + $this->assertNotEmpty($payment->amount); + $this->assertNotEmpty($payment->description); + $this->assertNotEmpty($payment->method); + $this->assertNotEmpty($payment->metadata); + $this->assertNotEmpty($payment->profileId); + } +} diff --git a/tests/EndpointCollection/PaymentLinkEndpointCollectionTest.php b/tests/EndpointCollection/PaymentLinkEndpointCollectionTest.php new file mode 100644 index 000000000..0ea51dc75 --- /dev/null +++ b/tests/EndpointCollection/PaymentLinkEndpointCollectionTest.php @@ -0,0 +1,128 @@ + MockResponse::created('payment-link'), + ]); + + /** @var PaymentLink $paymentLink */ + $paymentLink = $client->paymentLinks->create(new CreatePaymentLinkPayload( + 'Test payment link', + new Money('10.00', 'EUR'), + 'https://example.org/redirect', + 'https://example.org/webhook', + null, + null, + new DateTimeImmutable('2023-12-31'), + )); + + $this->assertPaymentLink($paymentLink); + } + + /** @test */ + public function get() + { + $client = new MockMollieClient([ + GetPaymentLinkRequest::class => MockResponse::ok('payment-link'), + ]); + + /** @var PaymentLink $paymentLink */ + $paymentLink = $client->paymentLinks->get('pl_4Y0eZitmBnQ6IDoMqZQKh'); + + $this->assertPaymentLink($paymentLink); + } + + /** @test */ + public function update() + { + $client = new MockMollieClient([ + UpdatePaymentLinkRequest::class => MockResponse::ok('payment-link'), + ]); + + /** @var PaymentLink $paymentLink */ + $paymentLink = $client->paymentLinks->update('pl_4Y0eZitmBnQ6IDoMqZQKh', new UpdatePaymentLinkPayload( + 'Updated description', + )); + + $this->assertPaymentLink($paymentLink); + } + + /** @test */ + public function delete() + { + $client = new MockMollieClient([ + DeletePaymentLinkRequest::class => MockResponse::noContent(), + ]); + + $client->paymentLinks->delete('pl_4Y0eZitmBnQ6IDoMqZQKh'); + + // Test passes if no exception is thrown + $this->assertTrue(true); + } + + /** @test */ + public function page() + { + $client = new MockMollieClient([ + GetPaginatedPaymentLinksRequest::class => MockResponse::ok('payment-link-list'), + ]); + + /** @var PaymentLinkCollection $paymentLinks */ + $paymentLinks = $client->paymentLinks->page(); + + $this->assertInstanceOf(PaymentLinkCollection::class, $paymentLinks); + $this->assertGreaterThan(0, $paymentLinks->count()); + $this->assertGreaterThan(0, count($paymentLinks)); + + foreach ($paymentLinks as $paymentLink) { + $this->assertPaymentLink($paymentLink); + } + } + + /** @test */ + public function iterator() + { + $client = new MockMollieClient([ + GetPaginatedPaymentLinksRequest::class => MockResponse::ok('payment-link-list'), + DynamicGetRequest::class => MockResponse::ok('empty-list', 'payment_links'), + ]); + + foreach ($client->paymentLinks->iterator() as $paymentLink) { + $this->assertInstanceOf(PaymentLink::class, $paymentLink); + $this->assertPaymentLink($paymentLink); + } + } + + protected function assertPaymentLink(PaymentLink $paymentLink) + { + $this->assertInstanceOf(PaymentLink::class, $paymentLink); + $this->assertEquals('payment-link', $paymentLink->resource); + $this->assertNotEmpty($paymentLink->id); + $this->assertNotEmpty($paymentLink->description); + $this->assertNotEmpty($paymentLink->amount); + $this->assertNotEmpty($paymentLink->expiresAt); + $this->assertNotEmpty($paymentLink->_links); + } +} diff --git a/tests/EndpointCollection/PaymentLinkPaymentEndpointCollectionTest.php b/tests/EndpointCollection/PaymentLinkPaymentEndpointCollectionTest.php new file mode 100644 index 000000000..7efb82e13 --- /dev/null +++ b/tests/EndpointCollection/PaymentLinkPaymentEndpointCollectionTest.php @@ -0,0 +1,61 @@ + MockResponse::ok('payment-list'), + ]); + + /** @var PaymentCollection $payments */ + $payments = $client->paymentLinkPayments->pageForId('pl_4Y0eZitmBnQ6IDoMqZQKh'); + + $this->assertInstanceOf(PaymentCollection::class, $payments); + $this->assertGreaterThan(0, $payments->count()); + + foreach ($payments as $payment) { + $this->assertPayment($payment); + } + } + + /** @test */ + public function iterator_for() + { + $client = new MockMollieClient([ + GetPaginatedPaymentLinkPaymentsRequest::class => MockResponse::ok('payment-list'), + DynamicGetRequest::class => MockResponse::ok('empty-list', 'payments'), + ]); + + foreach ($client->paymentLinkPayments->iteratorForId('pl_4Y0eZitmBnQ6IDoMqZQKh') as $payment) { + $this->assertPayment($payment); + } + } + + protected function assertPayment(Payment $payment) + { + $this->assertInstanceOf(Payment::class, $payment); + $this->assertEquals('payment', $payment->resource); + $this->assertNotEmpty($payment->id); + $this->assertNotEmpty($payment->mode); + $this->assertNotEmpty($payment->createdAt); + $this->assertNotEmpty($payment->status); + $this->assertNotEmpty($payment->amount); + $this->assertNotEmpty($payment->description); + $this->assertNotEmpty($payment->method); + $this->assertNotEmpty($payment->metadata); + $this->assertNotEmpty($payment->profileId); + $this->assertNotEmpty($payment->_links); + } +} diff --git a/tests/EndpointCollection/PaymentRefundEndpointCollectionTest.php b/tests/EndpointCollection/PaymentRefundEndpointCollectionTest.php new file mode 100644 index 000000000..d0fe7e5b8 --- /dev/null +++ b/tests/EndpointCollection/PaymentRefundEndpointCollectionTest.php @@ -0,0 +1,123 @@ + MockResponse::created('refund'), + ]); + + $payment = new Payment($client); + $payment->id = 'tr_7UhSN1zuXS'; + + /** @var Refund $refund */ + $refund = $client->paymentRefunds->createFor($payment, [ + 'amount' => [ + 'currency' => 'EUR', + 'value' => '5.95', + ], + 'description' => 'Test refund', + ]); + + $this->assertRefund($refund); + } + + /** @test */ + public function get_for() + { + $client = new MockMollieClient([ + GetPaymentRefundRequest::class => MockResponse::ok('refund'), + ]); + + $payment = new Payment($client); + $payment->id = 'tr_7UhSN1zuXS'; + + /** @var Refund $refund */ + $refund = $client->paymentRefunds->getFor($payment, 're_4qqhO89gsT'); + + $this->assertRefund($refund); + } + + /** @test */ + public function cancel_for() + { + $client = new MockMollieClient([ + CancelPaymentRefundRequest::class => MockResponse::noContent(), + ]); + + $payment = new Payment($client); + $payment->id = 'tr_7UhSN1zuXS'; + + $client->paymentRefunds->cancelForPayment($payment, 're_4qqhO89gsT'); + + // Test passes if no exception is thrown + $this->assertTrue(true); + } + + /** @test */ + public function page_for() + { + $client = new MockMollieClient([ + GetPaginatedPaymentRefundsRequest::class => MockResponse::ok('refund-list'), + ]); + + $payment = new Payment($client); + $payment->id = 'tr_7UhSN1zuXS'; + + /** @var RefundCollection $refunds */ + $refunds = $client->paymentRefunds->pageFor($payment); + + $this->assertInstanceOf(RefundCollection::class, $refunds); + $this->assertGreaterThan(0, $refunds->count()); + $this->assertGreaterThan(0, count($refunds)); + + foreach ($refunds as $refund) { + $this->assertRefund($refund); + } + } + + /** @test */ + public function iterator_for() + { + $client = new MockMollieClient([ + GetPaginatedPaymentRefundsRequest::class => MockResponse::ok('refund-list'), + DynamicGetRequest::class => MockResponse::ok('empty-list', 'refunds'), + ]); + + $payment = new Payment($client); + $payment->id = 'tr_7UhSN1zuXS'; + + foreach ($client->paymentRefunds->iteratorFor($payment) as $refund) { + $this->assertInstanceOf(Refund::class, $refund); + $this->assertRefund($refund); + } + } + + protected function assertRefund(Refund $refund) + { + $this->assertInstanceOf(Refund::class, $refund); + $this->assertEquals('refund', $refund->resource); + $this->assertNotEmpty($refund->id); + $this->assertNotEmpty($refund->amount); + $this->assertNotEmpty($refund->status); + $this->assertEquals('tr_7UhSN1zuXS', $refund->paymentId); + $this->assertNotEmpty($refund->createdAt); + $this->assertNotEmpty($refund->_links); + } +} diff --git a/tests/EndpointCollection/PaymentRouteEndpointCollectionTest.php b/tests/EndpointCollection/PaymentRouteEndpointCollectionTest.php new file mode 100644 index 000000000..3406d2ee1 --- /dev/null +++ b/tests/EndpointCollection/PaymentRouteEndpointCollectionTest.php @@ -0,0 +1,30 @@ + MockResponse::ok('route'), + ]); + + /** @var Route $route */ + $route = $client->paymentRoutes->updateReleaseDateForId('tr_7UhSN1zuXS', 'rt_abc123', '2024-01-01'); + + $this->assertInstanceOf(Route::class, $route); + $this->assertEquals('route', $route->resource); + $this->assertNotEmpty($route->id); + $this->assertNotEmpty($route->amount); + $this->assertNotEmpty($route->destination); + $this->assertNotEmpty($route->releaseDate); + } +} diff --git a/tests/EndpointCollection/PermissionEndpointCollectionTest.php b/tests/EndpointCollection/PermissionEndpointCollectionTest.php new file mode 100644 index 000000000..64a5297ab --- /dev/null +++ b/tests/EndpointCollection/PermissionEndpointCollectionTest.php @@ -0,0 +1,56 @@ + MockResponse::ok('permission'), + ]); + + /** @var Permission $permission */ + $permission = $client->permissions->get('payments.read'); + + $this->assertPermission($permission); + } + + /** @test */ + public function list() + { + $client = new MockMollieClient([ + ListPermissionsRequest::class => MockResponse::ok('permission-list'), + ]); + + /** @var PermissionCollection $permissions */ + $permissions = $client->permissions->list(); + + $this->assertInstanceOf(PermissionCollection::class, $permissions); + $this->assertGreaterThan(0, $permissions->count()); + $this->assertGreaterThan(0, count($permissions)); + + foreach ($permissions as $permission) { + $this->assertPermission($permission); + } + } + + protected function assertPermission(Permission $permission) + { + $this->assertInstanceOf(Permission::class, $permission); + $this->assertEquals('permission', $permission->resource); + $this->assertNotEmpty($permission->id); + $this->assertNotEmpty($permission->description); + $this->assertIsBool($permission->granted); + $this->assertNotEmpty($permission->_links); + } +} diff --git a/tests/EndpointCollection/ProfileEndpointCollectionTest.php b/tests/EndpointCollection/ProfileEndpointCollectionTest.php new file mode 100644 index 000000000..64b0c9306 --- /dev/null +++ b/tests/EndpointCollection/ProfileEndpointCollectionTest.php @@ -0,0 +1,143 @@ + MockResponse::created('profile'), + ]); + + /** @var Profile $profile */ + $profile = $client->profiles->create(new CreateProfilePayload( + 'My Test Profile', + 'https://example.org', + 'info@example.org', + '+31612345678', + 'test', + )); + + $this->assertProfile($profile); + } + + /** @test */ + public function get() + { + $client = new MockMollieClient([ + GetProfileRequest::class => MockResponse::ok('profile'), + ]); + + /** @var Profile $profile */ + $profile = $client->profiles->get('pfl_v9hTwCvYqw'); + + $this->assertProfile($profile); + } + + /** @test */ + public function get_current() + { + $client = new MockMollieClient([ + GetProfileRequest::class => MockResponse::ok('current-profile'), + ]); + + /** @var Profile $profile */ + $profile = $client->profiles->getCurrent(); + + $this->assertProfile($profile); + } + + /** @test */ + public function update() + { + $client = new MockMollieClient([ + UpdateProfileRequest::class => MockResponse::ok('profile'), + ]); + + /** @var Profile $profile */ + $profile = $client->profiles->update('pfl_v9hTwCvYqw', new UpdateProfilePayload( + 'Updated Profile Name', + 'https://updated-example.org', + )); + + $this->assertProfile($profile); + } + + /** @test */ + public function delete() + { + $client = new MockMollieClient([ + DeleteProfileRequest::class => MockResponse::noContent(), + ]); + + $client->profiles->delete('pfl_v9hTwCvYqw'); + + // Test passes if no exception is thrown + $this->assertTrue(true); + } + + /** @test */ + public function page() + { + $client = new MockMollieClient([ + GetPaginatedProfilesRequest::class => MockResponse::ok('profile-list'), + ]); + + /** @var ProfileCollection $profiles */ + $profiles = $client->profiles->page(); + + $this->assertInstanceOf(ProfileCollection::class, $profiles); + $this->assertGreaterThan(0, $profiles->count()); + $this->assertGreaterThan(0, count($profiles)); + + foreach ($profiles as $profile) { + $this->assertProfile($profile); + } + } + + /** @test */ + public function iterator() + { + $client = new MockMollieClient([ + GetPaginatedProfilesRequest::class => MockResponse::ok('profile-list'), + DynamicGetRequest::class => MockResponse::ok('empty-list', 'profiles'), + ]); + + foreach ($client->profiles->iterator() as $profile) { + $this->assertInstanceOf(Profile::class, $profile); + $this->assertProfile($profile); + } + } + + protected function assertProfile(Profile $profile) + { + $this->assertInstanceOf(Profile::class, $profile); + $this->assertEquals('profile', $profile->resource); + $this->assertNotEmpty($profile->id); + $this->assertNotEmpty($profile->mode); + $this->assertNotEmpty($profile->name); + $this->assertNotEmpty($profile->website); + $this->assertNotEmpty($profile->email); + $this->assertNotEmpty($profile->phone); + $this->assertNotEmpty($profile->businessCategory); + $this->assertNotEmpty($profile->status); + $this->assertNotEmpty($profile->createdAt); + $this->assertNotEmpty($profile->_links); + } +} diff --git a/tests/EndpointCollection/ProfileMethodEndpointCollectionTest.php b/tests/EndpointCollection/ProfileMethodEndpointCollectionTest.php new file mode 100644 index 000000000..c05701ee3 --- /dev/null +++ b/tests/EndpointCollection/ProfileMethodEndpointCollectionTest.php @@ -0,0 +1,75 @@ + MockResponse::ok('method', 'ideal'), + ]); + + /** @var Method $method */ + $method = $client->profileMethods->enableForId('pfl_v9hTwCvYqw', 'ideal'); + + $this->assertMethod($method); + } + + /** @test */ + public function enable() + { + $client = new MockMollieClient([ + EnableProfileMethodRequest::class => MockResponse::ok('method', 'ideal'), + ]); + + /** @var Method $method */ + $method = $client->profileMethods->enable('ideal'); + + $this->assertMethod($method); + } + + /** @test */ + public function disable_for_id() + { + $client = new MockMollieClient([ + DisableProfileMethodRequest::class => MockResponse::noContent(), + ]); + + $client->profileMethods->disableForId('pfl_v9hTwCvYqw', 'ideal'); + + // Test passes if no exception is thrown + $this->assertTrue(true); + } + + /** @test */ + public function disable() + { + $client = new MockMollieClient([ + DisableProfileMethodRequest::class => MockResponse::noContent(), + ]); + + $client->profileMethods->disable('ideal'); + + // Test passes if no exception is thrown + $this->assertTrue(true); + } + + protected function assertMethod(Method $method) + { + $this->assertInstanceOf(Method::class, $method); + $this->assertEquals('method', $method->resource); + $this->assertNotEmpty($method->id); + $this->assertNotEmpty($method->description); + $this->assertNotEmpty($method->status); + $this->assertNotEmpty($method->_links); + } +} diff --git a/tests/EndpointCollection/RefundEndpointCollectionTest.php b/tests/EndpointCollection/RefundEndpointCollectionTest.php new file mode 100644 index 000000000..be584a31a --- /dev/null +++ b/tests/EndpointCollection/RefundEndpointCollectionTest.php @@ -0,0 +1,57 @@ + MockResponse::ok('refund-list'), + ]); + + /** @var RefundCollection $refunds */ + $refunds = $client->refunds->page(); + + $this->assertInstanceOf(RefundCollection::class, $refunds); + $this->assertGreaterThan(0, $refunds->count()); + + foreach ($refunds as $refund) { + $this->assertRefund($refund); + } + } + + /** @test */ + public function iterator() + { + $client = new MockMollieClient([ + GetPaginatedRefundsRequest::class => MockResponse::ok('refund-list'), + DynamicGetRequest::class => MockResponse::ok('empty-list', 'refunds'), + ]); + + foreach ($client->refunds->iterator() as $refund) { + $this->assertRefund($refund); + } + } + + protected function assertRefund(Refund $refund) + { + $this->assertInstanceOf(Refund::class, $refund); + $this->assertEquals('refund', $refund->resource); + $this->assertNotEmpty($refund->id); + $this->assertNotEmpty($refund->amount); + $this->assertNotEmpty($refund->status); + $this->assertNotEmpty($refund->createdAt); + $this->assertNotEmpty($refund->paymentId); + $this->assertNotEmpty($refund->_links); + } +} diff --git a/tests/EndpointCollection/SalesInvoiceEndpointCollectionTest.php b/tests/EndpointCollection/SalesInvoiceEndpointCollectionTest.php new file mode 100644 index 000000000..4ff831d30 --- /dev/null +++ b/tests/EndpointCollection/SalesInvoiceEndpointCollectionTest.php @@ -0,0 +1,136 @@ + MockResponse::ok('sales-invoice'), + ]); + + $salesInvoice = $client->salesInvoices->get('inv_123'); + + $this->assertInstanceOf(SalesInvoice::class, $salesInvoice); + } + + /** @test */ + public function create() + { + $client = new MockMollieClient([ + CreateSalesInvoiceRequest::class => MockResponse::created('sales-invoice'), + ]); + + $invoiceLines = [ + new InvoiceLine( + 'Monthly subscription fee', + 1, + '21', + new Money('EUR', '10,00'), + ), + ]; + + // Create a sales invoice + $payload = new CreateSalesInvoicePayload( + 'EUR', + SalesInvoiceStatus::DRAFT, + VatScheme::STANDARD, + VatMode::INCLUSIVE, + PaymentTerm::DAYS_30, + 'XXXXX', + new Recipient( + RecipientType::CONSUMER, + 'darth@vader.deathstar', + 'Sample Street 12b', + '2000 AA', + 'Amsterdam', + 'NL', + 'nl_NL' + ), + new DataCollection($invoiceLines) + ); + + $salesInvoice = $client->salesInvoices->create($payload); + + $this->assertInstanceOf(SalesInvoice::class, $salesInvoice); + } + + /** @test */ + public function update() + { + $client = new MockMollieClient([ + UpdateSalesInvoiceRequest::class => MockResponse::ok('sales-invoice'), + ]); + + $payload = new UpdateSalesInvoicePayload( + SalesInvoiceStatus::PAID, + 'XXXXX', + ); + $salesInvoice = $client->salesInvoices->update('invoice_123', $payload); + + $this->assertInstanceOf(SalesInvoice::class, $salesInvoice); + } + + /** @test */ + public function delete() + { + $client = new MockMollieClient([ + DeleteSalesInvoiceRequest::class => MockResponse::noContent(), + ]); + + $client->salesInvoices->delete('invoice_123'); + + $this->assertTrue(true); // Test passes if no exception is thrown + } + + /** @test */ + public function page() + { + $client = new MockMollieClient([ + GetPaginatedSalesInvoicesRequest::class => MockResponse::ok('sales-invoice-list'), + ]); + + $salesInvoices = $client->salesInvoices->page(); + + $this->assertInstanceOf(SalesInvoiceCollection::class, $salesInvoices); + } + + /** @test */ + public function iterate() + { + $client = new MockMollieClient([ + GetPaginatedSalesInvoicesRequest::class => MockResponse::ok('sales-invoice-list'), + DynamicGetRequest::class => MockResponse::ok('empty-list', 'sales_invoices'), + ]); + + /** @var SalesInvoice $salesInvoice */ + foreach ($client->salesInvoices->iterator() as $salesInvoice) { + $this->assertInstanceOf(SalesInvoice::class, $salesInvoice); + } + } +} diff --git a/tests/EndpointCollection/SessionEndpointCollectionTest.php b/tests/EndpointCollection/SessionEndpointCollectionTest.php new file mode 100644 index 000000000..3d6b149b2 --- /dev/null +++ b/tests/EndpointCollection/SessionEndpointCollectionTest.php @@ -0,0 +1,120 @@ + MockResponse::ok('session'), + ]); + + /** @var Session $session */ + $session = $client->sessions->get('ses_123', new AnyData(['include' => 'details'])); + + $this->assertSession($session); + } + + /** @test */ + public function create() + { + $client = new MockMollieClient([ + CreateSessionRequest::class => MockResponse::created('session'), + ]); + + /** @var Session $session */ + $session = $client->sessions->create(new AnyData([ + 'amount' => new Money('EUR', '10.00'), + 'description' => 'Test Session', + ])); + + $this->assertSession($session); + } + + /** @test */ + public function update() + { + $client = new MockMollieClient([ + UpdateSessionRequest::class => MockResponse::ok('session'), + ]); + + /** @var Session $session */ + $session = $client->sessions->update('ses_123', new AnyData([ + 'description' => 'Updated Session', + ])); + + $this->assertSession($session); + } + + /** @test */ + public function cancel() + { + $client = new MockMollieClient([ + CancelSessionRequest::class => MockResponse::noContent(), + ]); + + $client->sessions->cancel('ses_123'); + + // Test passes if no exception is thrown + $this->assertTrue(true); + } + + /** @test */ + public function page() + { + $client = new MockMollieClient([ + GetPaginatedSessionsRequest::class => MockResponse::ok('session-list'), + ]); + + /** @var SessionCollection $sessions */ + $sessions = $client->sessions->page(); + + $this->assertInstanceOf(SessionCollection::class, $sessions); + $this->assertGreaterThan(0, $sessions->count()); + + foreach ($sessions as $session) { + $this->assertSession($session); + } + } + + /** @test */ + public function iterator() + { + $client = new MockMollieClient([ + GetPaginatedSessionsRequest::class => MockResponse::ok('session-list'), + DynamicGetRequest::class => MockResponse::ok('empty-list', 'sessions'), + ]); + + foreach ($client->sessions->iterator() as $session) { + $this->assertSession($session); + } + } + + protected function assertSession(Session $session) + { + $this->assertInstanceOf(Session::class, $session); + $this->assertEquals('session', $session->resource); + $this->assertNotEmpty($session->id); + $this->assertNotEmpty($session->mode); + $this->assertNotEmpty($session->status); + $this->assertNotEmpty($session->amount); + $this->assertNotEmpty($session->description); + $this->assertNotEmpty($session->_links); + } +} diff --git a/tests/EndpointCollection/SettlementCaptureEndpointCollectionTest.php b/tests/EndpointCollection/SettlementCaptureEndpointCollectionTest.php new file mode 100644 index 000000000..9ee93c62f --- /dev/null +++ b/tests/EndpointCollection/SettlementCaptureEndpointCollectionTest.php @@ -0,0 +1,64 @@ + MockResponse::ok('capture-list'), + ]); + + $settlement = new Settlement($client); + $settlement->id = 'stl_jDk30akdN'; + + /** @var CaptureCollection $captures */ + $captures = $client->settlementCaptures->pageFor($settlement); + + $this->assertInstanceOf(CaptureCollection::class, $captures); + $this->assertGreaterThan(0, $captures->count()); + + foreach ($captures as $capture) { + $this->assertCapture($capture); + } + } + + /** @test */ + public function iterator_for() + { + $client = new MockMollieClient([ + GetPaginatedSettlementCapturesRequest::class => MockResponse::ok('capture-list'), + DynamicGetRequest::class => MockResponse::ok('empty-list', 'captures'), + ]); + + $settlement = new Settlement($client); + $settlement->id = 'stl_jDk30akdN'; + + foreach ($client->settlementCaptures->iteratorFor($settlement) as $capture) { + $this->assertCapture($capture); + } + } + + protected function assertCapture(Capture $capture) + { + $this->assertInstanceOf(Capture::class, $capture); + $this->assertEquals('capture', $capture->resource); + $this->assertNotEmpty($capture->id); + $this->assertNotEmpty($capture->mode); + $this->assertNotEmpty($capture->amount); + $this->assertNotEmpty($capture->paymentId); + $this->assertNotEmpty($capture->createdAt); + $this->assertNotEmpty($capture->_links); + } +} diff --git a/tests/EndpointCollection/SettlementChargebackEndpointCollectionTest.php b/tests/EndpointCollection/SettlementChargebackEndpointCollectionTest.php new file mode 100644 index 000000000..64c786f7b --- /dev/null +++ b/tests/EndpointCollection/SettlementChargebackEndpointCollectionTest.php @@ -0,0 +1,64 @@ + MockResponse::ok('chargeback-list'), + ]); + + $settlement = new Settlement($client); + $settlement->id = 'stl_jDk30akdN'; + + /** @var ChargebackCollection $chargebacks */ + $chargebacks = $client->settlementChargebacks->pageFor($settlement); + + $this->assertInstanceOf(ChargebackCollection::class, $chargebacks); + $this->assertGreaterThan(0, $chargebacks->count()); + + foreach ($chargebacks as $chargeback) { + $this->assertChargeback($chargeback); + } + } + + /** @test */ + public function iterator_for() + { + $client = new MockMollieClient([ + GetPaginatedSettlementChargebacksRequest::class => MockResponse::ok('chargeback-list'), + DynamicGetRequest::class => MockResponse::ok('empty-list', 'chargebacks'), + ]); + + $settlement = new Settlement($client); + $settlement->id = 'stl_jDk30akdN'; + + foreach ($client->settlementChargebacks->iteratorFor($settlement) as $chargeback) { + $this->assertChargeback($chargeback); + } + } + + protected function assertChargeback(Chargeback $chargeback) + { + $this->assertInstanceOf(Chargeback::class, $chargeback); + $this->assertEquals('chargeback', $chargeback->resource); + $this->assertNotEmpty($chargeback->id); + $this->assertNotEmpty($chargeback->amount); + $this->assertNotEmpty($chargeback->settlementAmount); + $this->assertNotEmpty($chargeback->createdAt); + $this->assertNotEmpty($chargeback->paymentId); + $this->assertNotEmpty($chargeback->_links); + } +} diff --git a/tests/EndpointCollection/SettlementPaymentEndpointCollectionTest.php b/tests/EndpointCollection/SettlementPaymentEndpointCollectionTest.php new file mode 100644 index 000000000..3a69cc904 --- /dev/null +++ b/tests/EndpointCollection/SettlementPaymentEndpointCollectionTest.php @@ -0,0 +1,65 @@ + MockResponse::ok('payment-list'), + ]); + + $settlement = new Settlement($client); + $settlement->id = 'stl_jDk30akdN'; + + /** @var PaymentCollection $payments */ + $payments = $client->settlementPayments->pageFor($settlement); + + $this->assertInstanceOf(PaymentCollection::class, $payments); + $this->assertGreaterThan(0, $payments->count()); + + foreach ($payments as $payment) { + $this->assertPayment($payment); + } + } + + /** @test */ + public function iterator_for() + { + $client = new MockMollieClient([ + GetPaginatedSettlementPaymentsRequest::class => MockResponse::ok('payment-list'), + DynamicGetRequest::class => MockResponse::ok('empty-list', 'payments'), + ]); + + $settlement = new Settlement($client); + $settlement->id = 'stl_jDk30akdN'; + + foreach ($client->settlementPayments->iteratorFor($settlement) as $payment) { + $this->assertPayment($payment); + } + } + + protected function assertPayment(Payment $payment) + { + $this->assertInstanceOf(Payment::class, $payment); + $this->assertEquals('payment', $payment->resource); + $this->assertNotEmpty($payment->id); + $this->assertNotEmpty($payment->amount); + $this->assertNotEmpty($payment->description); + $this->assertNotEmpty($payment->createdAt); + $this->assertNotEmpty($payment->status); + $this->assertNotEmpty($payment->profileId); + $this->assertNotEmpty($payment->_links); + } +} diff --git a/tests/EndpointCollection/SettlementRefundEndpointCollectionTest.php b/tests/EndpointCollection/SettlementRefundEndpointCollectionTest.php new file mode 100644 index 000000000..2de64871d --- /dev/null +++ b/tests/EndpointCollection/SettlementRefundEndpointCollectionTest.php @@ -0,0 +1,64 @@ + MockResponse::ok('refund-list'), + ]); + + $settlement = new Settlement($client); + $settlement->id = 'stl_jDk30akdN'; + + /** @var RefundCollection $refunds */ + $refunds = $client->settlementRefunds->pageFor($settlement); + + $this->assertInstanceOf(RefundCollection::class, $refunds); + $this->assertGreaterThan(0, $refunds->count()); + + foreach ($refunds as $refund) { + $this->assertRefund($refund); + } + } + + /** @test */ + public function iterator_for() + { + $client = new MockMollieClient([ + GetPaginatedSettlementRefundsRequest::class => MockResponse::ok('refund-list'), + DynamicGetRequest::class => MockResponse::ok('empty-list', 'refunds'), + ]); + + $settlement = new Settlement($client); + $settlement->id = 'stl_jDk30akdN'; + + foreach ($client->settlementRefunds->iteratorFor($settlement) as $refund) { + $this->assertRefund($refund); + } + } + + protected function assertRefund(Refund $refund) + { + $this->assertInstanceOf(Refund::class, $refund); + $this->assertEquals('refund', $refund->resource); + $this->assertNotEmpty($refund->id); + $this->assertNotEmpty($refund->amount); + $this->assertNotEmpty($refund->status); + $this->assertNotEmpty($refund->createdAt); + $this->assertNotEmpty($refund->paymentId); + $this->assertNotEmpty($refund->_links); + } +} diff --git a/tests/EndpointCollection/SettlementsEndpointCollectionTest.php b/tests/EndpointCollection/SettlementsEndpointCollectionTest.php new file mode 100644 index 000000000..ccc859777 --- /dev/null +++ b/tests/EndpointCollection/SettlementsEndpointCollectionTest.php @@ -0,0 +1,97 @@ + MockResponse::ok('settlement'), + ]); + + /** @var Settlement $settlement */ + $settlement = $client->settlements->get('stl_123'); + + $this->assertSettlement($settlement); + } + + /** @test */ + public function next() + { + $client = new MockMollieClient([ + GetSettlementRequest::class => MockResponse::ok('settlement'), + ]); + + /** @var Settlement $settlement */ + $settlement = $client->settlements->next(); + + $this->assertSettlement($settlement); + } + + /** @test */ + public function open() + { + $client = new MockMollieClient([ + GetSettlementRequest::class => MockResponse::ok('settlement'), + ]); + + /** @var Settlement $settlement */ + $settlement = $client->settlements->open(); + + $this->assertSettlement($settlement); + } + + /** @test */ + public function page() + { + $client = new MockMollieClient([ + GetPaginatedSettlementsRequest::class => MockResponse::ok('settlement-list'), + ]); + + /** @var SettlementCollection $settlements */ + $settlements = $client->settlements->page('stl_123', 50, ['reference' => 'test']); + + $this->assertInstanceOf(SettlementCollection::class, $settlements); + $this->assertGreaterThan(0, $settlements->count()); + + foreach ($settlements as $settlement) { + $this->assertSettlement($settlement); + } + } + + /** @test */ + public function iterator() + { + $client = new MockMollieClient([ + GetPaginatedSettlementsRequest::class => MockResponse::ok('settlement-list'), + DynamicGetRequest::class => MockResponse::ok('empty-list', 'settlements'), + ]); + + foreach ($client->settlements->iterator('stl_123', 50, ['reference' => 'test']) as $settlement) { + $this->assertSettlement($settlement); + } + } + + protected function assertSettlement(Settlement $settlement) + { + $this->assertInstanceOf(Settlement::class, $settlement); + $this->assertEquals('settlement', $settlement->resource); + $this->assertNotEmpty($settlement->id); + $this->assertNotEmpty($settlement->reference); + $this->assertNotEmpty($settlement->settledAt); + $this->assertNotEmpty($settlement->status); + $this->assertNotEmpty($settlement->amount); + $this->assertNotEmpty($settlement->_links); + } +} diff --git a/tests/EndpointCollection/SubscriptionEndpointCollectionTest.php b/tests/EndpointCollection/SubscriptionEndpointCollectionTest.php new file mode 100644 index 000000000..31af75396 --- /dev/null +++ b/tests/EndpointCollection/SubscriptionEndpointCollectionTest.php @@ -0,0 +1,194 @@ + MockResponse::created('subscription'), + ]); + + $customer = new Customer($client); + $customer->id = 'cst_kEn1PlbGa'; + + /** @var Subscription $subscription */ + $subscription = $client->subscriptions->createFor($customer, [ + 'amount' => [ + 'currency' => 'EUR', + 'value' => '25.00', + ], + 'interval' => '1 month', + 'description' => 'Monthly subscription', + 'webhookUrl' => 'https://example.org/webhook', + ]); + + $this->assertSubscription($subscription); + } + + /** @test */ + public function get_for() + { + $client = new MockMollieClient([ + GetSubscriptionRequest::class => MockResponse::ok('subscription'), + ]); + + $customer = new Customer($client); + $customer->id = 'cst_kEn1PlbGa'; + + /** @var Subscription $subscription */ + $subscription = $client->subscriptions->getFor($customer, 'sub_rVKGtNd6s3'); + + $this->assertSubscription($subscription); + } + + /** @test */ + public function update_for() + { + $client = new MockMollieClient([ + UpdateSubscriptionRequest::class => MockResponse::ok('subscription'), + ]); + + $customer = new Customer($client); + $customer->id = 'cst_kEn1PlbGa'; + + /** @var Subscription $subscription */ + $subscription = $client->subscriptions->update($customer->id, 'sub_rVKGtNd6s3', [ + 'amount' => [ + 'currency' => 'EUR', + 'value' => '30.00', + ], + 'description' => 'Updated subscription', + ]); + + $this->assertSubscription($subscription); + } + + /** @test */ + public function cancel_for() + { + $client = new MockMollieClient([ + CancelSubscriptionRequest::class => MockResponse::noContent(), + ]); + + $customer = new Customer($client); + $customer->id = 'cst_kEn1PlbGa'; + + $client->subscriptions->cancelFor($customer, 'sub_rVKGtNd6s3'); + + // Test passes if no exception is thrown + $this->assertTrue(true); + } + + /** @test */ + public function page_for() + { + $client = new MockMollieClient([ + GetPaginatedSubscriptionsRequest::class => MockResponse::ok('subscription-list'), + ]); + + $customer = new Customer($client); + $customer->id = 'cst_kEn1PlbGa'; + + /** @var SubscriptionCollection $subscriptions */ + $subscriptions = $client->subscriptions->pageFor($customer); + + $this->assertInstanceOf(SubscriptionCollection::class, $subscriptions); + $this->assertGreaterThan(0, $subscriptions->count()); + $this->assertGreaterThan(0, count($subscriptions)); + + foreach ($subscriptions as $subscription) { + $this->assertSubscription($subscription); + } + } + + /** @test */ + public function iterator_for() + { + $client = new MockMollieClient([ + GetPaginatedSubscriptionsRequest::class => MockResponse::ok('subscription-list'), + DynamicGetRequest::class => MockResponse::ok('empty-list', 'subscriptions'), + ]); + + $customer = new Customer($client); + $customer->id = 'cst_kEn1PlbGa'; + + foreach ($client->subscriptions->iteratorFor($customer) as $subscription) { + $this->assertSubscription($subscription); + } + } + + /** @test */ + public function all_for_id() + { + $client = new MockMollieClient([ + GetAllPaginatedSubscriptionsRequest::class => MockResponse::ok('subscription-list'), + ]); + + /** @var SubscriptionCollection $subscriptions */ + $subscriptions = $client->subscriptions->allForId( + 'sub_123', + 50, + ['profile_id' => 'prf_123'] + ); + + $this->assertInstanceOf(SubscriptionCollection::class, $subscriptions); + $this->assertGreaterThan(0, $subscriptions->count()); + + foreach ($subscriptions as $subscription) { + $this->assertSubscription($subscription); + } + } + + /** @test */ + public function iterator_for_all() + { + $client = new MockMollieClient([ + GetAllPaginatedSubscriptionsRequest::class => MockResponse::ok('subscription-list'), + DynamicGetRequest::class => MockResponse::ok('empty-list', 'subscriptions'), + ]); + + foreach ( + $client->subscriptions->iteratorForAll( + 'sub_123', + 50, + ['profile_id' => 'prf_123'], + true + ) as $subscription + ) { + $this->assertSubscription($subscription); + } + } + + protected function assertSubscription(Subscription $subscription) + { + $this->assertInstanceOf(Subscription::class, $subscription); + $this->assertEquals('subscription', $subscription->resource); + $this->assertNotEmpty($subscription->id); + $this->assertNotEmpty($subscription->mode); + $this->assertNotEmpty($subscription->createdAt); + $this->assertNotEmpty($subscription->status); + $this->assertNotEmpty($subscription->amount); + $this->assertNotEmpty($subscription->times); + $this->assertNotEmpty($subscription->interval); + $this->assertNotEmpty($subscription->description); + $this->assertNotEmpty($subscription->webhookUrl); + $this->assertNotEmpty($subscription->_links); + } +} diff --git a/tests/EndpointCollection/SubscriptionPaymentEndpointCollectionTest.php b/tests/EndpointCollection/SubscriptionPaymentEndpointCollectionTest.php new file mode 100644 index 000000000..faeed67a1 --- /dev/null +++ b/tests/EndpointCollection/SubscriptionPaymentEndpointCollectionTest.php @@ -0,0 +1,71 @@ + MockResponse::ok('payment-list'), + ]); + + $subscription = new Subscription( + $client, + ); + $subscription->id = 'sub_rVKGtNd6s3'; + $subscription->customerId = 'cust_kEn1PlbGa'; + + /** @var PaymentCollection $payments */ + $payments = $client->subscriptionPayments->pageFor($subscription); + + $this->assertInstanceOf(PaymentCollection::class, $payments); + $this->assertGreaterThan(0, $payments->count()); + + foreach ($payments as $payment) { + $this->assertPayment($payment); + } + } + + /** @test */ + public function iterator_for() + { + $client = new MockMollieClient([ + GetPaginatedSubscriptionPaymentsRequest::class => MockResponse::ok('payment-list'), + DynamicGetRequest::class => MockResponse::ok('empty-list', 'payments'), + ]); + + $subscription = new Subscription( + $client, + ); + $subscription->id = 'sub_rVKGtNd6s3'; + $subscription->customerId = 'cust_kEn1PlbGa'; + + foreach ($client->subscriptionPayments->iteratorFor($subscription) as $payment) { + $this->assertPayment($payment); + } + } + + protected function assertPayment(Payment $payment) + { + $this->assertInstanceOf(Payment::class, $payment); + $this->assertEquals('payment', $payment->resource); + $this->assertNotEmpty($payment->id); + $this->assertNotEmpty($payment->amount); + $this->assertNotEmpty($payment->description); + $this->assertNotEmpty($payment->createdAt); + $this->assertNotEmpty($payment->status); + $this->assertNotEmpty($payment->profileId); + $this->assertNotEmpty($payment->_links); + } +} diff --git a/tests/EndpointCollection/TerminalEndpointCollectionTest.php b/tests/EndpointCollection/TerminalEndpointCollectionTest.php new file mode 100644 index 000000000..37fffc784 --- /dev/null +++ b/tests/EndpointCollection/TerminalEndpointCollectionTest.php @@ -0,0 +1,75 @@ + MockResponse::ok('terminal'), + ]); + + /** @var Terminal $terminal */ + $terminal = $client->terminals->get('term_7jKQR2wmKx'); + + $this->assertTerminal($terminal); + } + + /** @test */ + public function page() + { + $client = new MockMollieClient([ + GetPaginatedTerminalsRequest::class => MockResponse::ok('terminal-list'), + DynamicGetRequest::class => MockResponse::ok('empty-list', 'terminals'), + ]); + + /** @var TerminalCollection $terminals */ + $terminals = $client->terminals->page(); + + $this->assertInstanceOf(TerminalCollection::class, $terminals); + $this->assertGreaterThan(0, $terminals->count()); + + foreach ($terminals as $terminal) { + $this->assertTerminal($terminal); + } + } + + /** @test */ + public function iterator() + { + $client = new MockMollieClient([ + GetPaginatedTerminalsRequest::class => MockResponse::ok('terminal-list'), + DynamicGetRequest::class => MockResponse::ok('empty-list', 'terminals'), + ]); + + foreach ($client->terminals->iterator() as $terminal) { + $this->assertTerminal($terminal); + } + } + + protected function assertTerminal(Terminal $terminal) + { + $this->assertInstanceOf(Terminal::class, $terminal); + $this->assertEquals('terminal', $terminal->resource); + $this->assertNotEmpty($terminal->id); + $this->assertNotEmpty($terminal->profileId); + $this->assertNotEmpty($terminal->status); + $this->assertNotEmpty($terminal->brand); + $this->assertNotEmpty($terminal->model); + $this->assertNotEmpty($terminal->serialNumber); + $this->assertNotEmpty($terminal->currency); + $this->assertNotEmpty($terminal->createdAt); + $this->assertNotEmpty($terminal->_links); + } +} diff --git a/tests/EndpointCollection/WalletEndpointCollectionTest.php b/tests/EndpointCollection/WalletEndpointCollectionTest.php new file mode 100644 index 000000000..0a0709ef8 --- /dev/null +++ b/tests/EndpointCollection/WalletEndpointCollectionTest.php @@ -0,0 +1,42 @@ + MockResponse::ok('apple-pay-session'), + ]); + + $applePaySession = $client->wallets->requestApplePayPaymentSession( + 'pay.example.org', + 'https://apple-pay-gateway.example.com/paymentservices/paymentSession', + [ + 'displayName' => "Chuck Norris's Store", + ] + ); + + $this->assertInstanceOf(AnyResource::class, $applePaySession); + /** @phpstan-ignore-next-line */ + $this->assertNotEmpty($applePaySession->domainName); + /** @phpstan-ignore-next-line */ + $this->assertNotEmpty($applePaySession->displayName); + /** @phpstan-ignore-next-line */ + $this->assertNotEmpty($applePaySession->merchantIdentifier); + /** @phpstan-ignore-next-line */ + $this->assertNotEmpty($applePaySession->merchantSessionIdentifier); + /** @phpstan-ignore-next-line */ + $this->assertNotEmpty($applePaySession->nonce); + /** @phpstan-ignore-next-line */ + $this->assertNotEmpty($applePaySession->signature); + } +} diff --git a/tests/Fake/MockMollieHttpAdapterTest.php b/tests/Fake/MockMollieHttpAdapterTest.php new file mode 100644 index 000000000..370235872 --- /dev/null +++ b/tests/Fake/MockMollieHttpAdapterTest.php @@ -0,0 +1,127 @@ + MockResponse::ok(['test' => 'data']), + ]); + + $pendingRequest = new PendingRequest(new MockMollieClient, new DynamicGetRequest('')); + + $response = $adapter->sendRequest($pendingRequest); + + $this->assertEquals(200, $response->status()); + $this->assertEquals('{"test":"data"}', $response->body()); + } + + /** @test */ + public function can_handle_callback_for_expected_response() + { + $adapter = new MockMollieHttpAdapter([ + DynamicGetRequest::class => fn (PendingRequest $pendingRequest) => MockResponse::ok([ + 'test' => $pendingRequest->query()->get('test'), + ]), + ]); + + $pendingRequest = new PendingRequest(new MockMollieClient, new DynamicGetRequest('', ['test' => 'data'])); + + $response = $adapter->sendRequest($pendingRequest); + + $this->assertEquals(200, $response->status()); + $this->assertEquals('{"test":"data"}', $response->body()); + } + + /** @test */ + public function it_throws_exception_for_unexpected_request() + { + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('The request class '.DynamicGetRequest::class.' is not expected.'); + + $adapter = new MockMollieHttpAdapter([]); + $pendingRequest = new PendingRequest(new MockMollieClient, new DynamicGetRequest('')); + + $adapter->sendRequest($pendingRequest); + } + + /** @test */ + public function it_handles_sequence_mock_responses() + { + $adapter = new MockMollieHttpAdapter([ + DynamicGetRequest::class => new SequenceMockResponse( + MockResponse::ok(['first' => 'response']), + MockResponse::ok(['second' => 'response']), + ), + ]); + + $pendingRequest = new PendingRequest(new MockMollieClient, new DynamicGetRequest('')); + + // First request + /** @var Response $response */ + $response = $adapter->sendRequest($pendingRequest); + $this->assertEquals('{"first":"response"}', $response->body()); + + // Second request + $response2 = $adapter->sendRequest($pendingRequest); + $this->assertEquals('{"second":"response"}', $response2->body()); + } + + /** @test */ + public function it_records_requests_and_can_assert_on_them() + { + $adapter = new MockMollieHttpAdapter([ + DynamicGetRequest::class => MockResponse::ok(), + ]); + + $pendingRequest = new PendingRequest(new MockMollieClient, new DynamicGetRequest('')); + + $adapter->sendRequest($pendingRequest); + + // Test assertSent with class name + $adapter->assertSent(DynamicGetRequest::class); + + // Test assertSent with callback + $adapter->assertSent(function ($request) use ($pendingRequest) { + return $request === $pendingRequest->getRequest(); + }); + + // Test assertSentCount + $adapter->assertSentCount(1); + } + + /** @test */ + public function it_returns_recorded_requests() + { + $adapter = new MockMollieHttpAdapter([ + DynamicGetRequest::class => MockResponse::ok(), + ]); + + $pendingRequest = new PendingRequest(new MockMollieClient, new DynamicGetRequest('')); + + $adapter->sendRequest($pendingRequest); + + // Test recorded without callback + $recorded = $adapter->recorded(); + $this->assertCount(1, $recorded); + $this->assertSame($pendingRequest->getRequest(), $recorded[0][0]); + + // Test recorded with callback + $this->assertCount(1, $adapter->recorded(function ($request) use ($pendingRequest) { + return $request === $pendingRequest->getRequest(); + })); + } +} diff --git a/tests/Fake/MockResponseTest.php b/tests/Fake/MockResponseTest.php new file mode 100644 index 000000000..08e20f1e9 --- /dev/null +++ b/tests/Fake/MockResponseTest.php @@ -0,0 +1,49 @@ +assertEquals($jsonString, $response->body()); + } + + /** @test */ + public function body_converts_array_to_json_string() + { + $array = ['key' => 'value']; + $response = new MockResponse($array); + + $this->assertEquals(json_encode($array), $response->body()); + } + + /** @test */ + public function body_loads_json_file_when_not_json_string() + { + $response = new MockResponse('payment'); + + $body = $response->body(); + + $this->assertJson($body); + $this->assertStringContainsString('payment', $body); + } + + /** @test */ + public function body_replaces_resource_id_placeholder() + { + $response = new MockResponse('payment', 200, 'tr_12345'); + + $body = $response->body(); + + $this->assertStringContainsString('tr_12345', $body); + $this->assertStringNotContainsString('{{ RESOURCE_ID }}', $body); + } +} diff --git a/tests/Fixtures/Requests/DynamicDeleteRequest.php b/tests/Fixtures/Requests/DynamicDeleteRequest.php new file mode 100644 index 000000000..fde2f97e3 --- /dev/null +++ b/tests/Fixtures/Requests/DynamicDeleteRequest.php @@ -0,0 +1,35 @@ +payload = $payload; + } + + protected function defaultPayload(): array + { + return $this->payload; + } +} diff --git a/tests/Fixtures/Requests/DynamicGetRequest.php b/tests/Fixtures/Requests/DynamicGetRequest.php new file mode 100644 index 000000000..189ae9351 --- /dev/null +++ b/tests/Fixtures/Requests/DynamicGetRequest.php @@ -0,0 +1,8 @@ +assertFalse($adapter->debuggingIsActive()); + + $adapter->enableDebugging(); + $this->assertTrue($adapter->debuggingIsActive()); + + $adapter->disableDebugging(); + $this->assertFalse($adapter->debuggingIsActive()); + } + + /** @test */ + public function when_debugging_an_api_exception_includes_the_request() + { + $guzzleClient = $this->createMock(Client::class); + $guzzleClient + ->expects($this->once()) + ->method('send') + ->with($this->isInstanceOf(RequestInterface::class)) + ->willThrowException( + new ConnectException( + 'Mock exception', + new Request('POST', 'https://api.mollie.com') + ) + ); + + $adapter = new GuzzleMollieHttpAdapter($guzzleClient); + $adapter->enableDebugging(); + + $request = new DynamicGetRequest('https://api.mollie.com/v2/payments'); + $pendingRequest = new PendingRequest(new MockMollieClient, $request); + + try { + $adapter->sendRequest($pendingRequest); + } catch (ApiException $e) { + $this->assertInstanceOf(RequestInterface::class, $e->getRequest()); + } + } + + /** @test */ + public function when_not_debugging_an_api_exception_is_excluded_from_the_request() + { + $guzzleClient = $this->createMock(Client::class); + $guzzleClient + ->expects($this->once()) + ->method('send') + ->with($this->isInstanceOf(RequestInterface::class)) + ->willThrowException( + new ConnectException( + 'Mock exception', + new Request('POST', 'https://api.mollie.com') + ) + ); + + $adapter = new GuzzleMollieHttpAdapter($guzzleClient); + $this->assertFalse($adapter->debuggingIsActive()); + + $request = new DynamicGetRequest('https://api.mollie.com/v2/payments'); + $pendingRequest = new PendingRequest(new MockMollieClient, $request); + + try { + $adapter->sendRequest($pendingRequest); + } catch (ApiException $e) { + $this->assertNull($e->getRequest()); + } + } +} diff --git a/tests/Mollie/API/HttpAdapter/MollieHttpAdapterPickerTest.php b/tests/Http/Adapter/MollieHttpAdapterPickerTest.php similarity index 64% rename from tests/Mollie/API/HttpAdapter/MollieHttpAdapterPickerTest.php rename to tests/Http/Adapter/MollieHttpAdapterPickerTest.php index 42e7523d4..672e75859 100644 --- a/tests/Mollie/API/HttpAdapter/MollieHttpAdapterPickerTest.php +++ b/tests/Http/Adapter/MollieHttpAdapterPickerTest.php @@ -1,27 +1,28 @@ pickHttpAdapter(null); - $this->assertInstanceOf(Guzzle6And7MollieHttpAdapter::class, $adapter); + $this->assertInstanceOf(GuzzleMollieHttpAdapter::class, $adapter); } /** @test */ - public function returnsTheAdapterThatWasPassedIn() + public function returns_the_adapter_that_was_passed_in() { $picker = new MollieHttpAdapterPicker; $mockAdapter = new MockMollieHttpAdapter; @@ -33,18 +34,18 @@ public function returnsTheAdapterThatWasPassedIn() } /** @test */ - public function wrapsAGuzzleClientIntoAnAdapter() + public function wraps_a_guzzle_client_into_an_adapter() { $picker = new MollieHttpAdapterPicker; $guzzleClient = new GuzzleClient; $adapter = $picker->pickHttpAdapter($guzzleClient); - $this->assertInstanceOf(Guzzle6And7MollieHttpAdapter::class, $adapter); + $this->assertInstanceOf(GuzzleMollieHttpAdapter::class, $adapter); } /** @test */ - public function throwsAnExceptionWhenReceivingAnUnrecognizedClient() + public function throws_an_exception_when_receiving_an_unrecognized_client() { $this->expectExceptionObject(new UnrecognizedClientException('The provided http client or adapter was not recognized')); $picker = new MollieHttpAdapterPicker; diff --git a/tests/Mollie/Guzzle/RetryMiddlewareFactoryTest.php b/tests/Http/Adapter/RetryMiddlewareFactoryTest.php similarity index 57% rename from tests/Mollie/Guzzle/RetryMiddlewareFactoryTest.php rename to tests/Http/Adapter/RetryMiddlewareFactoryTest.php index 1ee85e713..084cf373f 100644 --- a/tests/Mollie/Guzzle/RetryMiddlewareFactoryTest.php +++ b/tests/Http/Adapter/RetryMiddlewareFactoryTest.php @@ -1,6 +1,6 @@ 'Bar']), ] ); @@ -33,46 +33,46 @@ public function testRetriesConnectException() $this->assertEquals(200, $finalResponse->getStatusCode()); } - public function testRetryLimit() + public function test_retry_limit() { - $middlewareFactory = new Guzzle6And7RetryMiddlewareFactory; + $middlewareFactory = new GuzzleRetryMiddlewareFactory; $mock = new MockHandler( [ - new ConnectException("Error 1", new Request('GET', 'test')), - new ConnectException("Error 2", new Request('GET', 'test')), - new ConnectException("Error 3", new Request('GET', 'test')), - new ConnectException("Error 4", new Request('GET', 'test')), - new ConnectException("Error 5", new Request('GET', 'test')), - new ConnectException("Error 6", new Request('GET', 'test')), + new ConnectException('Error 1', new Request('GET', 'test')), + new ConnectException('Error 2', new Request('GET', 'test')), + new ConnectException('Error 3', new Request('GET', 'test')), + new ConnectException('Error 4', new Request('GET', 'test')), + new ConnectException('Error 5', new Request('GET', 'test')), + new ConnectException('Error 6', new Request('GET', 'test')), ] ); $handler = HandlerStack::create($mock); $handler->push($middlewareFactory->retry(false)); - $client = new Client([ 'handler' => $handler ]); + $client = new Client(['handler' => $handler]); $this->expectException(ConnectException::class); - $this->expectExceptionMessage("Error 6"); + $this->expectExceptionMessage('Error 6'); $client->request('GET', '/')->getStatusCode(); } - public function testRetryDelay() + public function test_retry_delay() { - $middlewareFactory = new Guzzle6And7RetryMiddlewareFactory; + $middlewareFactory = new GuzzleRetryMiddlewareFactory; $mock = new MockHandler( [ - new ConnectException("+1 second delay", new Request('GET', 'test')), - new ConnectException("+2 second delay", new Request('GET', 'test')), + new ConnectException('+1 second delay', new Request('GET', 'test')), + new ConnectException('+2 second delay', new Request('GET', 'test')), new Response(200), ] ); $handler = HandlerStack::create($mock); $handler->push($middlewareFactory->retry(true)); - $client = new Client([ 'handler' => $handler ]); + $client = new Client(['handler' => $handler]); $startTime = time(); $client->request('GET', '/')->getStatusCode(); diff --git a/tests/Http/Auth/BearetTokenAuthenticatorTest.php b/tests/Http/Auth/BearetTokenAuthenticatorTest.php new file mode 100644 index 000000000..79027398d --- /dev/null +++ b/tests/Http/Auth/BearetTokenAuthenticatorTest.php @@ -0,0 +1,58 @@ +createMock(ArrayStore::class); + $headers + ->expects($this->once()) + ->method('add') + ->with('Authorization', "Bearer {$token}"); + + $pendingRequest = $this->createMock(PendingRequest::class); + $pendingRequest + ->expects($this->once()) + ->method('headers') + ->willReturn($headers); + + $authenticator->authenticate($pendingRequest); + } + + /** + * @test + */ + public function authenticate_with_token_trimming() + { + $token = ' test_token_with_spaces '; + $trimmedToken = 'test_token_with_spaces'; + $authenticator = new BearerTokenAuthenticator($token); + + $headers = $this->createMock(ArrayStore::class); + $headers + ->expects($this->once()) + ->method('add') + ->with('Authorization', "Bearer {$trimmedToken}"); + + $pendingRequest = $this->createMock(PendingRequest::class); + $pendingRequest + ->expects($this->once()) + ->method('headers') + ->willReturn($headers); + + $authenticator->authenticate($pendingRequest); + } +} diff --git a/tests/Http/Middleware/GuardResponseTest.php b/tests/Http/Middleware/GuardResponseTest.php new file mode 100644 index 000000000..a583c4faf --- /dev/null +++ b/tests/Http/Middleware/GuardResponseTest.php @@ -0,0 +1,103 @@ +createMock(Response::class); + + // Mock the status method to return a status other than HTTP_NO_CONTENT + $responseMock->expects($this->once()) + ->method('status') + ->willReturn(ResponseStatusCode::HTTP_OK); + + // Mock the body method to return an empty body + $responseMock->expects($this->once()) + ->method('isEmpty') + ->willReturn(true); + + $guardResponse = new GuardResponse; + + // Expect the ApiException to be thrown due to no response body + $this->expectException(ApiException::class); + $this->expectExceptionMessage('No response body found.'); + + $guardResponse($responseMock); + } + + /** + * @test + */ + public function it_does_not_throw_exception_if_http_no_content(): void + { + $responseMock = $this->createMock(Response::class); + + // Mock the status method to return HTTP_NO_CONTENT + $responseMock->expects($this->once()) + ->method('status') + ->willReturn(ResponseStatusCode::HTTP_NO_CONTENT); + + // Mock the body method to return an empty body + $responseMock->expects($this->once()) + ->method('isEmpty') + ->willReturn(true); + + $guardResponse = new GuardResponse; + + // No exception should be thrown + $guardResponse($responseMock); + } + + /** + * @test + */ + public function it_throws_exception_if_response_contains_error_message(): void + { + $responseMock = $this->createMock(Response::class); + + // Mock the json method to return an error object + $responseMock->expects($this->once()) + ->method('json') + ->willReturn((object) ['error' => (object) ['message' => 'Some error occurred']]); + + $guardResponse = new GuardResponse; + + // Expect the ApiException to be thrown due to error in the response + $this->expectException(ApiException::class); + $this->expectExceptionMessage('Some error occurred'); + + $guardResponse($responseMock); + } + + /** + * @test + */ + public function it_passes_if_valid_json_and_no_error_message(): void + { + $responseMock = $this->createMock(Response::class); + + // Mock the json method to return valid data + $responseMock->expects($this->once()) + ->method('json') + ->willReturn((object) ['data' => 'valid']); + + $guardResponse = new GuardResponse; + + // No exception should be thrown + $guardResponse($responseMock); + + // If the test reaches here without exceptions, it passes + $this->assertTrue(true); + } +} diff --git a/tests/Http/Middleware/HandlersTest.php b/tests/Http/Middleware/HandlersTest.php new file mode 100644 index 000000000..91e5ca1b7 --- /dev/null +++ b/tests/Http/Middleware/HandlersTest.php @@ -0,0 +1,65 @@ +add(fn () => null); + + $this->assertCount(1, $handlers->getHandlers()); + } + + /** @test */ + public function handlers_are_executed_in_the_correct_order(): void + { + $output = []; + + $handlers = new Handlers; + $handlers->add(function ($value) use (&$output) { + $output[] = 1; + + return new TestViableResponse($output); + }, 'a', MiddlewarePriority::LOW); + + $handlers->add(function () use (&$output) { + $output[] = 2; + }, 'b', MiddlewarePriority::MEDIUM); + + $handlers->add(function () use (&$output) { + $output[] = 3; + }, 'c', MiddlewarePriority::HIGH); + + $this->assertCount(3, $handlers->getHandlers()); + + /** @var TestViableResponse $response */ + $response = $handlers->execute($output); + + $this->assertInstanceOf(TestViableResponse::class, $response); + $this->assertEquals([3, 2, 1], $response->toArray()); + } +} + +class TestViableResponse implements Arrayable, ViableResponse +{ + public array $output = []; + + public function __construct(array $output) + { + $this->output = $output; + } + + public function toArray(): array + { + return $this->output; + } +} diff --git a/tests/Http/MiddlewareTest.php b/tests/Http/MiddlewareTest.php new file mode 100644 index 000000000..3abadd9be --- /dev/null +++ b/tests/Http/MiddlewareTest.php @@ -0,0 +1,85 @@ +onRequest(function (PendingRequest $pendingRequest) { + $pendingRequest->headers()->add('Foo', 'Bar'); + + return $pendingRequest; + }); + + $result = $middlewareHandlers->executeOnRequest( + new PendingRequest(new MockMollieClient, new DynamicGetRequest('')) + ); + + $this->assertEquals('Bar', $result->headers()->get('Foo')); + } + + /** + * @test + */ + public function it_can_add_response_middleware_and_execute_it(): void + { + $middlewareHandlers = new Middleware; + + $middlewareHandlers->onResponse(function (Response $response) { + $this->assertTrue($response->successful()); + + return $response; + }); + + // Create a mock response + $responseMock = $this->createMock(Response::class); + $responseMock->method('successful')->willReturn(true); + + $result = $middlewareHandlers->executeOnResponse($responseMock); + + $this->assertTrue($result->successful()); + } + + /** + * @test + */ + public function it_can_merge_middleware_handlers(): void + { + $middlewareHandlers1 = new Middleware; + $middlewareHandlers2 = new Middleware; + + $middlewareHandlers1->onRequest(function (PendingRequest $pendingRequest) { + $pendingRequest->headers()->add('Request-One', 'One'); + + return $pendingRequest; + }); + + $middlewareHandlers2->onRequest(function (PendingRequest $pendingRequest) { + $pendingRequest->headers()->add('Request-Two', 'Two'); + + return $pendingRequest; + }); + + $middlewareHandlers1->merge($middlewareHandlers2); + + $result = $middlewareHandlers1->executeOnRequest( + new PendingRequest(new MockMollieClient, new DynamicGetRequest('')) + ); + + $this->assertEquals('One', $result->headers()->get('Request-One')); + $this->assertEquals('Two', $result->headers()->get('Request-Two')); + } +} diff --git a/tests/Http/Requests/ApplePayPaymentSessionRequestTest.php b/tests/Http/Requests/ApplePayPaymentSessionRequestTest.php new file mode 100644 index 000000000..b0620d52c --- /dev/null +++ b/tests/Http/Requests/ApplePayPaymentSessionRequestTest.php @@ -0,0 +1,52 @@ + MockResponse::ok('apple-pay-session'), + ]); + + $payload = new RequestApplePayPaymentSessionPayload( + 'https://example.com', + 'Example Domain', + 'EUR' + ); + + $request = new ApplePayPaymentSessionRequest($payload); + + /** @var AnyResource */ + $appleSession = $client->send($request); + + $this->assertTrue($appleSession->getResponse()->successful()); + $this->assertInstanceOf(AnyResource::class, $appleSession); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $payload = new RequestApplePayPaymentSessionPayload( + 'https://example.com', + 'Example Domain', + 'EUR' + ); + + $request = new ApplePayPaymentSessionRequest($payload); + + $this->assertEquals( + 'wallets/applepay/sessions', + $request->resolveResourcePath() + ); + } +} diff --git a/tests/Http/Requests/CancelPaymentRefundRequestTest.php b/tests/Http/Requests/CancelPaymentRefundRequestTest.php new file mode 100644 index 000000000..800705afe --- /dev/null +++ b/tests/Http/Requests/CancelPaymentRefundRequestTest.php @@ -0,0 +1,45 @@ + MockResponse::noContent(''), + ]); + + $paymentId = 'tr_7UhSN1zuXS'; + $refundId = 're_4qqhO89gsT'; + + $request = new CancelPaymentRefundRequest($paymentId, $refundId); + + /** @var Response */ + $response = $client->send($request); + + $this->assertTrue($response->successful()); + $this->assertEquals(204, $response->status()); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $paymentId = 'tr_7UhSN1zuXS'; + $refundId = 're_4qqhO89gsT'; + + $request = new CancelPaymentRefundRequest($paymentId, $refundId); + + $this->assertEquals( + "payments/{$paymentId}/refunds/{$refundId}", + $request->resolveResourcePath() + ); + } +} diff --git a/tests/Http/Requests/CancelPaymentRequestTest.php b/tests/Http/Requests/CancelPaymentRequestTest.php new file mode 100644 index 000000000..58b661498 --- /dev/null +++ b/tests/Http/Requests/CancelPaymentRequestTest.php @@ -0,0 +1,41 @@ + MockResponse::ok('payment'), + ]); + + $paymentId = 'tr_WDqYK6vllg'; + $request = new CancelPaymentRequest($paymentId); + + /** @var Payment */ + $payment = $client->send($request); + + $this->assertTrue($payment->getResponse()->successful()); + $this->assertInstanceOf(Payment::class, $payment); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $paymentId = 'tr_WDqYK6vllg'; + $request = new CancelPaymentRequest($paymentId); + + $this->assertEquals( + "payments/{$paymentId}", + $request->resolveResourcePath() + ); + } +} diff --git a/tests/Http/Requests/CancelSessionRequestTest.php b/tests/Http/Requests/CancelSessionRequestTest.php new file mode 100644 index 000000000..590e4ee79 --- /dev/null +++ b/tests/Http/Requests/CancelSessionRequestTest.php @@ -0,0 +1,41 @@ + MockResponse::ok('session'), + ]); + + $sessionId = 'sess_pNxqdWEFws'; + $request = new CancelSessionRequest($sessionId); + + /** @var Session */ + $session = $client->send($request); + + $this->assertTrue($session->getResponse()->successful()); + $this->assertInstanceOf(Session::class, $session); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $sessionId = 'sess_pNxqdWEFws'; + $request = new CancelSessionRequest($sessionId); + + $this->assertEquals( + "sessions/{$sessionId}", + $request->resolveResourcePath() + ); + } +} diff --git a/tests/Http/Requests/CancelSubscriptionRequestTest.php b/tests/Http/Requests/CancelSubscriptionRequestTest.php new file mode 100644 index 000000000..976503a62 --- /dev/null +++ b/tests/Http/Requests/CancelSubscriptionRequestTest.php @@ -0,0 +1,43 @@ + MockResponse::ok('subscription'), + ]); + + $customerId = 'cst_kEn1PlbGa'; + $subscriptionId = 'sub_rVKGtNd6s3'; + $request = new CancelSubscriptionRequest($customerId, $subscriptionId); + + /** @var Subscription */ + $subscription = $client->send($request); + + $this->assertTrue($subscription->getResponse()->successful()); + $this->assertInstanceOf(Subscription::class, $subscription); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $customerId = 'cst_kEn1PlbGa'; + $subscriptionId = 'sub_rVKGtNd6s3'; + $request = new CancelSubscriptionRequest($customerId, $subscriptionId); + + $this->assertEquals( + "customers/{$customerId}/subscriptions/{$subscriptionId}", + $request->resolveResourcePath() + ); + } +} diff --git a/tests/Http/Requests/CreateClientLinkRequestTest.php b/tests/Http/Requests/CreateClientLinkRequestTest.php new file mode 100644 index 000000000..9a6991d99 --- /dev/null +++ b/tests/Http/Requests/CreateClientLinkRequestTest.php @@ -0,0 +1,37 @@ + MockResponse::created('client-link'), + ]); + + $payload = new CreateClientLinkPayload( + new Owner('test@example.org', 'John', 'Doe'), + 'Test', + new OwnerAddress('NL') + ); + + $request = new CreateClientLinkRequest($payload); + + /** @var ClientLink */ + $clientLink = $client->send($request); + + $this->assertTrue($clientLink->getResponse()->successful()); + $this->assertInstanceOf(ClientLink::class, $clientLink); + } +} diff --git a/tests/Http/Requests/CreateCustomerPaymentRequestTest.php b/tests/Http/Requests/CreateCustomerPaymentRequestTest.php new file mode 100644 index 000000000..cd31c992c --- /dev/null +++ b/tests/Http/Requests/CreateCustomerPaymentRequestTest.php @@ -0,0 +1,54 @@ + MockResponse::created('payment'), + ]); + + $payload = new CreatePaymentPayload( + 'Test payment', + new Money('EUR', '10.00'), + 'https://example.org/redirect' + ); + + $request = new CreateCustomerPaymentRequest( + 'cst_123', + $payload, + new CreatePaymentQuery(true) + ); + + /** @var Payment */ + $payment = $client->send($request); + + $this->assertTrue($payment->getResponse()->successful()); + $this->assertInstanceOf(Payment::class, $payment); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $customerId = 'cst_123'; + $request = new CreateCustomerPaymentRequest($customerId, new CreatePaymentPayload( + 'Test payment', + new Money('EUR', '10.00'), + 'https://example.org/redirect' + )); + + $this->assertEquals("customers/{$customerId}/payments", $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/CreateCustomerRequestTest.php b/tests/Http/Requests/CreateCustomerRequestTest.php new file mode 100644 index 000000000..698b46d58 --- /dev/null +++ b/tests/Http/Requests/CreateCustomerRequestTest.php @@ -0,0 +1,45 @@ + MockResponse::created('customer'), + ]); + + $payload = new CreateCustomerPayload( + 'John Doe', + 'john@example.org' + ); + + $request = new CreateCustomerRequest($payload); + + /** @var Customer */ + $customer = $client->send($request); + + $this->assertTrue($customer->getResponse()->successful()); + $this->assertInstanceOf(Customer::class, $customer); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new CreateCustomerRequest(new CreateCustomerPayload( + 'John Doe', + 'john@example.org' + )); + + $this->assertEquals('customers', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/CreateMandateRequestTest.php b/tests/Http/Requests/CreateMandateRequestTest.php new file mode 100644 index 000000000..28954df89 --- /dev/null +++ b/tests/Http/Requests/CreateMandateRequestTest.php @@ -0,0 +1,54 @@ + MockResponse::created('mandate'), + ]); + + $customerId = 'cst_kEn1PlbGa'; + $payload = new CreateMandatePayload( + 'directdebit', + 'John Doe', + 'NL55INGB0000000000' + ); + + $request = new CreateMandateRequest($customerId, $payload); + + /** @var Mandate */ + $mandate = $client->send($request); + + $this->assertTrue($mandate->getResponse()->successful()); + $this->assertInstanceOf(Mandate::class, $mandate); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $customerId = 'cst_kEn1PlbGa'; + $payload = new CreateMandatePayload( + 'directdebit', + 'John Doe', + 'NL55INGB0000000000' + ); + + $request = new CreateMandateRequest($customerId, $payload); + + $this->assertEquals( + "customers/{$customerId}/mandates", + $request->resolveResourcePath() + ); + } +} diff --git a/tests/Http/Requests/CreatePaymentCaptureRequestTest.php b/tests/Http/Requests/CreatePaymentCaptureRequestTest.php new file mode 100644 index 000000000..7cc237025 --- /dev/null +++ b/tests/Http/Requests/CreatePaymentCaptureRequestTest.php @@ -0,0 +1,46 @@ + MockResponse::created('capture'), + ]); + + $payload = new CreatePaymentCapturePayload( + 'Test capture', + new Money('EUR', '10.00') + ); + + $request = new CreatePaymentCaptureRequest('tr_123', $payload); + + /** @var Capture */ + $capture = $client->send($request); + + $this->assertTrue($capture->getResponse()->successful()); + $this->assertInstanceOf(Capture::class, $capture); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new CreatePaymentCaptureRequest('tr_123', new CreatePaymentCapturePayload( + 'Test capture', + new Money('EUR', '10.00') + )); + + $this->assertEquals('payments/tr_123/captures', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/CreatePaymentLinkRequestTest.php b/tests/Http/Requests/CreatePaymentLinkRequestTest.php new file mode 100644 index 000000000..92f3230cf --- /dev/null +++ b/tests/Http/Requests/CreatePaymentLinkRequestTest.php @@ -0,0 +1,46 @@ + MockResponse::created('payment-link'), + ]); + + $payload = new CreatePaymentLinkPayload( + 'Test payment link', + new Money('EUR', '10.00') + ); + + $request = new CreatePaymentLinkRequest($payload); + + /** @var PaymentLink */ + $paymentLink = $client->send($request); + + $this->assertTrue($paymentLink->getResponse()->successful()); + $this->assertInstanceOf(PaymentLink::class, $paymentLink); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new CreatePaymentLinkRequest(new CreatePaymentLinkPayload( + 'Test payment link', + new Money('EUR', '10.00') + )); + + $this->assertEquals('payment-links', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/CreatePaymentRefundRequestTest.php b/tests/Http/Requests/CreatePaymentRefundRequestTest.php new file mode 100644 index 000000000..f5e5d6c3a --- /dev/null +++ b/tests/Http/Requests/CreatePaymentRefundRequestTest.php @@ -0,0 +1,53 @@ + MockResponse::created('refund'), + ]); + + $paymentId = 'tr_WDqYK6vllg'; + $payload = new CreateRefundPaymentPayload( + 'Order cancellation', + new Money('EUR', '10.00') + ); + + $request = new CreatePaymentRefundRequest($paymentId, $payload); + + /** @var Refund */ + $refund = $client->send($request); + + $this->assertTrue($refund->getResponse()->successful()); + $this->assertInstanceOf(Refund::class, $refund); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $paymentId = 'tr_WDqYK6vllg'; + $payload = new CreateRefundPaymentPayload( + 'Order cancellation', + new Money('EUR', '10.00') + ); + + $request = new CreatePaymentRefundRequest($paymentId, $payload); + + $this->assertEquals( + "payments/{$paymentId}/refunds", + $request->resolveResourcePath() + ); + } +} diff --git a/tests/Http/Requests/CreatePaymentRequestTest.php b/tests/Http/Requests/CreatePaymentRequestTest.php new file mode 100644 index 000000000..2bf148f21 --- /dev/null +++ b/tests/Http/Requests/CreatePaymentRequestTest.php @@ -0,0 +1,50 @@ + MockResponse::created('payment'), + ]); + + $payload = new CreatePaymentPayload( + 'Test payment', + new Money('EUR', '10.00'), + 'https://example.org/redirect', + 'https://example.org/webhook', + ); + + $request = new CreatePaymentRequest($payload); + + /** @var Payment */ + $payment = $client->send($request); + + $this->assertTrue($payment->getResponse()->successful()); + $this->assertInstanceOf(Payment::class, $payment); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new CreatePaymentRequest(new CreatePaymentPayload( + 'Test payment', + new Money('EUR', '10.00'), + 'https://example.org/redirect', + 'https://example.org/webhook' + )); + + $this->assertEquals('payments', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/CreateProfileRequestTest.php b/tests/Http/Requests/CreateProfileRequestTest.php new file mode 100644 index 000000000..83ef3b6d0 --- /dev/null +++ b/tests/Http/Requests/CreateProfileRequestTest.php @@ -0,0 +1,51 @@ + MockResponse::created('profile'), + ]); + + $payload = new CreateProfilePayload( + 'Test profile', + 'https://example.org', + 'test@example.org', + 'en_US', + '+31612345678' + ); + + $request = new CreateProfileRequest($payload); + + /** @var Profile */ + $profile = $client->send($request); + + $this->assertTrue($profile->getResponse()->successful()); + $this->assertInstanceOf(Profile::class, $profile); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new CreateProfileRequest(new CreateProfilePayload( + 'Test profile', + 'https://example.org', + 'test@example.org', + 'en_US', + '+31612345678' + )); + + $this->assertEquals('profiles', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/CreateSalesInvoiceRequestTest.php b/tests/Http/Requests/CreateSalesInvoiceRequestTest.php new file mode 100644 index 000000000..d6a8f5557 --- /dev/null +++ b/tests/Http/Requests/CreateSalesInvoiceRequestTest.php @@ -0,0 +1,98 @@ + MockResponse::created('sales-invoice'), + ]); + + $invoiceLines = [ + new InvoiceLine( + 'Monthly subscription fee', + 1, + '21', + new Money('EUR', '10,00'), + ), + ]; + + // Create a sales invoice + $payload = new CreateSalesInvoicePayload( + 'EUR', + SalesInvoiceStatus::DRAFT, + VatScheme::STANDARD, + VatMode::INCLUSIVE, + PaymentTerm::DAYS_30, + 'XXXXX', + new Recipient( + RecipientType::CONSUMER, + 'darth@vader.deathstar', + 'Sample Street 12b', + '2000 AA', + 'Amsterdam', + 'NL', + 'nl_NL' + ), + new DataCollection($invoiceLines) + ); + $request = new CreateSalesInvoiceRequest($payload); + + /** @var SalesInvoice */ + $salesInvoice = $client->send($request); + + $this->assertTrue($salesInvoice->getResponse()->successful()); + $this->assertInstanceOf(SalesInvoice::class, $salesInvoice); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new CreateSalesInvoiceRequest(new CreateSalesInvoicePayload( + 'EUR', + SalesInvoiceStatus::DRAFT, + VatScheme::STANDARD, + VatMode::INCLUSIVE, + PaymentTerm::DAYS_30, + 'XXXXX', + new Recipient( + RecipientType::CONSUMER, + 'darth@vader.deathstar', + 'Sample Street 12b', + '2000 AA', + 'Amsterdam', + 'NL', + 'nl_NL' + ), + new DataCollection([ + new InvoiceLine( + 'Monthly subscription fee', + 1, + '21', + new Money('EUR', '10,00'), + ), + ]) + )); + + $this->assertEquals('sales-invoices', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/CreateSessionRequestTest.php b/tests/Http/Requests/CreateSessionRequestTest.php new file mode 100644 index 000000000..5eea86b9c --- /dev/null +++ b/tests/Http/Requests/CreateSessionRequestTest.php @@ -0,0 +1,40 @@ + MockResponse::created('session'), + ]); + + $request = new CreateSessionRequest( + new AnyData(['foo' => 'bar']), + new AnyData(['baz' => 'qux']) + ); + + /** @var Session */ + $session = $client->send($request); + + $this->assertTrue($session->getResponse()->successful()); + $this->assertInstanceOf(Session::class, $session); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new CreateSessionRequest(new AnyData(['foo' => 'bar']), new AnyData(['baz' => 'qux'])); + + $this->assertEquals('sessions', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/CreateSubscriptionRequestTest.php b/tests/Http/Requests/CreateSubscriptionRequestTest.php new file mode 100644 index 000000000..4cf56145a --- /dev/null +++ b/tests/Http/Requests/CreateSubscriptionRequestTest.php @@ -0,0 +1,46 @@ + MockResponse::created('subscription'), + ]); + + $request = new CreateSubscriptionRequest('cst_123', new CreateSubscriptionPayload( + new Money('EUR', '10.00'), + '1 month', + 'Test subscription' + )); + + /** @var Subscription */ + $subscription = $client->send($request); + + $this->assertTrue($subscription->getResponse()->successful()); + $this->assertInstanceOf(Subscription::class, $subscription); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new CreateSubscriptionRequest('cst_123', new CreateSubscriptionPayload( + new Money('EUR', '10.00'), + '1 month', + 'Test subscription' + )); + + $this->assertEquals('customers/cst_123/subscriptions', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/DeleteCustomerRequestTest.php b/tests/Http/Requests/DeleteCustomerRequestTest.php new file mode 100644 index 000000000..052fa2ff9 --- /dev/null +++ b/tests/Http/Requests/DeleteCustomerRequestTest.php @@ -0,0 +1,36 @@ + MockResponse::noContent(), + ]); + + $request = new DeleteCustomerRequest('cst_123'); + + /** @var Response */ + $response = $client->send($request); + + $this->assertTrue($response->successful()); + $this->assertEquals(204, $response->status()); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new DeleteCustomerRequest('cst_123'); + + $this->assertEquals('customers/cst_123', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/DeletePaymentLinkRequestTest.php b/tests/Http/Requests/DeletePaymentLinkRequestTest.php new file mode 100644 index 000000000..f6f3ed1e9 --- /dev/null +++ b/tests/Http/Requests/DeletePaymentLinkRequestTest.php @@ -0,0 +1,36 @@ + MockResponse::noContent(), + ]); + + $request = new DeletePaymentLinkRequest('pl_123'); + + /** @var Response */ + $response = $client->send($request); + + $this->assertTrue($response->successful()); + $this->assertEquals(204, $response->status()); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new DeletePaymentLinkRequest('pl_123'); + + $this->assertEquals('payment-links/pl_123', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/DeleteProfileRequestTest.php b/tests/Http/Requests/DeleteProfileRequestTest.php new file mode 100644 index 000000000..f4f25b205 --- /dev/null +++ b/tests/Http/Requests/DeleteProfileRequestTest.php @@ -0,0 +1,41 @@ + MockResponse::noContent(''), + ]); + + $profileId = 'pfl_v9hTwCvYqw'; + $request = new DeleteProfileRequest($profileId); + + /** @var Response */ + $response = $client->send($request); + + $this->assertTrue($response->successful()); + $this->assertEquals(204, $response->status()); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $profileId = 'pfl_v9hTwCvYqw'; + $request = new DeleteProfileRequest($profileId); + + $this->assertEquals( + "profiles/{$profileId}", + $request->resolveResourcePath() + ); + } +} diff --git a/tests/Http/Requests/DeleteSalesInvoiceRequestTest.php b/tests/Http/Requests/DeleteSalesInvoiceRequestTest.php new file mode 100644 index 000000000..07ed626e1 --- /dev/null +++ b/tests/Http/Requests/DeleteSalesInvoiceRequestTest.php @@ -0,0 +1,35 @@ + MockResponse::noContent(), + ]); + + $request = new DeleteSalesInvoiceRequest('invoice_123'); + + /** @var Response */ + $response = $client->send($request); + + $this->assertTrue($response->successful()); + $this->assertEquals(204, $response->status()); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new DeleteSalesInvoiceRequest('invoice_123'); + $this->assertEquals('sales-invoices/invoice_123', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/DisableMethodIssuerRequestTest.php b/tests/Http/Requests/DisableMethodIssuerRequestTest.php new file mode 100644 index 000000000..89ba74e3e --- /dev/null +++ b/tests/Http/Requests/DisableMethodIssuerRequestTest.php @@ -0,0 +1,45 @@ + MockResponse::noContent(''), + ]); + + $profileId = 'pfl_v9hTwCvYqw'; + $methodId = 'ideal'; + $issuerId = 'INGBNL2A'; + $request = new DisableMethodIssuerRequest($profileId, $methodId, $issuerId); + + /** @var Response */ + $response = $client->send($request); + + $this->assertTrue($response->successful()); + $this->assertEquals(204, $response->status()); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $profileId = 'pfl_v9hTwCvYqw'; + $methodId = 'ideal'; + $issuerId = 'INGBNL2A'; + $request = new DisableMethodIssuerRequest($profileId, $methodId, $issuerId); + + $this->assertEquals( + "profiles/{$profileId}/methods/{$methodId}/issuers/{$issuerId}", + $request->resolveResourcePath() + ); + } +} diff --git a/tests/Http/Requests/DisableProfileMethodRequestTest.php b/tests/Http/Requests/DisableProfileMethodRequestTest.php new file mode 100644 index 000000000..beceb3371 --- /dev/null +++ b/tests/Http/Requests/DisableProfileMethodRequestTest.php @@ -0,0 +1,43 @@ + MockResponse::noContent(''), + ]); + + $profileId = 'pfl_v9hTwCvYqw'; + $methodId = 'ideal'; + $request = new DisableProfileMethodRequest($profileId, $methodId); + + /** @var Response */ + $response = $client->send($request); + + $this->assertTrue($response->successful()); + $this->assertEquals(204, $response->status()); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $profileId = 'pfl_v9hTwCvYqw'; + $methodId = 'ideal'; + $request = new DisableProfileMethodRequest($profileId, $methodId); + + $this->assertEquals( + "profiles/{$profileId}/methods/{$methodId}", + $request->resolveResourcePath() + ); + } +} diff --git a/tests/Http/Requests/DynamicGetRequestTest.php b/tests/Http/Requests/DynamicGetRequestTest.php new file mode 100644 index 000000000..2ac03a981 --- /dev/null +++ b/tests/Http/Requests/DynamicGetRequestTest.php @@ -0,0 +1,43 @@ + MockResponse::ok('payment'), + ]); + + $request = new DynamicGetRequest( + 'payments/tr_WDqYK6vllg', + ['testmode' => 'true'] + ); + + $request->setHydratableResource(Payment::class); + + /** @var Payment */ + $payment = $client->send($request); + + $this->assertTrue($payment->getResponse()->successful()); + $this->assertInstanceOf(Payment::class, $payment); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $path = 'payments/tr_WDqYK6vllg'; + $request = new DynamicGetRequest($path); + $request->setHydratableResource(Payment::class); + + $this->assertEquals($path, $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/DynamicRequestTest.php b/tests/Http/Requests/DynamicRequestTest.php new file mode 100644 index 000000000..547a2f74e --- /dev/null +++ b/tests/Http/Requests/DynamicRequestTest.php @@ -0,0 +1,38 @@ +setHydratableResource(Payment::class); + + $this->assertEquals(Payment::class, $request->getHydratableResource()); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $url = 'https://example.org'; + $request = new class($url) extends DynamicRequest + { + protected static string $method = Method::GET; + }; + + $request->setHydratableResource(Payment::class); + + $this->assertEquals($url, $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/EnableMethodIssuerRequestTest.php b/tests/Http/Requests/EnableMethodIssuerRequestTest.php new file mode 100644 index 000000000..511b2e356 --- /dev/null +++ b/tests/Http/Requests/EnableMethodIssuerRequestTest.php @@ -0,0 +1,45 @@ + MockResponse::noContent(''), + ]); + + $profileId = 'pfl_v9hTwCvYqw'; + $methodId = 'ideal'; + $issuerId = 'INGBNL2A'; + $request = new EnableMethodIssuerRequest($profileId, $methodId, $issuerId); + + /** @var Issuer */ + $issuer = $client->send($request); + + $this->assertTrue($issuer->getResponse()->successful()); + $this->assertEquals(204, $issuer->getResponse()->status()); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $profileId = 'pfl_v9hTwCvYqw'; + $methodId = 'ideal'; + $issuerId = 'INGBNL2A'; + $request = new EnableMethodIssuerRequest($profileId, $methodId, $issuerId); + + $this->assertEquals( + "profiles/{$profileId}/methods/{$methodId}/issuers/{$issuerId}", + $request->resolveResourcePath() + ); + } +} diff --git a/tests/Http/Requests/EnableProfileMethodRequestTest.php b/tests/Http/Requests/EnableProfileMethodRequestTest.php new file mode 100644 index 000000000..b1cc1320a --- /dev/null +++ b/tests/Http/Requests/EnableProfileMethodRequestTest.php @@ -0,0 +1,43 @@ + MockResponse::noContent(''), + ]); + + $profileId = 'pfl_v9hTwCvYqw'; + $methodId = 'ideal'; + $request = new EnableProfileMethodRequest($profileId, $methodId); + + /** @var Method */ + $method = $client->send($request); + + $this->assertTrue($method->getResponse()->successful()); + $this->assertEquals(204, $method->getResponse()->status()); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $profileId = 'pfl_v9hTwCvYqw'; + $methodId = 'ideal'; + $request = new EnableProfileMethodRequest($profileId, $methodId); + + $this->assertEquals( + "profiles/{$profileId}/methods/{$methodId}", + $request->resolveResourcePath() + ); + } +} diff --git a/tests/Http/Requests/GetAllMethodsRequestTest.php b/tests/Http/Requests/GetAllMethodsRequestTest.php new file mode 100644 index 000000000..d6a0f692b --- /dev/null +++ b/tests/Http/Requests/GetAllMethodsRequestTest.php @@ -0,0 +1,36 @@ + MockResponse::ok('method-list'), + ]); + + $request = new GetAllMethodsRequest; + + /** @var MethodCollection */ + $methods = $client->send($request); + + $this->assertTrue($methods->getResponse()->successful()); + $this->assertInstanceOf(MethodCollection::class, $methods); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new GetAllMethodsRequest; + + $this->assertEquals('methods/all', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetAllPaginatedSubscriptionsRequestTest.php b/tests/Http/Requests/GetAllPaginatedSubscriptionsRequestTest.php new file mode 100644 index 000000000..2cfd1f0f7 --- /dev/null +++ b/tests/Http/Requests/GetAllPaginatedSubscriptionsRequestTest.php @@ -0,0 +1,36 @@ + MockResponse::ok('subscription-list'), + ]); + + $request = new GetAllPaginatedSubscriptionsRequest; + + /** @var SubscriptionCollection */ + $subscriptions = $client->send($request); + + $this->assertTrue($subscriptions->getResponse()->successful()); + $this->assertInstanceOf(SubscriptionCollection::class, $subscriptions); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new GetAllPaginatedSubscriptionsRequest; + + $this->assertEquals('subscriptions', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetBalanceReportRequestTest.php b/tests/Http/Requests/GetBalanceReportRequestTest.php new file mode 100644 index 000000000..ae9ddab31 --- /dev/null +++ b/tests/Http/Requests/GetBalanceReportRequestTest.php @@ -0,0 +1,47 @@ + MockResponse::ok('balance-report'), + ]); + + $request = new GetBalanceReportRequest( + 'bal_12345', + new GetBalanceReportQuery( + new DateTime('2024-01-01'), + new DateTime('2024-01-31'), + ) + ); + + /** @var BalanceReport */ + $balanceReport = $client->send($request); + + $this->assertTrue($balanceReport->getResponse()->successful()); + $this->assertInstanceOf(BalanceReport::class, $balanceReport); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new GetBalanceReportRequest('bal_12345', new GetBalanceReportQuery( + new DateTime('2024-01-01'), + new DateTime('2024-01-31'), + )); + + $this->assertEquals('balances/bal_12345/report', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetBalanceRequestTest.php b/tests/Http/Requests/GetBalanceRequestTest.php new file mode 100644 index 000000000..919e83b05 --- /dev/null +++ b/tests/Http/Requests/GetBalanceRequestTest.php @@ -0,0 +1,41 @@ + MockResponse::ok('balance'), + ]); + + $balanceId = 'bal_12345678'; + $request = new GetBalanceRequest($balanceId); + + /** @var Balance */ + $balance = $client->send($request); + + $this->assertTrue($balance->getResponse()->successful()); + $this->assertInstanceOf(Balance::class, $balance); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $balanceId = 'bal_12345678'; + $request = new GetBalanceRequest($balanceId); + + $this->assertEquals( + "balances/{$balanceId}", + $request->resolveResourcePath() + ); + } +} diff --git a/tests/Http/Requests/GetClientRequestTest.php b/tests/Http/Requests/GetClientRequestTest.php new file mode 100644 index 000000000..268140fe3 --- /dev/null +++ b/tests/Http/Requests/GetClientRequestTest.php @@ -0,0 +1,37 @@ + MockResponse::ok('client'), + ]); + + $request = new GetClientRequest('client_123'); + + /** @var Client */ + $client = $client->send($request); + + $this->assertTrue($client->getResponse()->successful()); + $this->assertInstanceOf(Client::class, $client); + $this->assertEquals('client', $client->resource); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new GetClientRequest('client_123'); + + $this->assertEquals('clients/client_123', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetCustomerRequestTest.php b/tests/Http/Requests/GetCustomerRequestTest.php new file mode 100644 index 000000000..7db30d9d7 --- /dev/null +++ b/tests/Http/Requests/GetCustomerRequestTest.php @@ -0,0 +1,41 @@ + MockResponse::ok('customer'), + ]); + + $customerId = 'cst_kEn1PlbGa'; + $request = new GetCustomerRequest($customerId); + + /** @var Customer */ + $customer = $client->send($request); + + $this->assertTrue($customer->getResponse()->successful()); + $this->assertInstanceOf(Customer::class, $customer); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $customerId = 'cst_kEn1PlbGa'; + $request = new GetCustomerRequest($customerId); + + $this->assertEquals( + "customers/{$customerId}", + $request->resolveResourcePath() + ); + } +} diff --git a/tests/Http/Requests/GetEnabledMethodsRequestTest.php b/tests/Http/Requests/GetEnabledMethodsRequestTest.php new file mode 100644 index 000000000..9c7f3b7c4 --- /dev/null +++ b/tests/Http/Requests/GetEnabledMethodsRequestTest.php @@ -0,0 +1,36 @@ + MockResponse::ok('method-list'), + ]); + + $request = new GetEnabledMethodsRequest; + + /** @var MethodCollection */ + $methods = $client->send($request); + + $this->assertTrue($methods->getResponse()->successful()); + $this->assertInstanceOf(MethodCollection::class, $methods); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new GetEnabledMethodsRequest; + + $this->assertEquals('methods', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetInvoiceRequestTest.php b/tests/Http/Requests/GetInvoiceRequestTest.php new file mode 100644 index 000000000..2a51ccf72 --- /dev/null +++ b/tests/Http/Requests/GetInvoiceRequestTest.php @@ -0,0 +1,37 @@ + MockResponse::ok('invoice'), + ]); + + $invoiceId = 'inv_xBEbP9rvAq'; + $request = new GetInvoiceRequest($invoiceId); + + /** @var Invoice */ + $invoice = $client->send($request); + + $this->assertTrue($invoice->getResponse()->successful()); + $this->assertInstanceOf(Invoice::class, $invoice); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new GetInvoiceRequest('inv_xBEbP9rvAq'); + + $this->assertEquals('invoices/inv_xBEbP9rvAq', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetMandateRequestTest.php b/tests/Http/Requests/GetMandateRequestTest.php new file mode 100644 index 000000000..dc5c26363 --- /dev/null +++ b/tests/Http/Requests/GetMandateRequestTest.php @@ -0,0 +1,43 @@ + MockResponse::ok('mandate'), + ]); + + $customerId = 'cst_kEn1PlbGa'; + $mandateId = 'mdt_h3gAaD5zP'; + $request = new GetMandateRequest($customerId, $mandateId); + + /** @var Mandate */ + $mandate = $client->send($request); + + $this->assertTrue($mandate->getResponse()->successful()); + $this->assertInstanceOf(Mandate::class, $mandate); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $customerId = 'cst_kEn1PlbGa'; + $mandateId = 'mdt_h3gAaD5zP'; + $request = new GetMandateRequest($customerId, $mandateId); + + $this->assertEquals( + "customers/{$customerId}/mandates/{$mandateId}", + $request->resolveResourcePath() + ); + } +} diff --git a/tests/Http/Requests/GetOnboardingStatusRequestTest.php b/tests/Http/Requests/GetOnboardingStatusRequestTest.php new file mode 100644 index 000000000..48173a29d --- /dev/null +++ b/tests/Http/Requests/GetOnboardingStatusRequestTest.php @@ -0,0 +1,36 @@ + MockResponse::ok('onboarding'), + ]); + + $request = new GetOnboardingStatusRequest; + + /** @var Onboarding */ + $onboarding = $client->send($request); + + $this->assertTrue($onboarding->getResponse()->successful()); + $this->assertInstanceOf(Onboarding::class, $onboarding); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new GetOnboardingStatusRequest; + + $this->assertEquals('onboarding/me', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetOrganizationPartnerStatusRequestTest.php b/tests/Http/Requests/GetOrganizationPartnerStatusRequestTest.php new file mode 100644 index 000000000..200cb03a8 --- /dev/null +++ b/tests/Http/Requests/GetOrganizationPartnerStatusRequestTest.php @@ -0,0 +1,36 @@ + MockResponse::ok('partner-status'), + ]); + + $request = new GetOrganizationPartnerStatusRequest; + + /** @var Partner */ + $partner = $client->send($request); + + $this->assertTrue($partner->getResponse()->successful()); + $this->assertInstanceOf(Partner::class, $partner); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new GetOrganizationPartnerStatusRequest; + + $this->assertEquals('organizations/me/partner', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetOrganizationRequestTest.php b/tests/Http/Requests/GetOrganizationRequestTest.php new file mode 100644 index 000000000..398fbd41f --- /dev/null +++ b/tests/Http/Requests/GetOrganizationRequestTest.php @@ -0,0 +1,38 @@ + MockResponse::ok('organization'), + ]); + + $organizationId = 'org_1337'; + $request = new GetOrganizationRequest($organizationId); + + /** @var Organization */ + $organization = $client->send($request); + + $this->assertTrue($organization->getResponse()->successful()); + $this->assertInstanceOf(Organization::class, $organization); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $organizationId = 'org_1337'; + $request = new GetOrganizationRequest($organizationId); + + $this->assertEquals("organizations/{$organizationId}", $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaginatedBalanceRequestTest.php b/tests/Http/Requests/GetPaginatedBalanceRequestTest.php new file mode 100644 index 000000000..e4856993e --- /dev/null +++ b/tests/Http/Requests/GetPaginatedBalanceRequestTest.php @@ -0,0 +1,36 @@ + MockResponse::ok('balance-list'), + ]); + + $request = new GetPaginatedBalanceRequest; + + /** @var BalanceCollection */ + $balances = $client->send($request); + + $this->assertTrue($balances->getResponse()->successful()); + $this->assertInstanceOf(BalanceCollection::class, $balances); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new GetPaginatedBalanceRequest; + + $this->assertEquals('balances', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaginatedBalanceTransactionRequestTest.php b/tests/Http/Requests/GetPaginatedBalanceTransactionRequestTest.php new file mode 100644 index 000000000..8ca7e8dd4 --- /dev/null +++ b/tests/Http/Requests/GetPaginatedBalanceTransactionRequestTest.php @@ -0,0 +1,38 @@ + MockResponse::ok('balance-transactions'), + ]); + + $balanceId = 'bal_gVMhHKqSSRYJyPsuoPNFH'; + $request = new GetPaginatedBalanceTransactionRequest($balanceId); + + /** @var BalanceTransactionCollection */ + $balanceTransactions = $client->send($request); + + $this->assertTrue($balanceTransactions->getResponse()->successful()); + $this->assertInstanceOf(BalanceTransactionCollection::class, $balanceTransactions); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $balanceId = 'bal_gVMhHKqSSRYJyPsuoPNFH'; + $request = new GetPaginatedBalanceTransactionRequest($balanceId); + + $this->assertEquals("balances/{$balanceId}/transactions", $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaginatedChargebacksRequestTest.php b/tests/Http/Requests/GetPaginatedChargebacksRequestTest.php new file mode 100644 index 000000000..64f1ba807 --- /dev/null +++ b/tests/Http/Requests/GetPaginatedChargebacksRequestTest.php @@ -0,0 +1,36 @@ + MockResponse::ok('chargeback-list'), + ]); + + $request = new GetPaginatedChargebacksRequest; + + /** @var ChargebackCollection */ + $chargebacks = $client->send($request); + + $this->assertTrue($chargebacks->getResponse()->successful()); + $this->assertInstanceOf(ChargebackCollection::class, $chargebacks); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new GetPaginatedChargebacksRequest; + + $this->assertEquals('chargebacks', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaginatedClientRequestTest.php b/tests/Http/Requests/GetPaginatedClientRequestTest.php new file mode 100644 index 000000000..fc78c7589 --- /dev/null +++ b/tests/Http/Requests/GetPaginatedClientRequestTest.php @@ -0,0 +1,36 @@ + MockResponse::ok('client-list'), + ]); + + $request = new GetPaginatedClientRequest; + + /** @var ClientCollection */ + $clients = $client->send($request); + + $this->assertTrue($clients->getResponse()->successful()); + $this->assertInstanceOf(ClientCollection::class, $clients); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new GetPaginatedClientRequest; + + $this->assertEquals('clients', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaginatedCustomerPaymentsRequestTest.php b/tests/Http/Requests/GetPaginatedCustomerPaymentsRequestTest.php new file mode 100644 index 000000000..75563d79d --- /dev/null +++ b/tests/Http/Requests/GetPaginatedCustomerPaymentsRequestTest.php @@ -0,0 +1,38 @@ + MockResponse::ok('payment-list'), + ]); + + $customerId = 'cst_kEn1PlbGa'; + $request = new GetPaginatedCustomerPaymentsRequest($customerId); + + /** @var PaymentCollection */ + $payments = $client->send($request); + + $this->assertTrue($payments->getResponse()->successful()); + $this->assertInstanceOf(PaymentCollection::class, $payments); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $customerId = 'cst_kEn1PlbGa'; + $request = new GetPaginatedCustomerPaymentsRequest($customerId); + + $this->assertEquals("customers/{$customerId}/payments", $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaginatedCustomerRequestTest.php b/tests/Http/Requests/GetPaginatedCustomerRequestTest.php new file mode 100644 index 000000000..3cef1c873 --- /dev/null +++ b/tests/Http/Requests/GetPaginatedCustomerRequestTest.php @@ -0,0 +1,36 @@ + MockResponse::ok('customer-list'), + ]); + + $request = new GetPaginatedCustomerRequest; + + /** @var CustomerCollection */ + $customers = $client->send($request); + + $this->assertTrue($customers->getResponse()->successful()); + $this->assertInstanceOf(CustomerCollection::class, $customers); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new GetPaginatedCustomerRequest; + + $this->assertEquals('customers', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaginatedInvoiceRequestTest.php b/tests/Http/Requests/GetPaginatedInvoiceRequestTest.php new file mode 100644 index 000000000..b734fb3d4 --- /dev/null +++ b/tests/Http/Requests/GetPaginatedInvoiceRequestTest.php @@ -0,0 +1,36 @@ + MockResponse::ok('invoice-list'), + ]); + + $request = new GetPaginatedInvoiceRequest; + + /** @var InvoiceCollection */ + $invoices = $client->send($request); + + $this->assertTrue($invoices->getResponse()->successful()); + $this->assertInstanceOf(InvoiceCollection::class, $invoices); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new GetPaginatedInvoiceRequest; + + $this->assertEquals('invoices', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaginatedMandateRequestTest.php b/tests/Http/Requests/GetPaginatedMandateRequestTest.php new file mode 100644 index 000000000..e02d1179f --- /dev/null +++ b/tests/Http/Requests/GetPaginatedMandateRequestTest.php @@ -0,0 +1,70 @@ + MockResponse::ok('mandate-list'), + ]); + + $request = new GetPaginatedMandateRequest('cst_kEn1PlbGa'); + + /** @var MandateCollection */ + $mandates = $client->send($request); + + $this->assertTrue($mandates->getResponse()->successful()); + $this->assertInstanceOf(MandateCollection::class, $mandates); + $this->assertGreaterThan(0, $mandates->count()); + + foreach ($mandates as $mandate) { + $this->assertInstanceOf(Mandate::class, $mandate); + $this->assertEquals('mandate', $mandate->resource); + } + } + + /** @test */ + public function it_can_iterate_over_mandates() + { + $client = new MockMollieClient([ + GetPaginatedMandateRequest::class => MockResponse::ok('mandate-list'), + DynamicGetRequest::class => new SequenceMockResponse( + MockResponse::ok('mandate-list'), + MockResponse::ok('empty-list', 'mandates'), + ), + ]); + + $request = (new GetPaginatedMandateRequest('cst_kEn1PlbGa'))->useIterator(); + + /** @var MandateCollection */ + $mandates = $client->send($request); + $this->assertTrue($mandates->getResponse()->successful()); + + foreach ($mandates as $mandate) { + $this->assertInstanceOf(Mandate::class, $mandate); + } + + $client->assertSentCount(3); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $customerId = 'cst_kEn1PlbGa'; + $request = new GetPaginatedMandateRequest($customerId); + + $this->assertEquals("customers/{$customerId}/mandates", $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaginatedPaymentCapturesRequestTest.php b/tests/Http/Requests/GetPaginatedPaymentCapturesRequestTest.php new file mode 100644 index 000000000..7c6205657 --- /dev/null +++ b/tests/Http/Requests/GetPaginatedPaymentCapturesRequestTest.php @@ -0,0 +1,70 @@ + MockResponse::ok('capture-list'), + ]); + + $request = new GetPaginatedPaymentCapturesRequest('tr_WDqYK6vllg'); + + /** @var CaptureCollection */ + $captures = $client->send($request); + + $this->assertTrue($captures->getResponse()->successful()); + $this->assertInstanceOf(CaptureCollection::class, $captures); + $this->assertGreaterThan(0, $captures->count()); + + foreach ($captures as $capture) { + $this->assertInstanceOf(Capture::class, $capture); + $this->assertEquals('capture', $capture->resource); + } + } + + /** @test */ + public function it_can_iterate_over_captures() + { + $client = new MockMollieClient([ + GetPaginatedPaymentCapturesRequest::class => MockResponse::ok('capture-list'), + DynamicGetRequest::class => new SequenceMockResponse( + MockResponse::ok('capture-list'), + MockResponse::ok('empty-list', 'captures'), + ), + ]); + + $request = (new GetPaginatedPaymentCapturesRequest('tr_WDqYK6vllg'))->useIterator(); + + /** @var CaptureCollection */ + $captures = $client->send($request); + $this->assertTrue($captures->getResponse()->successful()); + + foreach ($captures as $capture) { + $this->assertInstanceOf(Capture::class, $capture); + } + + $client->assertSentCount(3); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $paymentId = 'tr_WDqYK6vllg'; + $request = new GetPaginatedPaymentCapturesRequest($paymentId); + + $this->assertEquals("payments/{$paymentId}/captures", $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaginatedPaymentChargebacksRequestTest.php b/tests/Http/Requests/GetPaginatedPaymentChargebacksRequestTest.php new file mode 100644 index 000000000..6923f6e04 --- /dev/null +++ b/tests/Http/Requests/GetPaginatedPaymentChargebacksRequestTest.php @@ -0,0 +1,70 @@ + MockResponse::ok('chargeback-list'), + ]); + + $request = new GetPaginatedPaymentChargebacksRequest('tr_WDqYK6vllg'); + + /** @var ChargebackCollection */ + $chargebacks = $client->send($request); + + $this->assertTrue($chargebacks->getResponse()->successful()); + $this->assertInstanceOf(ChargebackCollection::class, $chargebacks); + $this->assertGreaterThan(0, $chargebacks->count()); + + foreach ($chargebacks as $chargeback) { + $this->assertInstanceOf(Chargeback::class, $chargeback); + $this->assertEquals('chargeback', $chargeback->resource); + } + } + + /** @test */ + public function it_can_iterate_over_chargebacks() + { + $client = new MockMollieClient([ + GetPaginatedPaymentChargebacksRequest::class => MockResponse::ok('chargeback-list'), + DynamicGetRequest::class => new SequenceMockResponse( + MockResponse::ok('chargeback-list'), + MockResponse::ok('empty-list', 'chargebacks'), + ), + ]); + + $request = (new GetPaginatedPaymentChargebacksRequest('tr_WDqYK6vllg'))->useIterator(); + + /** @var ChargebackCollection */ + $chargebacks = $client->send($request); + $this->assertTrue($chargebacks->getResponse()->successful()); + + foreach ($chargebacks as $chargeback) { + $this->assertInstanceOf(Chargeback::class, $chargeback); + } + + $client->assertSentCount(3); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $paymentId = 'tr_WDqYK6vllg'; + $request = new GetPaginatedPaymentChargebacksRequest($paymentId); + + $this->assertEquals("payments/{$paymentId}/chargebacks", $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaginatedPaymentLinkPaymentsRequestTest.php b/tests/Http/Requests/GetPaginatedPaymentLinkPaymentsRequestTest.php new file mode 100644 index 000000000..f5315cb58 --- /dev/null +++ b/tests/Http/Requests/GetPaginatedPaymentLinkPaymentsRequestTest.php @@ -0,0 +1,71 @@ + MockResponse::ok('payment-list'), + ]); + + $request = new GetPaginatedPaymentLinkPaymentsRequest('pl_4Y0eZitmBnQ5jsBYZIBw'); + + /** @var PaymentCollection */ + $payments = $client->send($request); + + $this->assertTrue($payments->getResponse()->successful()); + + $this->assertInstanceOf(PaymentCollection::class, $payments); + $this->assertGreaterThan(0, $payments->count()); + + foreach ($payments as $payment) { + $this->assertInstanceOf(Payment::class, $payment); + $this->assertEquals('payment', $payment->resource); + } + } + + /** @test */ + public function it_can_iterate_over_payment_link_payments() + { + $client = new MockMollieClient([ + GetPaginatedPaymentLinkPaymentsRequest::class => MockResponse::ok('payment-list'), + DynamicGetRequest::class => new SequenceMockResponse( + MockResponse::ok('payment-list'), + MockResponse::ok('empty-list', 'payments'), + ), + ]); + + $request = (new GetPaginatedPaymentLinkPaymentsRequest('pl_4Y0eZitmBnQ5jsBYZIBw'))->useIterator(); + + /** @var PaymentCollection */ + $payments = $client->send($request); + $this->assertTrue($payments->getResponse()->successful()); + + foreach ($payments as $payment) { + $this->assertInstanceOf(Payment::class, $payment); + } + + $client->assertSentCount(3); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $paymentLinkId = 'pl_4Y0eZitmBnQ5jsBYZIBw'; + $request = new GetPaginatedPaymentLinkPaymentsRequest($paymentLinkId); + + $this->assertEquals("payment-links/{$paymentLinkId}/payments", $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaginatedPaymentLinksRequestTest.php b/tests/Http/Requests/GetPaginatedPaymentLinksRequestTest.php new file mode 100644 index 000000000..5f9973a05 --- /dev/null +++ b/tests/Http/Requests/GetPaginatedPaymentLinksRequestTest.php @@ -0,0 +1,68 @@ + MockResponse::ok('payment-link-list'), + ]); + + $request = new GetPaginatedPaymentLinksRequest; + + /** @var PaymentLinkCollection */ + $paymentLinks = $client->send($request); + + $this->assertTrue($paymentLinks->getResponse()->successful()); + + foreach ($paymentLinks as $paymentLink) { + $this->assertInstanceOf(PaymentLink::class, $paymentLink); + $this->assertEquals('payment-link', $paymentLink->resource); + } + } + + /** @test */ + public function it_can_iterate_over_payment_links() + { + $client = new MockMollieClient([ + GetPaginatedPaymentLinksRequest::class => MockResponse::ok('payment-link-list'), + DynamicGetRequest::class => new SequenceMockResponse( + MockResponse::ok('payment-link-list'), + MockResponse::ok('empty-list', 'payment_links'), + ), + ]); + + $request = (new GetPaginatedPaymentLinksRequest)->useIterator(); + + /** @var PaymentLinkCollection */ + $paymentLinks = $client->send($request); + + $this->assertTrue($paymentLinks->getResponse()->successful()); + + foreach ($paymentLinks as $paymentLink) { + $this->assertInstanceOf(PaymentLink::class, $paymentLink); + } + + $client->assertSentCount(3); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new GetPaginatedPaymentLinksRequest; + + $this->assertEquals('payment-links', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaginatedPaymentRefundsRequestTest.php b/tests/Http/Requests/GetPaginatedPaymentRefundsRequestTest.php new file mode 100644 index 000000000..a2f6de47e --- /dev/null +++ b/tests/Http/Requests/GetPaginatedPaymentRefundsRequestTest.php @@ -0,0 +1,67 @@ + MockResponse::ok('refund-list'), + ]); + + $request = new GetPaginatedPaymentRefundsRequest('tr_WDqYK6vllg'); + + /** @var RefundCollection */ + $refunds = $client->send($request); + $this->assertTrue($refunds->getResponse()->successful()); + + foreach ($refunds as $refund) { + $this->assertInstanceOf(Refund::class, $refund); + $this->assertEquals('refund', $refund->resource); + } + } + + /** @test */ + public function it_can_iterate_over_refunds() + { + $client = new MockMollieClient([ + GetPaginatedPaymentRefundsRequest::class => MockResponse::ok('refund-list'), + DynamicGetRequest::class => new SequenceMockResponse( + MockResponse::ok('refund-list'), + MockResponse::ok('empty-list', 'refunds'), + ), + ]); + + $request = (new GetPaginatedPaymentRefundsRequest('tr_WDqYK6vllg'))->useIterator(); + + /** @var RefundCollection */ + $refunds = $client->send($request); + $this->assertTrue($refunds->getResponse()->successful()); + + foreach ($refunds as $refund) { + $this->assertInstanceOf(Refund::class, $refund); + } + + $client->assertSentCount(3); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $paymentId = 'tr_WDqYK6vllg'; + $request = new GetPaginatedPaymentRefundsRequest($paymentId); + + $this->assertEquals("payments/{$paymentId}/refunds", $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaginatedPaymentsRequestTest.php b/tests/Http/Requests/GetPaginatedPaymentsRequestTest.php new file mode 100644 index 000000000..8f3a97a9e --- /dev/null +++ b/tests/Http/Requests/GetPaginatedPaymentsRequestTest.php @@ -0,0 +1,73 @@ + MockResponse::ok('payment-list'), + ]); + + $request = new GetPaginatedPaymentsRequest; + + /** @var PaymentCollection */ + $payments = $client->send($request); + + $this->assertTrue($payments->getResponse()->successful()); + + // Assert response was properly handled + $this->assertInstanceOf(PaymentCollection::class, $payments); + $this->assertGreaterThan(0, $payments->count()); + + foreach ($payments as $payment) { + $this->assertInstanceOf(Payment::class, $payment); + $this->assertEquals('payment', $payment->resource); + } + } + + /** @test */ + public function it_can_iterate_over_payments() + { + $client = new MockMollieClient([ + GetPaginatedPaymentsRequest::class => MockResponse::ok('payment-list'), + DynamicGetRequest::class => new SequenceMockResponse( + MockResponse::ok('payment-list'), + MockResponse::ok('empty-list', 'payments'), + ), + ]); + + $request = (new GetPaginatedPaymentsRequest)->useIterator(); + + /** @var LazyCollection */ + $payments = $client->send($request); + $this->assertTrue($payments->getResponse()->successful()); + + foreach ($payments as $payment) { + $this->assertInstanceOf(Payment::class, $payment); + } + + $client->assertSentCount(3); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new GetPaginatedPaymentsRequest; + + $this->assertEquals('payments', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaginatedProfilesRequestTest.php b/tests/Http/Requests/GetPaginatedProfilesRequestTest.php new file mode 100644 index 000000000..89a953159 --- /dev/null +++ b/tests/Http/Requests/GetPaginatedProfilesRequestTest.php @@ -0,0 +1,68 @@ + MockResponse::ok('profile-list'), + ]); + + $request = new GetPaginatedProfilesRequest; + + /** @var ProfileCollection */ + $profiles = $client->send($request); + + $this->assertTrue($profiles->getResponse()->successful()); + + foreach ($profiles as $profile) { + $this->assertInstanceOf(Profile::class, $profile); + $this->assertEquals('profile', $profile->resource); + } + } + + /** @test */ + public function it_can_iterate_over_profiles() + { + $client = new MockMollieClient([ + GetPaginatedProfilesRequest::class => MockResponse::ok('profile-list'), + DynamicGetRequest::class => new SequenceMockResponse( + MockResponse::ok('profile-list'), + MockResponse::ok('empty-list', 'profiles'), + ), + ]); + + $request = (new GetPaginatedProfilesRequest)->useIterator(); + + /** @var LazyCollection */ + $profiles = $client->send($request); + $this->assertTrue($profiles->getResponse()->successful()); + + foreach ($profiles as $profile) { + $this->assertInstanceOf(Profile::class, $profile); + } + + $client->assertSentCount(3); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new GetPaginatedProfilesRequest; + + $this->assertEquals('profiles', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaginatedRefundsRequestTest.php b/tests/Http/Requests/GetPaginatedRefundsRequestTest.php new file mode 100644 index 000000000..eab2dad75 --- /dev/null +++ b/tests/Http/Requests/GetPaginatedRefundsRequestTest.php @@ -0,0 +1,67 @@ + MockResponse::ok('refund-list'), + ]); + + $request = new GetPaginatedRefundsRequest; + + /** @var RefundCollection */ + $refunds = $client->send($request); + + $this->assertTrue($refunds->getResponse()->successful()); + + foreach ($refunds as $refund) { + $this->assertInstanceOf(Refund::class, $refund); + $this->assertEquals('refund', $refund->resource); + } + } + + /** @test */ + public function it_can_iterate_over_refunds() + { + $client = new MockMollieClient([ + GetPaginatedRefundsRequest::class => MockResponse::ok('refund-list'), + DynamicGetRequest::class => new SequenceMockResponse( + MockResponse::ok('refund-list'), + MockResponse::ok('empty-list', 'refunds'), + ), + ]); + + $request = (new GetPaginatedRefundsRequest)->useIterator(); + + /** @var RefundCollection */ + $refunds = $client->send($request); + $this->assertTrue($refunds->getResponse()->successful()); + + foreach ($refunds as $refund) { + $this->assertInstanceOf(Refund::class, $refund); + } + + $client->assertSentCount(3); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new GetPaginatedRefundsRequest; + + $this->assertEquals('refunds', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaginatedSalesInvoicesRequestTest.php b/tests/Http/Requests/GetPaginatedSalesInvoicesRequestTest.php new file mode 100644 index 000000000..099e4ef71 --- /dev/null +++ b/tests/Http/Requests/GetPaginatedSalesInvoicesRequestTest.php @@ -0,0 +1,65 @@ + MockResponse::ok('sales-invoice-list'), + ]); + + $request = new GetPaginatedSalesInvoicesRequest; + + /** @var SalesInvoiceCollection */ + $salesInvoices = $client->send($request); + + $this->assertTrue($salesInvoices->getResponse()->successful()); + + $this->assertInstanceOf(SalesInvoiceCollection::class, $salesInvoices); + $this->assertGreaterThan(0, $salesInvoices->count()); + } + + /** @test */ + public function it_can_iterate_over_sales_invoices() + { + $client = new MockMollieClient([ + GetPaginatedSalesInvoicesRequest::class => MockResponse::ok('sales-invoice-list'), + DynamicGetRequest::class => new SequenceMockResponse( + MockResponse::ok('sales-invoice-list'), + MockResponse::ok('empty-list', 'sales_invoices'), + ), + ]); + + $request = (new GetPaginatedSalesInvoicesRequest)->useIterator(); + + /** @var LazyCollection */ + $salesInvoices = $client->send($request); + $this->assertTrue($salesInvoices->getResponse()->successful()); + + foreach ($salesInvoices as $salesInvoice) { + $this->assertInstanceOf(SalesInvoice::class, $salesInvoice); + } + + $client->assertSentCount(3); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new GetPaginatedSalesInvoicesRequest; + $this->assertEquals('sales-invoices', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaginatedSessionsRequestTest.php b/tests/Http/Requests/GetPaginatedSessionsRequestTest.php new file mode 100644 index 000000000..ff639689c --- /dev/null +++ b/tests/Http/Requests/GetPaginatedSessionsRequestTest.php @@ -0,0 +1,68 @@ + MockResponse::ok('session-list'), + ]); + + $request = new GetPaginatedSessionsRequest; + + /** @var SessionCollection */ + $sessions = $client->send($request); + + $this->assertTrue($sessions->getResponse()->successful()); + + foreach ($sessions as $session) { + $this->assertInstanceOf(Session::class, $session); + $this->assertEquals('session', $session->resource); + } + } + + /** @test */ + public function it_can_iterate_over_sessions() + { + $client = new MockMollieClient([ + GetPaginatedSessionsRequest::class => MockResponse::ok('session-list'), + DynamicGetRequest::class => new SequenceMockResponse( + MockResponse::ok('session-list'), + MockResponse::ok('empty-list', 'sessions'), + ), + ]); + + $request = (new GetPaginatedSessionsRequest)->useIterator(); + + /** @var LazyCollection */ + $sessions = $client->send($request); + $this->assertTrue($sessions->getResponse()->successful()); + + foreach ($sessions as $session) { + $this->assertInstanceOf(Session::class, $session); + } + + $client->assertSentCount(3); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new GetPaginatedSessionsRequest; + + $this->assertEquals('sessions', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaginatedSettlementCapturesRequestTest.php b/tests/Http/Requests/GetPaginatedSettlementCapturesRequestTest.php new file mode 100644 index 000000000..169117442 --- /dev/null +++ b/tests/Http/Requests/GetPaginatedSettlementCapturesRequestTest.php @@ -0,0 +1,69 @@ + MockResponse::ok('capture-list'), + ]); + + $request = new GetPaginatedSettlementCapturesRequest('stl_jDk30akdN'); + + /** @var CaptureCollection */ + $captures = $client->send($request); + + $this->assertTrue($captures->getResponse()->successful()); + + foreach ($captures as $capture) { + $this->assertInstanceOf(Capture::class, $capture); + $this->assertEquals('capture', $capture->resource); + } + } + + /** @test */ + public function it_can_iterate_over_settlement_captures() + { + $client = new MockMollieClient([ + GetPaginatedSettlementCapturesRequest::class => MockResponse::ok('capture-list'), + DynamicGetRequest::class => new SequenceMockResponse( + MockResponse::ok('capture-list'), + MockResponse::ok('empty-list', 'captures'), + ), + ]); + + $request = (new GetPaginatedSettlementCapturesRequest('stl_jDk30akdN'))->useIterator(); + + /** @var LazyCollection */ + $captures = $client->send($request); + $this->assertTrue($captures->getResponse()->successful()); + + foreach ($captures as $capture) { + $this->assertInstanceOf(Capture::class, $capture); + } + + $client->assertSentCount(3); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $settlementId = 'stl_jDk30akdN'; + $request = new GetPaginatedSettlementCapturesRequest($settlementId); + + $this->assertEquals("settlements/{$settlementId}/captures", $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaginatedSettlementChargebacksRequestTest.php b/tests/Http/Requests/GetPaginatedSettlementChargebacksRequestTest.php new file mode 100644 index 000000000..b6bd284b1 --- /dev/null +++ b/tests/Http/Requests/GetPaginatedSettlementChargebacksRequestTest.php @@ -0,0 +1,68 @@ + MockResponse::ok('chargeback-list'), + ]); + + $request = new GetPaginatedSettlementChargebacksRequest('stl_jDk30akdN'); + + /** @var LazyCollection */ + $chargebacks = $client->send($request); + + $this->assertTrue($chargebacks->getResponse()->successful()); + + foreach ($chargebacks as $chargeback) { + $this->assertInstanceOf(Chargeback::class, $chargeback); + $this->assertEquals('chargeback', $chargeback->resource); + } + } + + /** @test */ + public function it_can_iterate_over_settlement_chargebacks() + { + $client = new MockMollieClient([ + GetPaginatedSettlementChargebacksRequest::class => MockResponse::ok('chargeback-list'), + DynamicGetRequest::class => new SequenceMockResponse( + MockResponse::ok('chargeback-list'), + MockResponse::ok('empty-list', 'chargebacks'), + ), + ]); + + $request = (new GetPaginatedSettlementChargebacksRequest('stl_jDk30akdN'))->useIterator(); + + /** @var LazyCollection */ + $chargebacks = $client->send($request); + $this->assertTrue($chargebacks->getResponse()->successful()); + + foreach ($chargebacks as $chargeback) { + $this->assertInstanceOf(Chargeback::class, $chargeback); + } + + $client->assertSentCount(3); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $settlementId = 'stl_jDk30akdN'; + $request = new GetPaginatedSettlementChargebacksRequest($settlementId); + + $this->assertEquals("settlements/{$settlementId}/chargebacks", $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaginatedSettlementPaymentsRequestTest.php b/tests/Http/Requests/GetPaginatedSettlementPaymentsRequestTest.php new file mode 100644 index 000000000..316c919ca --- /dev/null +++ b/tests/Http/Requests/GetPaginatedSettlementPaymentsRequestTest.php @@ -0,0 +1,72 @@ + MockResponse::ok('payment-list'), + ]); + + $request = new GetPaginatedSettlementPaymentsRequest('stl_jDk30akdN'); + + /** @var PaymentCollection */ + $payments = $client->send($request); + + $this->assertTrue($payments->getResponse()->successful()); + + $this->assertInstanceOf(PaymentCollection::class, $payments); + $this->assertGreaterThan(0, $payments->count()); + + foreach ($payments as $payment) { + $this->assertInstanceOf(Payment::class, $payment); + $this->assertEquals('payment', $payment->resource); + } + } + + /** @test */ + public function it_can_iterate_over_settlement_payments() + { + $client = new MockMollieClient([ + GetPaginatedSettlementPaymentsRequest::class => MockResponse::ok('payment-list'), + DynamicGetRequest::class => new SequenceMockResponse( + MockResponse::ok('payment-list'), + MockResponse::ok('empty-list', 'payments'), + ), + ]); + + $request = (new GetPaginatedSettlementPaymentsRequest('stl_jDk30akdN'))->useIterator(); + + /** @var LazyCollection */ + $payments = $client->send($request); + $this->assertTrue($payments->getResponse()->successful()); + + foreach ($payments as $payment) { + $this->assertInstanceOf(Payment::class, $payment); + } + + $client->assertSentCount(3); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $settlementId = 'stl_jDk30akdN'; + $request = new GetPaginatedSettlementPaymentsRequest($settlementId); + + $this->assertEquals("settlements/{$settlementId}/payments", $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaginatedSettlementRefundsRequestTest.php b/tests/Http/Requests/GetPaginatedSettlementRefundsRequestTest.php new file mode 100644 index 000000000..827a5e2a7 --- /dev/null +++ b/tests/Http/Requests/GetPaginatedSettlementRefundsRequestTest.php @@ -0,0 +1,72 @@ + MockResponse::ok('refund-list'), + ]); + + $request = new GetPaginatedSettlementRefundsRequest('stl_jDk30akdN'); + + /** @var RefundCollection */ + $refunds = $client->send($request); + + $this->assertTrue($refunds->getResponse()->successful()); + + $this->assertInstanceOf(RefundCollection::class, $refunds); + $this->assertGreaterThan(0, $refunds->count()); + + foreach ($refunds as $refund) { + $this->assertInstanceOf(Refund::class, $refund); + $this->assertEquals('refund', $refund->resource); + } + } + + /** @test */ + public function it_can_iterate_over_settlement_refunds() + { + $client = new MockMollieClient([ + GetPaginatedSettlementRefundsRequest::class => MockResponse::ok('refund-list'), + DynamicGetRequest::class => new SequenceMockResponse( + MockResponse::ok('refund-list'), + MockResponse::ok('empty-list', 'refunds'), + ), + ]); + + $request = (new GetPaginatedSettlementRefundsRequest('stl_jDk30akdN'))->useIterator(); + + /** @var LazyCollection */ + $refunds = $client->send($request); + $this->assertTrue($refunds->getResponse()->successful()); + + foreach ($refunds as $refund) { + $this->assertInstanceOf(Refund::class, $refund); + } + + $client->assertSentCount(3); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $settlementId = 'stl_jDk30akdN'; + $request = new GetPaginatedSettlementRefundsRequest($settlementId); + + $this->assertEquals("settlements/{$settlementId}/refunds", $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaginatedSettlementsRequestTest.php b/tests/Http/Requests/GetPaginatedSettlementsRequestTest.php new file mode 100644 index 000000000..4fae673ef --- /dev/null +++ b/tests/Http/Requests/GetPaginatedSettlementsRequestTest.php @@ -0,0 +1,70 @@ + MockResponse::ok('settlement-list'), + ]); + + $request = new GetPaginatedSettlementsRequest; + + /** @var SettlementCollection */ + $settlements = $client->send($request); + + $this->assertTrue($settlements->getResponse()->successful()); + $this->assertInstanceOf(SettlementCollection::class, $settlements); + $this->assertGreaterThan(0, $settlements->count()); + + foreach ($settlements as $settlement) { + $this->assertInstanceOf(Settlement::class, $settlement); + $this->assertEquals('settlement', $settlement->resource); + } + } + + /** @test */ + public function it_can_iterate_over_settlements() + { + $client = new MockMollieClient([ + GetPaginatedSettlementsRequest::class => MockResponse::ok('settlement-list'), + DynamicGetRequest::class => new SequenceMockResponse( + MockResponse::ok('settlement-list'), + MockResponse::ok('empty-list', 'settlements'), + ), + ]); + + $request = (new GetPaginatedSettlementsRequest)->useIterator(); + + /** @var LazyCollection */ + $settlements = $client->send($request); + $this->assertTrue($settlements->getResponse()->successful()); + + foreach ($settlements as $settlement) { + $this->assertInstanceOf(Settlement::class, $settlement); + } + + $client->assertSentCount(3); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new GetPaginatedSettlementsRequest; + + $this->assertEquals('settlements', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaginatedSubscriptionPaymentsRequestTest.php b/tests/Http/Requests/GetPaginatedSubscriptionPaymentsRequestTest.php new file mode 100644 index 000000000..e37125663 --- /dev/null +++ b/tests/Http/Requests/GetPaginatedSubscriptionPaymentsRequestTest.php @@ -0,0 +1,73 @@ + MockResponse::ok('payment-list'), + ]); + + $request = new GetPaginatedSubscriptionPaymentsRequest('cst_kEn1PlbGa', 'sub_rVKGtNd6s3', new PaginatedQuery); + + /** @var PaymentCollection */ + $payments = $client->send($request); + + $this->assertTrue($payments->getResponse()->successful()); + $this->assertInstanceOf(PaymentCollection::class, $payments); + $this->assertGreaterThan(0, $payments->count()); + + foreach ($payments as $payment) { + $this->assertInstanceOf(Payment::class, $payment); + $this->assertEquals('payment', $payment->resource); + } + } + + /** @test */ + public function it_can_iterate_over_subscription_payments() + { + $client = new MockMollieClient([ + GetPaginatedSubscriptionPaymentsRequest::class => MockResponse::ok('payment-list'), + DynamicGetRequest::class => new SequenceMockResponse( + MockResponse::ok('payment-list'), + MockResponse::ok('empty-list', 'payments'), + ), + ]); + + $request = (new GetPaginatedSubscriptionPaymentsRequest('cst_kEn1PlbGa', 'sub_rVKGtNd6s3', new PaginatedQuery))->useIterator(); + + /** @var LazyCollection */ + $payments = $client->send($request); + $this->assertTrue($payments->getResponse()->successful()); + + foreach ($payments as $payment) { + $this->assertInstanceOf(Payment::class, $payment); + } + + $client->assertSentCount(3); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $customerId = 'cst_kEn1PlbGa'; + $subscriptionId = 'sub_rVKGtNd6s3'; + $request = new GetPaginatedSubscriptionPaymentsRequest($customerId, $subscriptionId); + + $this->assertEquals("customers/{$customerId}/subscriptions/{$subscriptionId}/payments", $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaginatedSubscriptionsRequestTest.php b/tests/Http/Requests/GetPaginatedSubscriptionsRequestTest.php new file mode 100644 index 000000000..4c1821513 --- /dev/null +++ b/tests/Http/Requests/GetPaginatedSubscriptionsRequestTest.php @@ -0,0 +1,71 @@ + MockResponse::ok('subscription-list'), + ]); + + $request = new GetPaginatedSubscriptionsRequest('cst_kEn1PlbGa'); + + /** @var SubscriptionCollection */ + $subscriptions = $client->send($request); + + $this->assertTrue($subscriptions->getResponse()->successful()); + $this->assertInstanceOf(SubscriptionCollection::class, $subscriptions); + $this->assertGreaterThan(0, $subscriptions->count()); + + foreach ($subscriptions as $subscription) { + $this->assertInstanceOf(Subscription::class, $subscription); + $this->assertEquals('subscription', $subscription->resource); + } + } + + /** @test */ + public function it_can_iterate_over_subscriptions() + { + $client = new MockMollieClient([ + GetPaginatedSubscriptionsRequest::class => MockResponse::ok('subscription-list'), + DynamicGetRequest::class => new SequenceMockResponse( + MockResponse::ok('subscription-list'), + MockResponse::ok('empty-list', 'subscriptions'), + ), + ]); + + $request = (new GetPaginatedSubscriptionsRequest('cst_kEn1PlbGa'))->useIterator(); + + /** @var LazyCollection */ + $subscriptions = $client->send($request); + $this->assertTrue($subscriptions->getResponse()->successful()); + + foreach ($subscriptions as $subscription) { + $this->assertInstanceOf(Subscription::class, $subscription); + } + + $client->assertSentCount(3); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $customerId = 'cst_kEn1PlbGa'; + $request = new GetPaginatedSubscriptionsRequest($customerId); + + $this->assertEquals("customers/{$customerId}/subscriptions", $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaginatedTerminalsRequestTest.php b/tests/Http/Requests/GetPaginatedTerminalsRequestTest.php new file mode 100644 index 000000000..4f88441bf --- /dev/null +++ b/tests/Http/Requests/GetPaginatedTerminalsRequestTest.php @@ -0,0 +1,68 @@ + MockResponse::ok('terminal-list'), + ]); + + $request = new GetPaginatedTerminalsRequest; + + /** @var TerminalCollection */ + $terminals = $client->send($request); + + $this->assertTrue($terminals->getResponse()->successful()); + + foreach ($terminals as $terminal) { + $this->assertInstanceOf(Terminal::class, $terminal); + $this->assertEquals('terminal', $terminal->resource); + } + } + + /** @test */ + public function it_can_iterate_over_terminals() + { + $client = new MockMollieClient([ + GetPaginatedTerminalsRequest::class => MockResponse::ok('terminal-list'), + DynamicGetRequest::class => new SequenceMockResponse( + MockResponse::ok('terminal-list'), + MockResponse::ok('empty-list', 'terminals'), + ), + ]); + + $request = (new GetPaginatedTerminalsRequest)->useIterator(); + + /** @var LazyCollection */ + $terminals = $client->send($request); + $this->assertTrue($terminals->getResponse()->successful()); + + foreach ($terminals as $terminal) { + $this->assertInstanceOf(Terminal::class, $terminal); + } + + $client->assertSentCount(3); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new GetPaginatedTerminalsRequest; + + $this->assertEquals('terminals', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaymentCaptureRequestTest.php b/tests/Http/Requests/GetPaymentCaptureRequestTest.php new file mode 100644 index 000000000..d13dc76bd --- /dev/null +++ b/tests/Http/Requests/GetPaymentCaptureRequestTest.php @@ -0,0 +1,39 @@ + MockResponse::ok('capture'), + ]); + + $request = new GetPaymentCaptureRequest('tr_WDqYK6vllg', 'cpt_4qqhO89gsT'); + + /** @var Capture */ + $capture = $client->send($request); + + $this->assertTrue($capture->getResponse()->successful()); + $this->assertInstanceOf(Capture::class, $capture); + } + + /** @test */ + /** @test */ + public function it_resolves_correct_resource_path() + { + $paymentId = 'tr_WDqYK6vllg'; + $captureId = 'cpt_4qqhO89gsT'; + $request = new GetPaymentCaptureRequest($paymentId, $captureId); + + $this->assertEquals("payments/{$paymentId}/captures/{$captureId}", $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaymentChargebackRequestTest.php b/tests/Http/Requests/GetPaymentChargebackRequestTest.php new file mode 100644 index 000000000..4f4e9b25c --- /dev/null +++ b/tests/Http/Requests/GetPaymentChargebackRequestTest.php @@ -0,0 +1,39 @@ + MockResponse::ok('chargeback'), + ]); + + $request = new GetPaymentChargebackRequest('tr_WDqYK6vllg', 'chb_n9z0tp'); + + /** @var Chargeback */ + $chargeback = $client->send($request); + + $this->assertTrue($chargeback->getResponse()->successful()); + $this->assertInstanceOf(Chargeback::class, $chargeback); + } + + /** @test */ + /** @test */ + public function it_resolves_correct_resource_path() + { + $paymentId = 'tr_WDqYK6vllg'; + $chargebackId = 'chb_n9z0tp'; + $request = new GetPaymentChargebackRequest($paymentId, $chargebackId); + + $this->assertEquals("payments/{$paymentId}/chargebacks/{$chargebackId}", $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaymentLinkRequestTest.php b/tests/Http/Requests/GetPaymentLinkRequestTest.php new file mode 100644 index 000000000..8bd19d68a --- /dev/null +++ b/tests/Http/Requests/GetPaymentLinkRequestTest.php @@ -0,0 +1,38 @@ + MockResponse::ok('payment-link'), + ]); + + $request = new GetPaymentLinkRequest('pl_4Y0eZitmBnQ5jsBYZIBw'); + + /** @var PaymentLink */ + $paymentLink = $client->send($request); + + $this->assertTrue($paymentLink->getResponse()->successful()); + $this->assertInstanceOf(PaymentLink::class, $paymentLink); + } + + /** @test */ + /** @test */ + public function it_resolves_correct_resource_path() + { + $paymentLinkId = 'pl_4Y0eZitmBnQ5jsBYZIBw'; + $request = new GetPaymentLinkRequest($paymentLinkId); + + $this->assertEquals("payment-links/{$paymentLinkId}", $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaymentMethodRequestTest.php b/tests/Http/Requests/GetPaymentMethodRequestTest.php new file mode 100644 index 000000000..d157591cf --- /dev/null +++ b/tests/Http/Requests/GetPaymentMethodRequestTest.php @@ -0,0 +1,37 @@ + MockResponse::ok('method'), + ]); + + $request = new GetPaymentMethodRequest('ideal'); + + /** @var Method */ + $method = $client->send($request); + + $this->assertTrue($method->getResponse()->successful()); + $this->assertInstanceOf(Method::class, $method); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $methodId = 'ideal'; + $request = new GetPaymentMethodRequest($methodId); + + $this->assertEquals("methods/{$methodId}", $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaymentRefundRequestTest.php b/tests/Http/Requests/GetPaymentRefundRequestTest.php new file mode 100644 index 000000000..56e257bfe --- /dev/null +++ b/tests/Http/Requests/GetPaymentRefundRequestTest.php @@ -0,0 +1,40 @@ + MockResponse::ok('refund'), + ]); + + $paymentId = 'tr_WDqYK6vllg'; + $refundId = 're_4qqhO89gsT'; + $request = new GetPaymentRefundRequest($paymentId, $refundId); + + /** @var Refund */ + $refund = $client->send($request); + + $this->assertTrue($refund->getResponse()->successful()); + $this->assertInstanceOf(Refund::class, $refund); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $paymentId = 'tr_WDqYK6vllg'; + $refundId = 're_4qqhO89gsT'; + $request = new GetPaymentRefundRequest($paymentId, $refundId); + + $this->assertEquals("payments/{$paymentId}/refunds/{$refundId}", $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPaymentRequestTest.php b/tests/Http/Requests/GetPaymentRequestTest.php new file mode 100644 index 000000000..9df8e29c2 --- /dev/null +++ b/tests/Http/Requests/GetPaymentRequestTest.php @@ -0,0 +1,38 @@ + MockResponse::ok('payment'), + ]); + + $paymentId = 'tr_WDqYK6vllg'; + $request = new GetPaymentRequest($paymentId); + + /** @var Payment */ + $payment = $client->send($request); + + $this->assertTrue($payment->getResponse()->successful()); + $this->assertInstanceOf(Payment::class, $payment); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $paymentId = 'tr_WDqYK6vllg'; + $request = new GetPaymentRequest($paymentId); + + $this->assertEquals("payments/{$paymentId}", $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/GetPermissionRequestTest.php b/tests/Http/Requests/GetPermissionRequestTest.php new file mode 100644 index 000000000..1e5602aa0 --- /dev/null +++ b/tests/Http/Requests/GetPermissionRequestTest.php @@ -0,0 +1,39 @@ + MockResponse::ok('permission'), + ]); + + $request = new GetPermissionRequest('payments.read'); + + /** @var Permission */ + $permission = $client->send($request); + + $this->assertTrue($permission->getResponse()->successful()); + $this->assertInstanceOf(Permission::class, $permission); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new GetPermissionRequest('payments.read'); + + $this->assertEquals( + 'permissions/payments.read', + $request->resolveResourcePath() + ); + } +} diff --git a/tests/Http/Requests/GetProfileRequestTest.php b/tests/Http/Requests/GetProfileRequestTest.php new file mode 100644 index 000000000..08d349528 --- /dev/null +++ b/tests/Http/Requests/GetProfileRequestTest.php @@ -0,0 +1,39 @@ + MockResponse::ok('profile'), + ]); + + $request = new GetProfileRequest('pfl_v9hTwCvYqw'); + + /** @var Profile */ + $profile = $client->send($request); + + $this->assertTrue($profile->getResponse()->successful()); + $this->assertInstanceOf(Profile::class, $profile); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new GetProfileRequest('pfl_v9hTwCvYqw'); + + $this->assertEquals( + 'profiles/pfl_v9hTwCvYqw', + $request->resolveResourcePath() + ); + } +} diff --git a/tests/Http/Requests/GetSalesInvoiceRequestTest.php b/tests/Http/Requests/GetSalesInvoiceRequestTest.php new file mode 100644 index 000000000..312470d84 --- /dev/null +++ b/tests/Http/Requests/GetSalesInvoiceRequestTest.php @@ -0,0 +1,28 @@ + MockResponse::ok('sales-invoice'), + ]); + + $request = new GetSalesInvoiceRequest('invoice_123'); + + /** @var SalesInvoice */ + $salesInvoice = $client->send($request); + + $this->assertTrue($salesInvoice->getResponse()->successful()); + $this->assertInstanceOf(SalesInvoice::class, $salesInvoice); + } +} diff --git a/tests/Http/Requests/GetSessionRequestTest.php b/tests/Http/Requests/GetSessionRequestTest.php new file mode 100644 index 000000000..d24a0edc9 --- /dev/null +++ b/tests/Http/Requests/GetSessionRequestTest.php @@ -0,0 +1,48 @@ + MockResponse::ok('session'), + ]); + + $query = new AnyData([ + 'testmode' => true, + ]); + + $request = new GetSessionRequest('ses_LQNz4v4Qvk', $query); + + /** @var Session */ + $session = $client->send($request); + + $this->assertTrue($session->getResponse()->successful()); + $this->assertInstanceOf(Session::class, $session); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $query = new AnyData([ + 'testmode' => true, + ]); + + $request = new GetSessionRequest('ses_LQNz4v4Qvk', $query); + + $this->assertEquals( + 'sessions/ses_LQNz4v4Qvk', + $request->resolveResourcePath() + ); + } +} diff --git a/tests/Http/Requests/GetSettlementRequestTest.php b/tests/Http/Requests/GetSettlementRequestTest.php new file mode 100644 index 000000000..fee759f6f --- /dev/null +++ b/tests/Http/Requests/GetSettlementRequestTest.php @@ -0,0 +1,39 @@ + MockResponse::ok('settlement'), + ]); + + $request = new GetSettlementRequest('stl_jDk30akdN'); + + /** @var Settlement */ + $settlement = $client->send($request); + + $this->assertTrue($settlement->getResponse()->successful()); + $this->assertInstanceOf(Settlement::class, $settlement); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new GetSettlementRequest('stl_jDk30akdN'); + + $this->assertEquals( + 'settlements/stl_jDk30akdN', + $request->resolveResourcePath() + ); + } +} diff --git a/tests/Http/Requests/GetSubscriptionRequestTest.php b/tests/Http/Requests/GetSubscriptionRequestTest.php new file mode 100644 index 000000000..60d003043 --- /dev/null +++ b/tests/Http/Requests/GetSubscriptionRequestTest.php @@ -0,0 +1,39 @@ + MockResponse::ok('subscription'), + ]); + + $request = new GetSubscriptionRequest('cst_kEn1PlbGa', 'sub_rVKGtNd6s3'); + + /** @var Subscription */ + $subscription = $client->send($request); + + $this->assertTrue($subscription->getResponse()->successful()); + $this->assertInstanceOf(Subscription::class, $subscription); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new GetSubscriptionRequest('cst_kEn1PlbGa', 'sub_rVKGtNd6s3'); + + $this->assertEquals( + 'customers/cst_kEn1PlbGa/subscriptions/sub_rVKGtNd6s3', + $request->resolveResourcePath() + ); + } +} diff --git a/tests/Http/Requests/GetTerminalRequestTest.php b/tests/Http/Requests/GetTerminalRequestTest.php new file mode 100644 index 000000000..6aed7e907 --- /dev/null +++ b/tests/Http/Requests/GetTerminalRequestTest.php @@ -0,0 +1,39 @@ + MockResponse::ok('terminal'), + ]); + + $request = new GetTerminalRequest('term_7MgL4wea'); + + /** @var Terminal */ + $terminal = $client->send($request); + + $this->assertTrue($terminal->getResponse()->successful()); + $this->assertInstanceOf(Terminal::class, $terminal); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new GetTerminalRequest('term_7MgL4wea'); + + $this->assertEquals( + 'terminals/term_7MgL4wea', + $request->resolveResourcePath() + ); + } +} diff --git a/tests/Http/Requests/ListPermissionsRequestTest.php b/tests/Http/Requests/ListPermissionsRequestTest.php new file mode 100644 index 000000000..7c087feb1 --- /dev/null +++ b/tests/Http/Requests/ListPermissionsRequestTest.php @@ -0,0 +1,43 @@ + MockResponse::ok('permission-list'), + ]); + + $request = new ListPermissionsRequest; + + /** @var PermissionCollection */ + $permissions = $client->send($request); + + $this->assertTrue($permissions->getResponse()->successful()); + $this->assertInstanceOf(PermissionCollection::class, $permissions); + $this->assertGreaterThan(0, $permissions->count()); + + foreach ($permissions as $permission) { + $this->assertInstanceOf(Permission::class, $permission); + $this->assertEquals('permission', $permission->resource); + } + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new ListPermissionsRequest; + + $this->assertEquals('permissions', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/PaginatedRequestTest.php b/tests/Http/Requests/PaginatedRequestTest.php new file mode 100644 index 000000000..d4d0307f6 --- /dev/null +++ b/tests/Http/Requests/PaginatedRequestTest.php @@ -0,0 +1,53 @@ +assertEquals([], $request->query()->all()); + } + + /** @test */ + public function it_can_handle_query() + { + $query = new ConcreteQuery(['limit' => 10]); + $request = new ConcretePaginatedRequest($query); + + $this->assertEquals(['limit' => 10], $request->query()->all()); + } +} + +class ConcretePaginatedRequest extends PaginatedRequest +{ + protected $hydratableResource = BaseCollection::class; + + public function resolveResourcePath(): string + { + return 'test'; + } +} + +class ConcreteQuery implements Arrayable +{ + private array $parameters; + + public function __construct(array $parameters) + { + $this->parameters = $parameters; + } + + public function toArray(): array + { + return $this->parameters; + } +} diff --git a/tests/Http/Requests/ResourceHydratableRequestTest.php b/tests/Http/Requests/ResourceHydratableRequestTest.php new file mode 100644 index 000000000..b2114867d --- /dev/null +++ b/tests/Http/Requests/ResourceHydratableRequestTest.php @@ -0,0 +1,85 @@ +assertEquals(BaseResource::class, $request->getHydratableResource()); + } + + /** @test */ + public function it_throws_exception_when_target_resource_class_is_not_set() + { + $request = new InvalidResourceHydratableRequest; + + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Resource class is not set.'); + + $request->getHydratableResource(); + } + + /** @test */ + public function it_can_hydrate_response_into_resource_wrapper() + { + $request = new class extends ResourceHydratableRequest + { + protected $hydratableResource = DummyResource::class; + + public function resolveResourcePath(): string + { + return 'test'; + } + }; + + // Set the wrapper as the hydratable resource + $request->setHydratableResource(new WrapperResource(DummyResourceWrapper::class)); + + // Assert the wrapper is set as the hydratable resource + $this->assertInstanceOf(WrapperResource::class, $request->getHydratableResource()); + $this->assertTrue($request->isHydratable()); + } +} + +class ConcreteResourceHydratableRequest extends ResourceHydratableRequest +{ + protected $hydratableResource = BaseResource::class; + + public function resolveResourcePath(): string + { + return 'test'; + } +} + +class InvalidResourceHydratableRequest extends ResourceHydratableRequest +{ + public function resolveResourcePath(): string + { + return 'test'; + } +} + +class DummyResource extends BaseResource +{ + public $id; + + public $name; +} + +class DummyResourceWrapper extends ResourceWrapper +{ + public static function fromResource($resource): self + { + return (new self)->wrap($resource); + } +} diff --git a/tests/Http/Requests/RevokeMandateRequestTest.php b/tests/Http/Requests/RevokeMandateRequestTest.php new file mode 100644 index 000000000..d6729c45f --- /dev/null +++ b/tests/Http/Requests/RevokeMandateRequestTest.php @@ -0,0 +1,43 @@ + MockResponse::noContent(''), + ]); + + $customerId = 'cst_kEn1PlbGa'; + $mandateId = 'mdt_h3gAaD5zP'; + $request = new RevokeMandateRequest($customerId, $mandateId); + + /** @var Response */ + $response = $client->send($request); + + $this->assertTrue($response->successful()); + $this->assertEquals(204, $response->status()); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $customerId = 'cst_kEn1PlbGa'; + $mandateId = 'mdt_h3gAaD5zP'; + $request = new RevokeMandateRequest($customerId, $mandateId); + + $this->assertEquals( + "customers/{$customerId}/mandates/{$mandateId}", + $request->resolveResourcePath() + ); + } +} diff --git a/tests/Http/Requests/UpdateCustomerRequestTest.php b/tests/Http/Requests/UpdateCustomerRequestTest.php new file mode 100644 index 000000000..eb519ab7c --- /dev/null +++ b/tests/Http/Requests/UpdateCustomerRequestTest.php @@ -0,0 +1,43 @@ + MockResponse::ok('customer'), + ]); + + $request = new UpdateCustomerRequest('cst_kEn1PlbGa', new UpdateCustomerPayload( + 'Updated Customer Name', + 'updated@example.com', + )); + + /** @var Customer */ + $customer = $client->send($request); + + $this->assertTrue($customer->getResponse()->successful()); + $this->assertInstanceOf(Customer::class, $customer); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new UpdateCustomerRequest('cst_kEn1PlbGa', new UpdateCustomerPayload( + 'Updated Customer Name', + 'updated@example.com', + )); + + $this->assertEquals('customers/cst_kEn1PlbGa', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/UpdatePaymentLinkRequestTest.php b/tests/Http/Requests/UpdatePaymentLinkRequestTest.php new file mode 100644 index 000000000..4f2c89bac --- /dev/null +++ b/tests/Http/Requests/UpdatePaymentLinkRequestTest.php @@ -0,0 +1,41 @@ + MockResponse::ok('payment-link'), + ]); + + $request = new UpdatePaymentLinkRequest('pl_4Y0eZitmBnQ5jsBYZIBw', new UpdatePaymentLinkPayload( + 'Updated payment link', + )); + + /** @var PaymentLink */ + $paymentLink = $client->send($request); + + $this->assertTrue($paymentLink->getResponse()->successful()); + $this->assertInstanceOf(PaymentLink::class, $paymentLink); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new UpdatePaymentLinkRequest('pl_4Y0eZitmBnQ5jsBYZIBw', new UpdatePaymentLinkPayload( + 'Updated payment link', + )); + + $this->assertEquals('payment-links/pl_4Y0eZitmBnQ5jsBYZIBw', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/UpdatePaymentRequestTest.php b/tests/Http/Requests/UpdatePaymentRequestTest.php new file mode 100644 index 000000000..a8d881008 --- /dev/null +++ b/tests/Http/Requests/UpdatePaymentRequestTest.php @@ -0,0 +1,43 @@ + MockResponse::ok('payment'), + ]); + + $request = new UpdatePaymentRequest('tr_WDqYK6vllg', new UpdatePaymentPayload( + 'Updated payment description', + 'https://example.com/redirect', + )); + + /** @var Payment */ + $payment = $client->send($request); + + $this->assertTrue($payment->getResponse()->successful()); + $this->assertInstanceOf(Payment::class, $payment); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new UpdatePaymentRequest('tr_WDqYK6vllg', new UpdatePaymentPayload( + 'Updated payment description', + 'https://example.com/redirect', + )); + + $this->assertEquals('payments/tr_WDqYK6vllg', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/UpdatePaymentRouteRequestTest.php b/tests/Http/Requests/UpdatePaymentRouteRequestTest.php new file mode 100644 index 000000000..e7d969ccb --- /dev/null +++ b/tests/Http/Requests/UpdatePaymentRouteRequestTest.php @@ -0,0 +1,42 @@ + MockResponse::ok('route'), + ]); + + $request = new UpdatePaymentRouteRequest('tr_WDqYK6vllg', 'rt_H2wvxEyQcP', new UpdatePaymentRoutePayload( + new DateTime('2024-01-01'), + )); + + /** @var Route */ + $route = $client->send($request); + + $this->assertTrue($route->getResponse()->successful()); + $this->assertInstanceOf(Route::class, $route); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new UpdatePaymentRouteRequest('tr_WDqYK6vllg', 'rt_H2wvxEyQcP', new UpdatePaymentRoutePayload( + new DateTime('2024-01-01'), + )); + + $this->assertEquals('payments/tr_WDqYK6vllg/routes/rt_H2wvxEyQcP', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/UpdateProfileRequestTest.php b/tests/Http/Requests/UpdateProfileRequestTest.php new file mode 100644 index 000000000..516daf968 --- /dev/null +++ b/tests/Http/Requests/UpdateProfileRequestTest.php @@ -0,0 +1,41 @@ + MockResponse::ok('profile'), + ]); + + $request = new UpdateProfileRequest('pfl_v9hTwCvYqw', new UpdateProfilePayload( + 'Updated Profile Name', + )); + + /** @var Profile */ + $profile = $client->send($request); + + $this->assertTrue($profile->getResponse()->successful()); + $this->assertInstanceOf(Profile::class, $profile); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new UpdateProfileRequest('pfl_v9hTwCvYqw', new UpdateProfilePayload( + 'Updated Profile Name', + )); + + $this->assertEquals('profiles/pfl_v9hTwCvYqw', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/UpdateSalesInvoiceRequestTest.php b/tests/Http/Requests/UpdateSalesInvoiceRequestTest.php new file mode 100644 index 000000000..2fa61bf0b --- /dev/null +++ b/tests/Http/Requests/UpdateSalesInvoiceRequestTest.php @@ -0,0 +1,44 @@ + MockResponse::ok('sales-invoice'), + ]); + + $payload = new UpdateSalesInvoicePayload( + SalesInvoiceStatus::PAID, + 'XXXXX', + ); + $request = new UpdateSalesInvoiceRequest('invoice_123', $payload); + + /** @var SalesInvoice */ + $salesInvoice = $client->send($request); + + $this->assertTrue($salesInvoice->getResponse()->successful()); + $this->assertInstanceOf(SalesInvoice::class, $salesInvoice); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $request = new UpdateSalesInvoiceRequest('invoice_123', new UpdateSalesInvoicePayload( + SalesInvoiceStatus::PAID, + 'XXXXX', + )); + $this->assertEquals('sales-invoices/invoice_123', $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/UpdateSessionRequestTest.php b/tests/Http/Requests/UpdateSessionRequestTest.php new file mode 100644 index 000000000..6bf9737dc --- /dev/null +++ b/tests/Http/Requests/UpdateSessionRequestTest.php @@ -0,0 +1,47 @@ + MockResponse::ok('session'), + ]); + + $payload = new AnyData([ + 'status' => 'completed', + 'metadata' => [ + 'order_id' => '12345', + ], + ]); + + $request = new UpdateSessionRequest('ses_LQNz4v4Qvk', $payload); + + /** @var Session */ + $session = $client->send($request); + + $this->assertTrue($session->getResponse()->successful()); + + $this->assertInstanceOf(Session::class, $session); + $this->assertEquals('session', $session->resource); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $sessionId = 'ses_LQNz4v4Qvk'; + $request = new UpdateSessionRequest($sessionId, new AnyData); + + $this->assertEquals("sessions/{$sessionId}", $request->resolveResourcePath()); + } +} diff --git a/tests/Http/Requests/UpdateSubscriptionRequestTest.php b/tests/Http/Requests/UpdateSubscriptionRequestTest.php new file mode 100644 index 000000000..7d7a6257e --- /dev/null +++ b/tests/Http/Requests/UpdateSubscriptionRequestTest.php @@ -0,0 +1,59 @@ + MockResponse::ok('subscription'), + ]); + + $customerId = 'cst_kEn1PlbGa'; + $subscriptionId = 'sub_rVKGtNd6s3'; + + $money = new Money('EUR', '20.00'); + $payload = new UpdateSubscriptionPayload( + $money, + 'Updated subscription', + '1 month' + ); + + $request = new UpdateSubscriptionRequest($customerId, $subscriptionId, $payload); + + $this->assertEquals( + "customers/{$customerId}/subscriptions/{$subscriptionId}", + $request->resolveResourcePath() + ); + + /** @var Subscription */ + $subscription = $client->send($request); + + $this->assertTrue($subscription->getResponse()->successful()); + $this->assertInstanceOf(Subscription::class, $subscription); + } + + /** @test */ + public function it_resolves_correct_resource_path() + { + $customerId = 'cst_kEn1PlbGa'; + $subscriptionId = 'sub_rVKGtNd6s3'; + $request = new UpdateSubscriptionRequest($customerId, $subscriptionId, new UpdateSubscriptionPayload( + new Money('EUR', '20.00'), + 'Updated subscription', + '1 month' + )); + + $this->assertEquals("customers/{$customerId}/subscriptions/{$subscriptionId}", $request->resolveResourcePath()); + } +} diff --git a/tests/Mollie/API/Endpoints/BalanceEndpointTest.php b/tests/Mollie/API/Endpoints/BalanceEndpointTest.php deleted file mode 100644 index c2b14129b..000000000 --- a/tests/Mollie/API/Endpoints/BalanceEndpointTest.php +++ /dev/null @@ -1,487 +0,0 @@ -mockApiCall( - new Request( - "GET", - "/v2/balances" - ), - new Response( - 200, - [], - '{ - "count": 2, - "_embedded": { - "balances": [ - { - "resource": "balance", - "id": "bal_gVMhHKqSSRYJyPsuoPNFH", - "mode": "live", - "createdAt": "2019-01-10T12:06:28+00:00", - "currency": "EUR", - "status": "active", - "availableAmount": { - "value": "0.00", - "currency": "EUR" - }, - "incomingAmount": { - "value": "0.00", - "currency": "EUR" - }, - "outgoingAmount": { - "value": "0.00", - "currency": "EUR" - }, - "transferFrequency": "daily", - "transferThreshold": { - "value": "40.00", - "currency": "EUR" - }, - "transferReference": "Mollie payout", - "transferDestination": { - "type": "bank-account", - "beneficiaryName": "Jack Bauer", - "bankAccount": "NL53INGB0654422370", - "bankAccountId": "bnk_jrty3f" - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/balances/bal_gVMhHKqSSRYJyPsuoPNFH", - "type": "application/hal+json" - } - } - }, - { - "resource": "balance", - "id": "bal_gVMhHKqSSRYJyPsuoPABC", - "mode": "live", - "createdAt": "2019-01-10T10:23:41+00:00", - "status": "active", - "currency": "EUR", - "availableAmount": { - "value": "0.00", - "currency": "EUR" - }, - "incomingAmount": { - "value": "0.00", - "currency": "EUR" - }, - "outgoingAmount": { - "value": "0.00", - "currency": "EUR" - }, - "transferFrequency": "twice-a-month", - "transferThreshold": { - "value": "5.00", - "currency": "EUR" - }, - "transferReference": "Mollie payout", - "transferDestination": { - "type": "bank-account", - "beneficiaryName": "Jack Bauer", - "bankAccount": "NL97MOLL6351480700", - "bankAccountId": "bnk_jrty3e" - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/balances/bal_gVMhHKqSSRYJyPsuoPABC", - "type": "application/hal+json" - } - } - } - ] - }, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/balances-api/list-balances", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.com/v2/balances?limit=5", - "type": "application/hal+json" - }, - "previous": null, - "next": { - "href": "https://api.mollie.com/v2/balances?from=bal_gVMhHKqSSRYJyPsuoPABC&limit=5", - "type": "application/hal+json" - } - } - }' - ) - ); - - /** @var BalanceCollection $balances */ - $balances = $this->apiClient->balances->page(); - - $this->assertInstanceOf(BalanceCollection::class, $balances); - $this->assertEquals(2, $balances->count); - $this->assertCount(2, $balances); - - $this->assertLinkObject( - "https://docs.mollie.com/reference/v2/balances-api/list-balances", - "text/html", - $balances->_links->documentation - ); - - $this->assertLinkObject( - "https://api.mollie.com/v2/balances?limit=5", - "application/hal+json", - $balances->_links->self - ); - - $this->assertLinkObject( - "https://api.mollie.com/v2/balances?from=bal_gVMhHKqSSRYJyPsuoPABC&limit=5", - "application/hal+json", - $balances->_links->next - ); - - /** @var Balance $balanceA */ - $balanceA = $balances[0]; - - /** @var Balance $balanceB */ - $balanceB = $balances[1]; - - $this->assertBalance( - $balanceA, - "bal_gVMhHKqSSRYJyPsuoPNFH", - "2019-01-10T12:06:28+00:00", - BalanceTransferFrequency::DAILY, - "40.00", - (object) [ - "type" => "bank-account", - "beneficiaryName" => "Jack Bauer", - "bankAccount" => "NL53INGB0654422370", - "bankAccountId" => "bnk_jrty3f", - ] - ); - $this->assertBalance( - $balanceB, - "bal_gVMhHKqSSRYJyPsuoPABC", - "2019-01-10T10:23:41+00:00", - BalanceTransferFrequency::TWICE_A_MONTH, - "5.00", - (object) [ - "type" => "bank-account", - "beneficiaryName" => "Jack Bauer", - "bankAccount" => "NL97MOLL6351480700", - "bankAccountId" => "bnk_jrty3e", - ] - ); - } - - public function testIterateBalances() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/balances" - ), - new Response( - 200, - [], - '{ - "count": 2, - "_embedded": { - "balances": [ - { - "resource": "balance", - "id": "bal_gVMhHKqSSRYJyPsuoPNFH", - "mode": "live", - "createdAt": "2019-01-10T12:06:28+00:00", - "currency": "EUR", - "status": "active", - "availableAmount": { - "value": "0.00", - "currency": "EUR" - }, - "incomingAmount": { - "value": "0.00", - "currency": "EUR" - }, - "outgoingAmount": { - "value": "0.00", - "currency": "EUR" - }, - "transferFrequency": "daily", - "transferThreshold": { - "value": "40.00", - "currency": "EUR" - }, - "transferReference": "Mollie payout", - "transferDestination": { - "type": "bank-account", - "beneficiaryName": "Jack Bauer", - "bankAccount": "NL53INGB0654422370", - "bankAccountId": "bnk_jrty3f" - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/balances/bal_gVMhHKqSSRYJyPsuoPNFH", - "type": "application/hal+json" - } - } - }, - { - "resource": "balance", - "id": "bal_gVMhHKqSSRYJyPsuoPABC", - "mode": "live", - "createdAt": "2019-01-10T10:23:41+00:00", - "status": "active", - "currency": "EUR", - "availableAmount": { - "value": "0.00", - "currency": "EUR" - }, - "incomingAmount": { - "value": "0.00", - "currency": "EUR" - }, - "outgoingAmount": { - "value": "0.00", - "currency": "EUR" - }, - "transferFrequency": "twice-a-month", - "transferThreshold": { - "value": "5.00", - "currency": "EUR" - }, - "transferReference": "Mollie payout", - "transferDestination": { - "type": "bank-account", - "beneficiaryName": "Jack Bauer", - "bankAccount": "NL97MOLL6351480700", - "bankAccountId": "bnk_jrty3e" - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/balances/bal_gVMhHKqSSRYJyPsuoPABC", - "type": "application/hal+json" - } - } - } - ] - }, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/balances-api/list-balances", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.com/v2/balances?limit=5", - "type": "application/hal+json" - }, - "previous": null, - "next": null - } - }' - ) - ); - - foreach ($this->apiClient->balances->iterator() as $balance) { - $this->assertInstanceOf(Balance::class, $balance); - } - } - - public function testGetBalance() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/balances/bal_gVMhHKqSSRYJyPsuoPNFH" - ), - new Response( - 200, - [], - '{ - "resource": "balance", - "id": "bal_gVMhHKqSSRYJyPsuoPNFH", - "mode": "live", - "createdAt": "2019-01-10T10:23:41+00:00", - "currency": "EUR", - "status": "active", - "availableAmount": { - "value": "0.00", - "currency": "EUR" - }, - "incomingAmount": { - "value": "0.00", - "currency": "EUR" - }, - "outgoingAmount": { - "value": "0.00", - "currency": "EUR" - }, - "transferFrequency": "twice-a-month", - "transferThreshold": { - "value": "5.00", - "currency": "EUR" - }, - "transferReference": "Mollie payout", - "transferDestination": { - "type": "bank-account", - "beneficiaryName": "Jack Bauer", - "bankAccount": "NL53INGB0654422370", - "bankAccountId": "bnk_jrty3f" - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/balances/bal_gVMhHKqSSRYJyPsuoPNFH", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/balances-api/get-balance", - "type": "text/html" - } - } - }' - ) - ); - - /** @var Balance $balance */ - $balance = $this->apiClient->balances->get("bal_gVMhHKqSSRYJyPsuoPNFH"); - - $this->assertBalance( - $balance, - "bal_gVMhHKqSSRYJyPsuoPNFH", - "2019-01-10T10:23:41+00:00", - BalanceTransferFrequency::TWICE_A_MONTH, - "5.00", - (object) [ - 'type' => 'bank-account', - 'beneficiaryName' => 'Jack Bauer', - 'bankAccount' => 'NL53INGB0654422370', - 'bankAccountId' => 'bnk_jrty3f', - ] - ); - } - - public function testGetPrimaryBalance() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/balances/primary" - ), - new Response( - 200, - [], - '{ - "resource": "balance", - "id": "bal_gVMhHKqSSRYJyPsuoPNFH", - "mode": "live", - "createdAt": "2019-01-10T10:23:41+00:00", - "currency": "EUR", - "status": "active", - "availableAmount": { - "value": "0.00", - "currency": "EUR" - }, - "incomingAmount": { - "value": "0.00", - "currency": "EUR" - }, - "outgoingAmount": { - "value": "0.00", - "currency": "EUR" - }, - "transferFrequency": "twice-a-month", - "transferThreshold": { - "value": "5.00", - "currency": "EUR" - }, - "transferReference": "Mollie payout", - "transferDestination": { - "type": "bank-account", - "beneficiaryName": "Jack Bauer", - "bankAccount": "NL53INGB0654422370", - "bankAccountId": "bnk_jrty3f" - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/balances/bal_gVMhHKqSSRYJyPsuoPNFH", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/balances-api/get-balance", - "type": "text/html" - } - } - }' - ) - ); - - /** @var Balance $balance */ - $balance = $this->apiClient->balances->primary(); - - $this->assertBalance( - $balance, - "bal_gVMhHKqSSRYJyPsuoPNFH", - "2019-01-10T10:23:41+00:00", - BalanceTransferFrequency::TWICE_A_MONTH, - "5.00", - (object) [ - 'type' => 'bank-account', - 'beneficiaryName' => 'Jack Bauer', - 'bankAccount' => 'NL53INGB0654422370', - 'bankAccountId' => 'bnk_jrty3f', - ] - ); - } - - /** - * @param \Mollie\Api\Resources\Balance $balance - * @param string $balanceId - * @param string $createdAt - * @param string $transferFrequency - * @param string $thresholdValue - * @param \stdClass $destination - * @return void - */ - protected function assertBalance( - Balance $balance, - string $balanceId, - string $createdAt, - string $transferFrequency, - string $thresholdValue, - \stdClass $destination - ) { - $this->assertInstanceOf(Balance::class, $balance); - $this->assertEquals("balance", $balance->resource); - $this->assertEquals($balanceId, $balance->id); - - $this->assertEquals("live", $balance->mode); - $this->assertEquals($createdAt, $balance->createdAt); - $this->assertEquals("EUR", $balance->currency); - $this->assertAmountObject("0.00", "EUR", $balance->availableAmount); - $this->assertAmountObject("0.00", "EUR", $balance->incomingAmount); - $this->assertAmountObject("0.00", "EUR", $balance->outgoingAmount); - $this->assertEquals($transferFrequency, $balance->transferFrequency); - $this->assertAmountObject($thresholdValue, "EUR", $balance->transferThreshold); - $this->assertEquals("Mollie payout", $balance->transferReference); - $this->assertEquals($destination, $balance->transferDestination); - - $this->assertLinkObject( - "https://api.mollie.com/v2/balances/{$balanceId}", - "application/hal+json", - $balance->_links->self - ); - } -} diff --git a/tests/Mollie/API/Endpoints/BalanceReportEndpointTest.php b/tests/Mollie/API/Endpoints/BalanceReportEndpointTest.php deleted file mode 100644 index 32d1a9988..000000000 --- a/tests/Mollie/API/Endpoints/BalanceReportEndpointTest.php +++ /dev/null @@ -1,398 +0,0 @@ -mockApiCall( - new Request( - "GET", - "/v2/balances/bal_gVMhHKqSSRYJyPsuoPNFH/report?from=2021-01-01&until=2021-02-01&grouping=transaction-categories" - ), - new Response( - 200, - [], - $this->getBalanceReportStub() - ) - ); - - $balance = new Balance($this->apiClient); - $balance->id = "bal_gVMhHKqSSRYJyPsuoPNFH"; - - $report = $this->apiClient->balanceReports->getFor($balance, [ - "from" => "2021-01-01", - "until" => "2021-02-01", - "grouping" => "transaction-categories", - ]); - - $this->assertBalanceReport($report); - } - - public function testCanGetPrimaryBalanceReportThroughBalanceReportEndpoint() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/balances/primary/report?from=2021-01-01&until=2021-02-01&grouping=transaction-categories" - ), - new Response( - 200, - [], - $this->getBalanceReportStub() - ) - ); - - $report = $this->apiClient->balanceReports->getForPrimary([ - "from" => "2021-01-01", - "until" => "2021-02-01", - "grouping" => "transaction-categories", - ]); - - $this->assertBalanceReport($report); - } - - private function getBalanceReportStub() - { - return - '{ - "resource": "balance-report", - "balanceId": "bal_gVMhHKqSSRYJyPsuoPNFH", - "timeZone": "Europe/Amsterdam", - "from": "2021-01-01", - "until": "2021-01-31", - "grouping": "transaction-categories", - "totals": { - "open": { - "available": { - "amount": { - "currency": "EUR", - "value": "0.00" - } - }, - "pending": { - "amount": { - "currency": "EUR", - "value": "0.00" - } - } - }, - "payments": { - "immediatelyAvailable": { - "amount": { - "currency": "EUR", - "value": "0.00" - } - }, - "pending": { - "amount": { - "currency": "EUR", - "value": "4.98" - }, - "subtotals": [ - { - "transactionType": "payment", - "count": 1, - "amount": { - "currency": "EUR", - "value": "4.98" - }, - "subtotals": [ - { - "amount": { - "currency": "EUR", - "value": "4.98" - }, - "count": 1, - "method": "ideal" - } - ] - } - ] - }, - "movedToAvailable": { - "amount": { - "currency": "EUR", - "value": "0.00" - } - } - }, - "refunds": {}, - "chargebacks": {}, - "capital": {}, - "transfers": {}, - "fee-prepayments": { - "immediatelyAvailable": { - "amount": { - "currency": "EUR", - "value": "0.00" - } - }, - "movedToAvailable": { - "amount": { - "currency": "EUR", - "value": "-0.36" - }, - "subtotals": [ - { - "amount": { - "currency": "EUR", - "value": "-0.29" - }, - "count": 1, - "prepaymentPartType": "fee", - "subtotals": [ - { - "amount": { - "currency": "EUR", - "value": "-0.29" - }, - "count": 1, - "feeType": "payment-fee", - "subtotals": [ - { - "amount": { - "currency": "EUR", - "value": "-0.29" - }, - "count": 1, - "method": "ideal" - } - ] - } - ] - }, - { - "amount": { - "currency": "EUR", - "value": "-0.0609" - }, - "prepaymentPartType": "fee-vat" - }, - { - "amount": { - "currency": "EUR", - "value": "-0.0091" - }, - "prepaymentPartType": "fee-rounding-compensation" - } - ] - }, - "pending": { - "amount": { - "currency": "EUR", - "value": "-0.36" - }, - "subtotals": [ - { - "amount": { - "currency": "EUR", - "value": "-0.29" - }, - "count": 1, - "prepaymentPartType": "fee", - "subtotals": [ - { - "amount": { - "currency": "EUR", - "value": "-0.29" - }, - "count": 1, - "feeType": "payment-fee", - "subtotals": [ - { - "amount": { - "currency": "EUR", - "value": "-0.29" - }, - "count": 1, - "method": "ideal" - } - ] - } - ] - }, - { - "amount": { - "currency": "EUR", - "value": "-0.0609" - }, - "prepaymentPartType": "fee-vat" - }, - { - "amount": { - "currency": "EUR", - "value": "-0.0091" - }, - "prepaymentPartType": "fee-rounding-compensation" - } - ] - } - }, - "corrections": {}, - "close": { - "available": { - "amount": { - "currency": "EUR", - "value": "0.00" - } - }, - "pending": { - "amount": { - "currency": "EUR", - "value": "4.32" - } - } - } - }, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/balances-api/get-balance-report", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.com/v2/balances/bal_gVMhHKqSSRYJyPsuoPNFH/report?from=2021-01-01&until=2021-02-01&grouping=transaction-categories", - "type": "application/hal+json" - } - } - }'; - } - - private function assertBalanceReport($report) - { - $this->assertInstanceOf(BalanceReport::class, $report); - $this->assertEquals("balance-report", $report->resource); - $this->assertEquals("bal_gVMhHKqSSRYJyPsuoPNFH", $report->balanceId); - $this->assertEquals("Europe/Amsterdam", $report->timeZone); - $this->assertEquals($report->from, "2021-01-01"); - $this->assertEquals($report->until, "2021-01-31"); - $this->assertEquals($report->grouping, "transaction-categories"); - $this->assertAmountObject('0.00', 'EUR', $report->totals->open->available->amount); - $this->assertAmountObject('0.00', 'EUR', $report->totals->open->pending->amount); - $this->assertAmountObject( - '0.00', - 'EUR', - $report->totals->payments->immediatelyAvailable->amount - ); - $this->assertAmountObject( - '4.98', - 'EUR', - $report->totals->payments->pending->amount - ); - $this->assertAmountObject( - '4.98', - 'EUR', - $report->totals->payments->pending->subtotals[0]->amount - ); - $this->assertEquals( - "payment", - $report->totals->payments->pending->subtotals[0]->transactionType - ); - $this->assertEquals( - 1, - $report->totals->payments->pending->subtotals[0]->count - ); - $this->assertAmountObject( - "4.98", - "EUR", - $report->totals->payments->pending->subtotals[0]->subtotals[0]->amount - ); - $this->assertEquals( - 1, - $report->totals->payments->pending->subtotals[0]->subtotals[0]->count - ); - $this->assertEquals( - "ideal", - $report->totals->payments->pending->subtotals[0]->subtotals[0]->method - ); - $this->assertAmountObject( - "0.00", - "EUR", - $report->totals->payments->movedToAvailable->amount - ); - $this->assertEquals(new \stdClass, $report->totals->refunds); - $this->assertEquals(new \stdClass, $report->totals->chargebacks); - $this->assertEquals(new \stdClass, $report->totals->capital); - $this->assertEquals(new \stdClass, $report->totals->transfers); - - $this->assertAmountObject( - "0.00", - "EUR", - $report->totals->{"fee-prepayments"}->immediatelyAvailable->amount - ); - - $movedToAvailable = $report->totals->{"fee-prepayments"}->movedToAvailable; - - $this->assertAmountObject( - "-0.36", - "EUR", - $movedToAvailable->amount - ); - - $this->assertAmountObject( - "-0.29", - "EUR", - $movedToAvailable->subtotals[0]->amount - ); - - $this->assertEquals(1, $movedToAvailable->subtotals[0]->count); - $this->assertEquals("fee", $movedToAvailable->subtotals[0]->prepaymentPartType); - - $this->assertAmountObject( - "-0.29", - "EUR", - $movedToAvailable->subtotals[0]->subtotals[0]->amount - ); - $this->assertEquals(1, $movedToAvailable->subtotals[0]->subtotals[0]->count); - $this->assertEquals("payment-fee", $movedToAvailable->subtotals[0]->subtotals[0]->feeType); - - $this->assertAmountObject( - "-0.29", - "EUR", - $movedToAvailable->subtotals[0]->subtotals[0]->subtotals[0]->amount - ); - $this->assertEquals(1, $movedToAvailable->subtotals[0]->subtotals[0]->subtotals[0]->count); - $this->assertEquals("ideal", $movedToAvailable->subtotals[0]->subtotals[0]->subtotals[0]->method); - - $this->assertAmountObject( - "-0.0609", - "EUR", - $movedToAvailable->subtotals[1]->amount - ); - $this->assertEquals("fee-vat", $movedToAvailable->subtotals[1]->prepaymentPartType); - - $this->assertAmountObject( - "-0.0091", - "EUR", - $movedToAvailable->subtotals[2]->amount - ); - $this->assertEquals("fee-rounding-compensation", $movedToAvailable->subtotals[2]->prepaymentPartType); - - // etc. - - $this->assertLinkObject( - "https://docs.mollie.com/reference/v2/balances-api/get-balance-report", - "text/html", - $report->_links->documentation - ); - - $this->assertLinkObject( - "https://api.mollie.com/v2/balances/bal_gVMhHKqSSRYJyPsuoPNFH/report?from=2021-01-01&until=2021-02-01&grouping=transaction-categories", - "application/hal+json", - $report->_links->self - ); - } -} diff --git a/tests/Mollie/API/Endpoints/BalanceTransactionEndpointTest.php b/tests/Mollie/API/Endpoints/BalanceTransactionEndpointTest.php deleted file mode 100644 index 55237ae85..000000000 --- a/tests/Mollie/API/Endpoints/BalanceTransactionEndpointTest.php +++ /dev/null @@ -1,380 +0,0 @@ -mockApiCall( - new Request("GET", "/v2/balances/bal_gVMhHKqSSRYJyPsuoPNFH/transactions"), - new Response( - 200, - [], - '{ - "count": 2, - "_embedded": { - "balance_transactions": [ - { - "resource": "balance_transaction", - "id": "baltr_QM24QwzUWR4ev4Xfgyt29A", - "type": "refund", - "resultAmount": { - "value": "-10.25", - "currency": "EUR" - }, - "initialAmount": { - "value": "-10.00", - "currency": "EUR" - }, - "deductions": { - "value": "-0.25", - "currency": "EUR" - }, - "createdAt": "2021-01-10T12:06:28+00:00", - "context": { - "paymentId": "tr_7UhSN1zuXS", - "refundId": "re_4qqhO89gsT" - } - }, - { - "resource": "balance_transaction", - "id": "baltr_QM24QwzUWR4ev4Xfgyt29B", - "type": "payment", - "resultAmount": { - "value": "9.71", - "currency": "EUR" - }, - "initialAmount": { - "value": "10.00", - "currency": "EUR" - }, - "deductions": { - "value": "-0.29", - "currency": "EUR" - }, - "createdAt": "2021-01-10T12:06:28+00:00", - "context": { - "paymentId": "tr_7UhSN1zuXS" - } - } - ] - }, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/balances-api/list-balance-transactions", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.com/v2/balances/bal_gVMhHKqSSRYJyPsuoPNFH/transactions?limit=5", - "type": "application/hal+json" - }, - "previous": null, - "next": null - } - }' - ) - ); - - $balance = new Balance($this->apiClient); - $balance->id = "bal_gVMhHKqSSRYJyPsuoPNFH"; - - $transactions = $this->apiClient->balanceTransactions->listFor($balance); - - $this->assertTransactions($transactions); - } - - public function testIteratorForBalanceTransactionsThroughEndpoint() - { - $this->mockApiCall( - new Request("GET", "/v2/balances/bal_gVMhHKqSSRYJyPsuoPNFH/transactions"), - new Response( - 200, - [], - '{ - "count": 2, - "_embedded": { - "balance_transactions": [ - { - "resource": "balance_transaction", - "id": "baltr_QM24QwzUWR4ev4Xfgyt29A", - "type": "refund", - "resultAmount": { - "value": "-10.25", - "currency": "EUR" - }, - "initialAmount": { - "value": "-10.00", - "currency": "EUR" - }, - "deductions": { - "value": "-0.25", - "currency": "EUR" - }, - "createdAt": "2021-01-10T12:06:28+00:00", - "context": { - "paymentId": "tr_7UhSN1zuXS", - "refundId": "re_4qqhO89gsT" - } - }, - { - "resource": "balance_transaction", - "id": "baltr_QM24QwzUWR4ev4Xfgyt29B", - "type": "payment", - "resultAmount": { - "value": "9.71", - "currency": "EUR" - }, - "initialAmount": { - "value": "10.00", - "currency": "EUR" - }, - "deductions": { - "value": "-0.29", - "currency": "EUR" - }, - "createdAt": "2021-01-10T12:06:28+00:00", - "context": { - "paymentId": "tr_7UhSN1zuXS" - } - } - ] - }, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/balances-api/list-balance-transactions", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.com/v2/balances/bal_gVMhHKqSSRYJyPsuoPNFH/transactions?limit=5", - "type": "application/hal+json" - }, - "previous": null, - "next": null - } - }' - ) - ); - - $balance = new Balance($this->apiClient); - $balance->id = "bal_gVMhHKqSSRYJyPsuoPNFH"; - - foreach ($this->apiClient->balanceTransactions->iteratorFor($balance) as $balanceTransactions) { - $this->assertInstanceOf(BalanceTransaction::class, $balanceTransactions); - } - } - - public function testGetPrimaryBalanceTransactionsThroughBalanceTransactionEndpoint() - { - $this->mockApiCall( - new Request("GET", "/v2/balances/primary/transactions"), - new Response( - 200, - [], - '{ - "count": 2, - "_embedded": { - "balance_transactions": [ - { - "resource": "balance_transaction", - "id": "baltr_QM24QwzUWR4ev4Xfgyt29A", - "type": "refund", - "resultAmount": { - "value": "-10.25", - "currency": "EUR" - }, - "initialAmount": { - "value": "-10.00", - "currency": "EUR" - }, - "deductions": { - "value": "-0.25", - "currency": "EUR" - }, - "createdAt": "2021-01-10T12:06:28+00:00", - "context": { - "paymentId": "tr_7UhSN1zuXS", - "refundId": "re_4qqhO89gsT" - } - }, - { - "resource": "balance_transaction", - "id": "baltr_QM24QwzUWR4ev4Xfgyt29B", - "type": "payment", - "resultAmount": { - "value": "9.71", - "currency": "EUR" - }, - "initialAmount": { - "value": "10.00", - "currency": "EUR" - }, - "deductions": { - "value": "-0.29", - "currency": "EUR" - }, - "createdAt": "2021-01-10T12:06:28+00:00", - "context": { - "paymentId": "tr_7UhSN1zuXS" - } - } - ] - }, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/balances-api/list-balance-transactions", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.com/v2/balances/bal_gVMhHKqSSRYJyPsuoPNFH/transactions?limit=5", - "type": "application/hal+json" - }, - "previous": null, - "next": null - } - }' - ) - ); - - $transactions = $this->apiClient->balanceTransactions->listForPrimary(); - - $this->assertTransactions($transactions); - } - - public function testIteratorForPrimaryBalanceTransactionsThroughBalanceTransactionEndpoint() - { - $this->mockApiCall( - new Request("GET", "/v2/balances/primary/transactions"), - new Response( - 200, - [], - '{ - "count": 2, - "_embedded": { - "balance_transactions": [ - { - "resource": "balance_transaction", - "id": "baltr_QM24QwzUWR4ev4Xfgyt29A", - "type": "refund", - "resultAmount": { - "value": "-10.25", - "currency": "EUR" - }, - "initialAmount": { - "value": "-10.00", - "currency": "EUR" - }, - "deductions": { - "value": "-0.25", - "currency": "EUR" - }, - "createdAt": "2021-01-10T12:06:28+00:00", - "context": { - "paymentId": "tr_7UhSN1zuXS", - "refundId": "re_4qqhO89gsT" - } - }, - { - "resource": "balance_transaction", - "id": "baltr_QM24QwzUWR4ev4Xfgyt29B", - "type": "payment", - "resultAmount": { - "value": "9.71", - "currency": "EUR" - }, - "initialAmount": { - "value": "10.00", - "currency": "EUR" - }, - "deductions": { - "value": "-0.29", - "currency": "EUR" - }, - "createdAt": "2021-01-10T12:06:28+00:00", - "context": { - "paymentId": "tr_7UhSN1zuXS" - } - } - ] - }, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/balances-api/list-balance-transactions", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.com/v2/balances/bal_gVMhHKqSSRYJyPsuoPNFH/transactions?limit=5", - "type": "application/hal+json" - }, - "previous": null, - "next": null - } - }' - ) - ); - - foreach ($this->apiClient->balanceTransactions->iteratorForPrimary() as $balanceTransactions) { - $this->assertInstanceOf(BalanceTransaction::class, $balanceTransactions); - } - } - - private function assertTransactions(BaseCollection $transactions) - { - $this->assertInstanceOf(BalanceTransactionCollection::class, $transactions); - $this->assertCount(2, $transactions); - $this->assertEquals(2, $transactions->count); - $this->assertLinkObject( - "https://api.mollie.com/v2/balances/bal_gVMhHKqSSRYJyPsuoPNFH/transactions?limit=5", - "application/hal+json", - $transactions->_links->self - ); - $this->assertLinkObject( - "https://docs.mollie.com/reference/v2/balances-api/list-balance-transactions", - "text/html", - $transactions->_links->documentation - ); - $this->assertNull($transactions->_links->next); - $this->assertNull($transactions->_links->previous); - - /** @var \Mollie\Api\Resources\BalanceTransaction $transactionA */ - $transactionA = $transactions[0]; - - /** @var \Mollie\Api\Resources\BalanceTransaction $transactionB */ - $transactionB = $transactions[1]; - - // Transaction A - $this->assertEquals("balance_transaction", $transactionA->resource); - $this->assertEquals("baltr_QM24QwzUWR4ev4Xfgyt29A", $transactionA->id); - $this->assertEquals("refund", $transactionA->type); - $this->assertAmountObject("-10.25", "EUR", $transactionA->resultAmount); - $this->assertAmountObject("-10.00", "EUR", $transactionA->initialAmount); - $this->assertAmountObject("-0.25", "EUR", $transactionA->deductions); - $this->assertEquals("2021-01-10T12:06:28+00:00", $transactionA->createdAt); - $this->assertEquals("tr_7UhSN1zuXS", $transactionA->context->paymentId); - $this->assertEquals("re_4qqhO89gsT", $transactionA->context->refundId); - - // Transaction B - $this->assertEquals("balance_transaction", $transactionB->resource); - $this->assertEquals("baltr_QM24QwzUWR4ev4Xfgyt29B", $transactionB->id); - $this->assertEquals("payment", $transactionB->type); - $this->assertAmountObject("9.71", "EUR", $transactionB->resultAmount); - $this->assertAmountObject("10.00", "EUR", $transactionB->initialAmount); - $this->assertAmountObject("-0.29", "EUR", $transactionB->deductions); - $this->assertEquals("2021-01-10T12:06:28+00:00", $transactionB->createdAt); - $this->assertEquals("tr_7UhSN1zuXS", $transactionB->context->paymentId); - } -} diff --git a/tests/Mollie/API/Endpoints/BaseEndpointTest.php b/tests/Mollie/API/Endpoints/BaseEndpointTest.php deleted file mode 100644 index cb8a02e42..000000000 --- a/tests/Mollie/API/Endpoints/BaseEndpointTest.php +++ /dev/null @@ -1,77 +0,0 @@ -guzzleClient = $this->createMock(Client::class); - - $this->apiClient = new MollieApiClient($this->guzzleClient); - - if (! $oAuthClient) { - $this->apiClient->setApiKey("test_dHar4XY7LxsDOtmnkVtjNVWXLSlXsM"); - } else { - $this->apiClient->setAccessToken("access_Wwvu7egPcJLLJ9Kb7J632x8wJ2zMeJ"); - } - - $this->guzzleClient - ->expects($this->once()) - ->method('send') - ->with($this->isInstanceOf(Request::class)) - ->willReturnCallback(function (Request $request) use ($expectedRequest, $response) { - $this->assertEquals($expectedRequest->getMethod(), $request->getMethod(), "HTTP method must be identical"); - - $this->assertEquals( - $expectedRequest->getUri()->getPath(), - $request->getUri()->getPath(), - "URI path must be identical" - ); - - $this->assertEquals( - $expectedRequest->getUri()->getQuery(), - $request->getUri()->getQuery(), - 'Query string parameters must be identical' - ); - - $requestBody = $request->getBody()->getContents(); - $expectedBody = $expectedRequest->getBody()->getContents(); - - if (strlen($expectedBody) > 0 && strlen($requestBody) > 0) { - $this->assertJsonStringEqualsJsonString( - $expectedBody, - $requestBody, - "HTTP body must be identical" - ); - } - - return $response; - }); - } - - protected function copy($array, $object) - { - foreach ($array as $property => $value) { - $object->$property = $value; - } - - return $object; - } -} diff --git a/tests/Mollie/API/Endpoints/ChargebackEndpointTest.php b/tests/Mollie/API/Endpoints/ChargebackEndpointTest.php deleted file mode 100644 index 44fb3b568..000000000 --- a/tests/Mollie/API/Endpoints/ChargebackEndpointTest.php +++ /dev/null @@ -1,283 +0,0 @@ -mockApiCall( - new Request( - "GET", - "/v2/chargebacks" - ), - new Response( - 200, - [], - '{ - "_embedded":{ - "chargebacks":[ - { - "resource":"chargeback", - "id":"chb_n9z0tp", - "amount":{ - "value":"-13.00", - "currency":"EUR" - }, - "createdAt":"2018-03-28T11:44:32+00:00", - "paymentId":"tr_44aKxzEbr8", - "settlementAmount":{ - "value":"-13.00", - "currency":"EUR" - }, - "reversedAt": null, - "reason":{ - "code":"AC01", - "description":"" - }, - "_links":{ - "self":{ - "href":"https://api.mollie.com/v2/payments/tr_44aKxzEbr8/chargebacks/chb_n9z0tp", - "type":"application/hal+json" - }, - "payment":{ - "href":"https://api.mollie.com/v2/payments/tr_44aKxzEbr8", - "type":"application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/chargebacks-api/get-chargeback", - "type": "text/html" - } - } - }, - { - "resource":"chargeback", - "id":"chb_6cqlwf", - "amount":{ - "value":"-0.37", - "currency":"EUR" - }, - "createdAt":"2018-03-28T11:44:32+00:00", - "paymentId":"tr_nQKWJbDj7j", - "settlementAmount":{ - "value":"-0.37", - "currency":"EUR" - }, - "reversedAt": null, - "reason": null, - "_links":{ - "self":{ - "href":"https://api.mollie.com/v2/payments/tr_nQKWJbDj7j/chargebacks/chb_6cqlwf", - "type":"application/hal+json" - }, - "payment":{ - "href":"https://api.mollie.com/v2/payments/tr_nQKWJbDj7j", - "type":"application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/chargebacks-api/get-chargeback", - "type": "text/html" - } - } - } - ] - }, - "_links":{ - "documentation":{ - "href":"https://docs.mollie.com/reference/v2/chargebacks-api/list-chargebacks", - "type":"text/html" - }, - "self":{ - "href":"https://api.mollie.com/v2/chargebacks", - "type":"application/hal+json" - } - }, - "count": 2 - }' - ) - ); - - $chargebacks = $this->apiClient->chargebacks->page(); - - $this->assertInstanceOf(ChargebackCollection::class, $chargebacks); - $this->assertEquals(2, $chargebacks->count); - $this->assertCount(2, $chargebacks); - - $this->assertLinkObject( - "https://docs.mollie.com/reference/v2/chargebacks-api/list-chargebacks", - "text/html", - $chargebacks->_links->documentation - ); - - $this->assertLinkObject( - "https://api.mollie.com/v2/chargebacks", - "application/hal+json", - $chargebacks->_links->self - ); - - $this->assertChargeback($chargebacks[0], 'tr_44aKxzEbr8', 'chb_n9z0tp', "-13.00", "AC01"); - $this->assertChargeback($chargebacks[1], 'tr_nQKWJbDj7j', 'chb_6cqlwf', "-0.37", null); - } - - public function testIterateChargebacks() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/chargebacks" - ), - new Response( - 200, - [], - '{ - "_embedded":{ - "chargebacks":[ - { - "resource":"chargeback", - "id":"chb_n9z0tp", - "amount":{ - "value":"-13.00", - "currency":"EUR" - }, - "createdAt":"2018-03-28T11:44:32+00:00", - "paymentId":"tr_44aKxzEbr8", - "settlementAmount":{ - "value":"-13.00", - "currency":"EUR" - }, - "reversedAt": null, - "reason":{ - "code":"AC01", - "description":"" - }, - "_links":{ - "self":{ - "href":"https://api.mollie.com/v2/payments/tr_44aKxzEbr8/chargebacks/chb_n9z0tp", - "type":"application/hal+json" - }, - "payment":{ - "href":"https://api.mollie.com/v2/payments/tr_44aKxzEbr8", - "type":"application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/chargebacks-api/get-chargeback", - "type": "text/html" - } - } - }, - { - "resource":"chargeback", - "id":"chb_6cqlwf", - "amount":{ - "value":"-0.37", - "currency":"EUR" - }, - "createdAt":"2018-03-28T11:44:32+00:00", - "paymentId":"tr_nQKWJbDj7j", - "settlementAmount":{ - "value":"-0.37", - "currency":"EUR" - }, - "reversedAt": null, - "reason": null, - "_links":{ - "self":{ - "href":"https://api.mollie.com/v2/payments/tr_nQKWJbDj7j/chargebacks/chb_6cqlwf", - "type":"application/hal+json" - }, - "payment":{ - "href":"https://api.mollie.com/v2/payments/tr_nQKWJbDj7j", - "type":"application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/chargebacks-api/get-chargeback", - "type": "text/html" - } - } - } - ] - }, - "_links":{ - "documentation":{ - "href":"https://docs.mollie.com/reference/v2/chargebacks-api/list-chargebacks", - "type":"text/html" - }, - "self":{ - "href":"https://api.mollie.com/v2/chargebacks", - "type":"application/hal+json" - } - }, - "count": 2 - }' - ) - ); - - foreach ($this->apiClient->chargebacks->iterator() as $chargeback) { - $this->assertInstanceOf(Chargeback::class, $chargeback); - } - } - - protected function assertChargeback($chargeback, $paymentId, $chargebackId, $amount, $reasonCode) - { - $this->assertInstanceOf(Chargeback::class, $chargeback); - $this->assertEquals("chargeback", $chargeback->resource); - $this->assertEquals($chargebackId, $chargeback->id); - - $this->assertAmountObject($amount, "EUR", $chargeback->amount); - $this->assertAmountObject($amount, "EUR", $chargeback->settlementAmount); - - $this->assertEquals("2018-03-28T11:44:32+00:00", $chargeback->createdAt); - $this->assertEquals($paymentId, $chargeback->paymentId); - $this->assertNull($chargeback->reversedAt); - - if ($reasonCode === null) { - $this->assertNull($chargeback->reason); - } else { - $this->assertReasonObject($reasonCode, "", $chargeback->reason); - } - - $this->assertLinkObject( - "https://api.mollie.com/v2/payments/{$paymentId}/chargebacks/{$chargebackId}", - "application/hal+json", - $chargeback->_links->self - ); - - $this->assertLinkObject( - "https://api.mollie.com/v2/payments/{$paymentId}", - "application/hal+json", - $chargeback->_links->payment - ); - - $this->assertLinkObject( - "https://docs.mollie.com/reference/v2/chargebacks-api/get-chargeback", - "text/html", - $chargeback->_links->documentation - ); - } - - protected function assertReasonObject($code, $description, $reasonObject) - { - $this->assertEquals( - $this->createReasonObject($code, $description), - $reasonObject - ); - } - - protected function createReasonObject($code, $description) - { - return (object) [ - 'code' => $code, - 'description' => $description, - ]; - } -} diff --git a/tests/Mollie/API/Endpoints/ClientEndpointTest.php b/tests/Mollie/API/Endpoints/ClientEndpointTest.php deleted file mode 100644 index bd0781f84..000000000 --- a/tests/Mollie/API/Endpoints/ClientEndpointTest.php +++ /dev/null @@ -1,166 +0,0 @@ -mockApiCall( - new Request("GET", "/v2/clients/org_1337"), - new Response( - 200, - [], - '{ - "resource": "client", - "id": "org_1337", - "organizationCreatedAt": "2018-03-21T13:13:37+00:00", - "commission": { - "count": 200, - "totalAmount": { - "currency": "EUR", - "value": "10.00" - } - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/clients/org_1337", - "type": "application/hal+json" - }, - "organization": { - "href": "https://api.mollie.com/v2/organizations/org_1337", - "type": "application/hal+json" - }, - "onboarding": { - "href": "https://api.mollie.com/v2/onboarding/org_1337", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/clients-api/get-client", - "type": "text/html" - } - } - }' - ) - ); - - $client = $this->apiClient->clients->get('org_1337'); - - $this->assertClient($client); - } - - public function testGetClientsPage() - { - $this->mockApiCall( - new Request("GET", "/v2/clients", [], ''), - new Response( - 200, - [], - '{ - "count":1, - "_embedded":{ - "clients":[ - { - "resource":"client", - "id":"org_1337", - "organizationCreatedAt":"2018-03-21T13:13:37+00:00", - "commission":{ - "count":200, - "totalAmount":{ - "currency":"EUR", - "value":"10.00" - } - }, - "_links":{ - "self":{ - "href":"https://api.mollie.com/v2/clients/org_1337", - "type":"application/hal+json" - }, - "organization":{ - "href":"https://api.mollie.com/v2/organizations/org_1337", - "type":"application/hal+json" - }, - "onboarding":{ - "href":"https://api.mollie.com/v2/onboarding/org_1337", - "type":"application/hal+json" - }, - "documentation":{ - "href":"https://docs.mollie.com/reference/v2/clients-api/get-client", - "type":"text/html" - } - } - } - ] - }, - "_links":{ - "self":{ - "href":"https://api.mollie.com/v2/clients?limit=3", - "type":"application/hal+json" - }, - "previous":null, - "next":{ - "href":"https://api.mollie.com/v2/clients?from=org_1379&limit=3", - "type":"application/hal+json" - }, - "documentation":{ - "href":"https://docs.mollie.com/reference/v2/clients-api/list-clients", - "type":"text/html" - } - } - }' - ) - ); - - $clients = $this->apiClient->clients->page(); - - $this->assertInstanceOf(ClientCollection::class, $clients); - $this->assertEquals(1, $clients->count); - $this->assertCount(1, $clients); - - $client = $clients[0]; - $this->assertClient($client); - } - - protected function assertClient($client) - { - $this->assertInstanceOf(Client::class, $client); - - $this->assertEquals('org_1337', $client->id); - $this->assertEquals('200', $client->commission->count); - $this->assertEquals('EUR', $client->commission->totalAmount->currency); - $this->assertEquals('10.00', $client->commission->totalAmount->value); - $this->assertEquals('2018-03-21T13:13:37+00:00', $client->organizationCreatedAt); - - $this->assertLinkObject( - 'https://api.mollie.com/v2/clients/org_1337', - 'application/hal+json', - $client->_links->self - ); - - $this->assertLinkObject( - 'https://api.mollie.com/v2/organizations/org_1337', - 'application/hal+json', - $client->_links->organization - ); - - $this->assertLinkObject( - 'https://api.mollie.com/v2/onboarding/org_1337', - 'application/hal+json', - $client->_links->onboarding - ); - - $this->assertLinkObject( - 'https://docs.mollie.com/reference/v2/clients-api/get-client', - 'text/html', - $client->_links->documentation - ); - } -} diff --git a/tests/Mollie/API/Endpoints/ClientLinkEndpointTest.php b/tests/Mollie/API/Endpoints/ClientLinkEndpointTest.php deleted file mode 100644 index e32c41663..000000000 --- a/tests/Mollie/API/Endpoints/ClientLinkEndpointTest.php +++ /dev/null @@ -1,126 +0,0 @@ -mockApiCall( - new Request( - "POST", - "/v2/client-links", - [], - '{ - "owner": { - "email": "foo@test.com", - "givenName": "foo", - "familyName": "bar", - "locale": "nl_NL" - }, - "name": "Foo Company", - "address": { - "streetAndNumber": "Keizersgracht 313", - "postalCode": "1016 EE", - "city": "Amsterdam", - "country": "nl" - }, - "registrationNumber": "30204462", - "vatNumber": "NL123456789B01" - }' - ), - new Response( - 201, - [], - $this->getClientLinkResponseFixture($client_link_id) - ) - ); - - $clientLink = $this->apiClient->clientLinks->create([ - "owner" => [ - "email" => "foo@test.com", - "givenName" => "foo", - "familyName" => "bar", - "locale" => "nl_NL", - ], - "name" => "Foo Company", - "address" => [ - "streetAndNumber" => "Keizersgracht 313", - "postalCode" => "1016 EE", - "city" => "Amsterdam", - "country" => "nl", - ], - "registrationNumber" => "30204462", - "vatNumber" => "NL123456789B01", - ]); - - $this->assertEquals($clientLink->id, $client_link_id); - $this->assertLinkObject("https://my.mollie.com/dashboard/client-link/finalize/{$client_link_id}", "text/html", $clientLink->_links->clientLink); - $this->assertLinkObject("https://docs.mollie.com/reference/v2/clients-api/create-client-link", "text/html", $clientLink->_links->documentation); - - $redirectLink = $clientLink->getRedirectUrl($app_id, $state, $scopes, $approval_prompt); - $this->assertEquals("https://my.mollie.com/dashboard/client-link/finalize/{$client_link_id}?{$expected_url_query}", $redirectLink); - } - - protected function getClientLinkResponseFixture(string $client_link_id) - { - return str_replace( - [ - "<>", - ], - [ - $client_link_id, - ], - '{ - "id": "<>", - "resource": "client-link", - "_links": { - "clientLink": { - "href": "https://my.mollie.com/dashboard/client-link/finalize/<>", - "type": "text/html" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/clients-api/create-client-link", - "type": "text/html" - } - } - }' - ); - } - - public function clientCreateData(): array - { - return [ - [ - 'cl_vZCnNQsV2UtfXxYifWKWH', - 'app_j9Pakf56Ajta6Y65AkdTtAv', - 'decafbad', - [ - 'onboarding.read', - 'onboarding.write', - ], - 'force', - 'client_id=app_j9Pakf56Ajta6Y65AkdTtAv&state=decafbad&approval_prompt=force&scope=onboarding.read%20onboarding.write', - ], - [ - 'cl_vZCnNQsV2UtfXxYifWKWG', - 'app_j9Pakf56Ajta6Y65AkdTtAw', - 'decafbad', - [ - 'onboarding.read', - ], - 'auto', - 'client_id=app_j9Pakf56Ajta6Y65AkdTtAw&state=decafbad&approval_prompt=auto&scope=onboarding.read', - ], - ]; - } -} diff --git a/tests/Mollie/API/Endpoints/CustomerEndpointTest.php b/tests/Mollie/API/Endpoints/CustomerEndpointTest.php deleted file mode 100644 index 20e939ba0..000000000 --- a/tests/Mollie/API/Endpoints/CustomerEndpointTest.php +++ /dev/null @@ -1,276 +0,0 @@ -mockApiCall( - new Request('POST', '/v2/customers'), - new Response( - 200, - [], - '{ - "resource": "customer", - "id": "cst_FhQJRw4s2n", - "mode": "test", - "name": "John Doe", - "email": "johndoe@example.org", - "locale": null, - "metadata": null, - "recentlyUsedMethods": [], - "createdAt": "2018-04-19T08:49:01+00:00", - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/customers-api/create-customer", - "type": "text/html" - } - } - }' - ) - ); - - /** @var Customer $customer */ - $customer = $this->apiClient->customers->create([ - "name" => "John Doe", - "email" => "johndoe@example.org", - ]); - - $this->assertInstanceOf(Customer::class, $customer); - $this->assertEquals("customer", $customer->resource); - $this->assertEquals("cst_FhQJRw4s2n", $customer->id); - $this->assertEquals("John Doe", $customer->name); - $this->assertEquals("johndoe@example.org", $customer->email); - $this->assertNull($customer->locale); - $this->assertNull($customer->metadata); - $this->assertEquals([], $customer->recentlyUsedMethods); - $this->assertEquals("2018-04-19T08:49:01+00:00", $customer->createdAt); - - $documentationLink = (object)["href" => "https://docs.mollie.com/reference/v2/customers-api/create-customer", "type" => "text/html"]; - $this->assertEquals($documentationLink, $customer->_links->documentation); - } - - public function testGetWorks() - { - $this->mockApiCall( - new Request('GET', '/v2/customers/cst_FhQJRw4s2n'), - new Response( - 200, - [], - '{ - "resource": "customer", - "id": "cst_FhQJRw4s2n", - "mode": "test", - "name": "John Doe", - "email": "johndoe@example.org", - "locale": null, - "metadata": null, - "recentlyUsedMethods": [], - "createdAt": "2018-04-19T08:49:01+00:00", - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/customers-api/get-customer", - "type": "text/html" - } - } - }' - ) - ); - - /** @var Customer $customer */ - $customer = $this->apiClient->customers->get("cst_FhQJRw4s2n"); - - $this->assertInstanceOf(Customer::class, $customer); - $this->assertEquals("customer", $customer->resource); - $this->assertEquals("cst_FhQJRw4s2n", $customer->id); - $this->assertEquals("John Doe", $customer->name); - $this->assertEquals("johndoe@example.org", $customer->email); - $this->assertNull($customer->locale); - $this->assertNull($customer->metadata); - $this->assertEquals([], $customer->recentlyUsedMethods); - $this->assertEquals("2018-04-19T08:49:01+00:00", $customer->createdAt); - - $documentationLink = (object)["href" => "https://docs.mollie.com/reference/v2/customers-api/get-customer", "type" => "text/html"]; - $this->assertEquals($documentationLink, $customer->_links->documentation); - } - - public function testListWorks() - { - $this->mockApiCall( - new Request('GET', '/v2/customers'), - new Response( - 200, - [], - '{ - "_embedded": { - "customers": [ - { - "resource": "customer", - "id": "cst_FhQJRw4s2n", - "mode": "test", - "name": "John Doe", - "email": "johndoe@example.org", - "locale": null, - "metadata": null, - "recentlyUsedMethods": [], - "createdAt": "2018-04-19T08:49:01+00:00" - } - ] - }, - "count": 1, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/customers-api/list-customers", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.com/v2/customers?limit=50", - "type": "application/hal+json" - }, - "previous": null, - "next": null - } - }' - ) - ); - - $customers = $this->apiClient->customers->page(); - - $this->assertInstanceOf(CustomerCollection::class, $customers); - - $documentationLink = (object)["href" => "https://docs.mollie.com/reference/v2/customers-api/list-customers", "type" => "text/html"]; - $this->assertEquals($documentationLink, $customers->_links->documentation); - - $selfLink = (object)["href" => "https://api.mollie.com/v2/customers?limit=50", "type" => "application/hal+json"]; - $this->assertEquals($selfLink, $customers->_links->self); - - foreach ($customers as $customer) { - $this->assertInstanceOf(Customer::class, $customer); - $this->assertEquals("customer", $customer->resource); - $this->assertNotEmpty($customer->createdAt); - } - } - - public function testIteratorWorks() - { - $this->mockApiCall( - new Request('GET', '/v2/customers'), - new Response( - 200, - [], - '{ - "_embedded": { - "customers": [ - { - "resource": "customer", - "id": "cst_FhQJRw4s2n", - "mode": "test", - "name": "John Doe", - "email": "johndoe@example.org", - "locale": null, - "metadata": null, - "recentlyUsedMethods": [], - "createdAt": "2018-04-19T08:49:01+00:00" - } - ] - }, - "count": 1, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/customers-api/list-customers", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.com/v2/customers?limit=50", - "type": "application/hal+json" - }, - "previous": null, - "next": null - } - }' - ) - ); - - foreach ($this->apiClient->customers->iterator() as $customer) { - $this->assertInstanceOf(Customer::class, $customer); - $this->assertEquals("customer", $customer->resource); - $this->assertNotEmpty($customer->createdAt); - } - } - - public function testUpdateWorks() - { - $expectedName = 'Kaas Broodje'; - $expectedEmail = 'kaas.broodje@gmail.com'; - - $this->mockApiCall( - new Request('PATCH', '/v2/customers/cst_FhQJRw4s2n'), - new Response( - 200, - [], - '{ - "resource": "customer", - "id": "cst_FhQJRw4s2n", - "mode": "test", - "name": "' . $expectedName . '", - "email": "' . $expectedEmail . '", - "locale": null, - "metadata": null, - "recentlyUsedMethods": [], - "createdAt": "2018-04-19T08:49:01+00:00", - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/customers-api/get-customer", - "type": "text/html" - } - } - }' - ) - ); - - $customer = $this->getCustomer(); - $customer->name = $expectedName; - $customer->email = $expectedEmail; - - $updatedCustomer = $customer->update(); - - $this->assertEquals($expectedName, $updatedCustomer->name); - $this->assertEquals($expectedEmail, $updatedCustomer->email); - } - - /** - * @return Customer - */ - private function getCustomer() - { - $customerJson = '{ - "resource": "customer", - "id": "cst_FhQJRw4s2n", - "mode": "test", - "name": "John Doe", - "email": "johndoe@example.org", - "locale": null, - "metadata": null, - "recentlyUsedMethods": [], - "createdAt": "2018-04-19T08:49:01+00:00", - "_links": { - "self": { - "href": "http://api.mollie.test/v2/customers/cst_FhQJRw4s2n", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/customers-api/get-customer", - "type": "text/html" - } - } - }'; - - return $this->copy(json_decode($customerJson), new Customer($this->apiClient)); - } -} diff --git a/tests/Mollie/API/Endpoints/CustomerPaymentEndpointTest.php b/tests/Mollie/API/Endpoints/CustomerPaymentEndpointTest.php deleted file mode 100644 index 2de0d4b7b..000000000 --- a/tests/Mollie/API/Endpoints/CustomerPaymentEndpointTest.php +++ /dev/null @@ -1,315 +0,0 @@ -mockApiCall( - new Request( - "POST", - "/v2/customers/cst_FhQJRw4s2n/payments", - [], - '{ - "amount":{ - "value":"20.00", - "currency":"EUR" - }, - "description": "My first API payment", - "redirectUrl": "https://example.org/redirect", - "webhookUrl": "https://example.org/webhook", - "metadata": { - "order_id": "1234" - } - }' - ), - new Response( - 201, - [], - '{ - "resource":"payment", - "id":"tr_44aKxzEbr8", - "mode":"test", - "createdAt":"2018-03-13T14:02:29+00:00", - "amount":{ - "value":"20.00", - "currency":"EUR" - }, - "description":"My first API payment", - "method":null, - "metadata":{ - "order_id":"1234" - }, - "status":"open", - "isCancelable":false, - "expiresAt":"2018-03-13T14:17:29+00:00", - "details":null, - "profileId":"pfl_2A1gacu42V", - "sequenceType":"oneoff", - "redirectUrl":"https://example.org/redirect", - "webhookUrl":"https://example.org/webhook", - "_links":{ - "self":{ - "href":"https://api.mollie.com/v2/payments/tr_44aKxzEbr8", - "type":"application/hal+json" - }, - "checkout":{ - "href":"https://www.mollie.com/payscreen/select-method/44aKxzEbr8", - "type":"text/html" - }, - "customer": { - "href": "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n", - "type": "application/hal+json" - }, - "documentation":{ - "href":"https://docs.mollie.com/reference/v2/customers-api/create-payment", - "type":"text/html" - } - } - }' - ) - ); - - /** @var Customer $customer */ - $customer = $this->getCustomer(); - - $payment = $customer->createPayment([ - "amount" => [ - "currency" => "EUR", - "value" => "20.00", - ], - "description" => "My first API payment", - "redirectUrl" => "https://example.org/redirect", - "webhookUrl" => "https://example.org/webhook", - "metadata" => [ - "order_id" => "1234", - ], - ]); - - $this->assertInstanceOf(Payment::class, $payment); - $this->assertEquals('tr_44aKxzEbr8', $payment->id); - $this->assertEquals('test', $payment->mode); - $this->assertEquals("2018-03-13T14:02:29+00:00", $payment->createdAt); - - $amount = new Stdclass(); - $amount->value = '20.00'; - $amount->currency = "EUR"; - $this->assertEquals($amount, $payment->amount); - - $this->assertEquals('My first API payment', $payment->description); - $this->assertNull($payment->method); - $this->assertEquals((object)["order_id" => "1234"], $payment->metadata); - $this->assertEquals(PaymentStatus::STATUS_OPEN, $payment->status); - $this->assertFalse($payment->isCancelable); - $this->assertEquals("2018-03-13T14:17:29+00:00", $payment->expiresAt); - $this->assertNull($payment->details); - $this->assertEquals("pfl_2A1gacu42V", $payment->profileId); - $this->assertEquals(SequenceType::SEQUENCETYPE_ONEOFF, $payment->sequenceType); - $this->assertEquals("https://example.org/redirect", $payment->redirectUrl); - $this->assertEquals("https://example.org/webhook", $payment->webhookUrl); - - $selfLink = (object)["href" => "https://api.mollie.com/v2/payments/tr_44aKxzEbr8", "type" => "application/hal+json"]; - $this->assertEquals($selfLink, $payment->_links->self); - - $checkoutLink = (object)["href" => "https://www.mollie.com/payscreen/select-method/44aKxzEbr8", "type" => "text/html"]; - $this->assertEquals($checkoutLink, $payment->_links->checkout); - - $customerLink = (object)["href" => "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n", "type" => "application/hal+json"]; - $this->assertEquals($customerLink, $payment->_links->customer); - - $documentationLink = (object)["href" => "https://docs.mollie.com/reference/v2/customers-api/create-payment", "type" => "text/html"]; - $this->assertEquals($documentationLink, $payment->_links->documentation); - } - - public function testListCustomerPayments() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/customers/cst_FhQJRw4s2n/payments?testmode=true", - [], - '' - ), - new Response( - 200, - [], - '{ - "_embedded": { - "payments": [ - { - "resource": "payment", - "id": "tr_admNa2tFfa", - "mode": "test", - "createdAt": "2018-03-19T15:00:50+00:00", - "amount": { - "value": "100.00", - "currency": "EUR" - }, - "description": "Payment no 1", - "method": null, - "metadata": null, - "status": "open", - "isCancelable": false, - "expiresAt": "2018-03-19T15:15:50+00:00", - "details": null, - "locale": "nl_NL", - "profileId": "pfl_7N5qjbu42V", - "sequenceType": "oneoff", - "redirectUrl": "https://www.example.org/", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_admNa2tFfa", - "type": "application/hal+json" - }, - "checkout": { - "href": "https://www.mollie.com/payscreen/select-method/admNa2tFfa", - "type": "text/html" - }, - "customer": { - "href": "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n", - "type": "application/hal+json" - } - } - }, - { - "resource": "payment", - "id": "tr_bcaLc7hFfa", - "mode": "test", - "createdAt": "2018-03-19T15:00:50+00:00", - "amount": { - "value": "100.00", - "currency": "EUR" - }, - "description": "Payment no 2", - "method": null, - "metadata": null, - "status": "open", - "isCancelable": false, - "expiresAt": "2018-03-19T15:15:50+00:00", - "details": null, - "locale": "nl_NL", - "profileId": "pfl_7N5qjbu42V", - "sequenceType": "oneoff", - "redirectUrl": "https://www.example.org/", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_bcaLc7hFfa", - "type": "application/hal+json" - }, - "checkout": { - "href": "https://www.mollie.com/payscreen/select-method/bcaLc7hFfa", - "type": "text/html" - }, - "customer": { - "href": "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n", - "type": "application/hal+json" - } - } - }, - { - "resource": "payment", - "id": "tr_pslHy1tFfa", - "mode": "test", - "createdAt": "2018-03-19T15:00:50+00:00", - "amount": { - "value": "100.00", - "currency": "EUR" - }, - "description": "Payment no 3", - "method": null, - "metadata": null, - "status": "open", - "isCancelable": false, - "expiresAt": "2018-03-19T15:15:50+00:00", - "details": null, - "locale": "nl_NL", - "profileId": "pfl_7N5qjbu42V", - "sequenceType": "oneoff", - "redirectUrl": "https://www.example.org/", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_pslHy1tFfa", - "type": "application/hal+json" - }, - "checkout": { - "href": "https://www.mollie.com/payscreen/select-method/pslHy1tFfa", - "type": "text/html" - }, - "customer": { - "href": "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n", - "type": "application/hal+json" - } - } - } - ] - }, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/customers-api/list-customer-payments", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.com/v2/customers/cst_TkNdP8yPrH/payments?limit=50", - "type": "application/hal+json" - }, - "previous": null, - "next": null - }, - "count": 3 - }' - ), - true - ); - - /** @var Customer $customer */ - $customer = $this->getCustomer(); - - $payments = $customer->payments(); - - $this->assertInstanceOf(PaymentCollection::class, $payments); - $this->assertEquals(3, $payments->count); - $this->assertEquals(3, count($payments)); - - $documentationLink = (object)["href" => "https://docs.mollie.com/reference/v2/customers-api/list-customer-payments", "type" => "text/html"]; - $this->assertEquals($documentationLink, $payments->_links->documentation); - - $selfLink = (object)["href" => "https://api.mollie.com/v2/customers/cst_TkNdP8yPrH/payments?limit=50", "type" => "application/hal+json"]; - $this->assertEquals($selfLink, $payments->_links->self); - } - - /** - * @return CustomerPaymentEndpointTest - */ - private function getCustomer() - { - $customerJson = '{ - "resource": "customer", - "id": "cst_FhQJRw4s2n", - "mode": "test", - "name": "John Doe", - "email": "johndoe@example.org", - "locale": null, - "metadata": null, - "recentlyUsedMethods": [], - "createdAt": "2018-04-19T08:49:01+00:00", - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/customers-api/get-customer", - "type": "text/html" - } - } - }'; - - return $this->copy(json_decode($customerJson), new Customer($this->apiClient)); - } -} diff --git a/tests/Mollie/API/Endpoints/CustomerSubscriptionPaymentEndpointTest.php b/tests/Mollie/API/Endpoints/CustomerSubscriptionPaymentEndpointTest.php deleted file mode 100644 index 902044d0f..000000000 --- a/tests/Mollie/API/Endpoints/CustomerSubscriptionPaymentEndpointTest.php +++ /dev/null @@ -1,112 +0,0 @@ -mockApiCall( - new Request('GET', '/v2/customers/cst_8wmqcHMN4U/subscriptions/sub_8JfGzs6v3K/payments?testmode=true'), - new Response( - 200, - [], - '{ - "_embedded": { - "payments": [ - { - "resource": "payment", - "id": "tr_DtKxVP2AgW", - "mode": "test", - "createdAt": "2018-09-19T12:49:52+00:00", - "amount": { - "value": "10.00", - "currency": "EUR" - }, - "description": "Some subscription 19 sep. 2018", - "method": "directdebit", - "metadata": null, - "status": "pending", - "isCancelable": true, - "expiresAt": "2019-09-19T12:49:52+00:00", - "locale": "nl_NL", - "profileId": "pfl_rH9rQtedgS", - "customerId": "cst_8wmqcHMN4U", - "mandateId": "mdt_aGQNkteF6w", - "subscriptionId": "sub_8JfGzs6v3K", - "sequenceType": "recurring", - "redirectUrl": null, - "webhookUrl": "https://example.org/webhook", - "settlementAmount": { - "value": "10.00", - "currency": "EUR" - }, - "details": { - "transferReference": "SD67-6850-2204-6029", - "creditorIdentifier": "NL08ZZZ502057730000", - "consumerName": "Customer A", - "consumerAccount": "NL50INGB0006588912", - "consumerBic": "INGBNL2A", - "dueDate": "2018-09-21", - "signatureDate": "2018-09-19" - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_DtKxVP2AgW?testmode=true", - "type": "application/hal+json" - }, - "checkout": null, - "customer": { - "href": "https://api.mollie.com/v2/customers/cst_8wmqcHMN4U?testmode=true", - "type": "application/hal+json" - }, - "mandate": { - "href": "https://api.mollie.com/v2/customers/cst_8wmqcHMN4U/mandates/mdt_aGQNkteF6w?testmode=true", - "type": "application/hal+json" - }, - "subscription": { - "href": "https://api.mollie.com/v2/customers/cst_8wmqcHMN4U/subscriptions/sub_8JfGzs6v3K?testmode=true", - "type": "application/hal+json" - } - } - } - ] - }, - "count": 1, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/subscriptions-api/list-subscriptions-payments", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.com/v2/customers/cst_8wmqcHMN4U/subscriptions/sub_8JfGzs6v3K/payments?limit=50&testmode=true", - "type": "application/hal+json" - }, - "previous": null, - "next": null - } - }' - ) - ); - - $subscription = new Subscription($this->apiClient); - $subscription->_links = $this->createNamedLinkObject( - 'payments', - '/v2/customers/cst_8wmqcHMN4U/subscriptions/sub_8JfGzs6v3K/payments?testmode=true', - 'application/hal+json' - ); - - $result = $subscription->payments(); - $this->assertInstanceOf(PaymentCollection::class, $result); - $this->assertEquals(1, $result->count); - $this->assertEquals('Some subscription 19 sep. 2018', $result[0]->description); - } -} diff --git a/tests/Mollie/API/Endpoints/InvoiceEndpointTest.php b/tests/Mollie/API/Endpoints/InvoiceEndpointTest.php deleted file mode 100644 index 3e251fd4a..000000000 --- a/tests/Mollie/API/Endpoints/InvoiceEndpointTest.php +++ /dev/null @@ -1,319 +0,0 @@ -mockApiCall( - new Request( - "GET", - "/v2/invoices/inv_bsa6PvAwaK", - [], - '' - ), - new Response( - 200, - [], - '{ - "resource": "invoice", - "id": "inv_bsa6PvAwaK", - "reference": "2018.190241", - "vatNumber": "123456789B01", - "status": "paid", - "issuedAt": "2018-05-02", - "paidAt": "2018-05-02", - "netAmount": { - "value": "100.00", - "currency": "EUR" - }, - "vatAmount": { - "value": "0.00", - "currency": "EUR" - }, - "grossAmount": { - "value": "100.00", - "currency": "EUR" - }, - "lines": [ - { - "period": "2018-04", - "description": "iDEAL transaction costs: april 2018", - "count": 1337, - "vatPercentage": 0, - "amount": { - "value": "50.00", - "currency": "EUR" - } - }, - { - "period": "2018-04", - "description": "Refunds iDEAL: april 2018", - "count": 1337, - "vatPercentage": 0, - "amount": { - "value": "50.00", - "currency": "EUR" - } - } - ], - "_links": { - "self": { - "href": "https://api.mollie.com/v2/invoices/inv_bsa6PvAwaK", - "type": "application/hal+json" - }, - "pdf": { - "href": "https://www.mollie.com/merchant/download/invoice/bsa6PvAwaK/79aa10f49132b7844c0243648ade6985", - "type": "application/pdf" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/invoices-api/get-invoice", - "type": "text/html" - } - } - }' - ) - ); - - $invoice = $this->apiClient->invoices->get("inv_bsa6PvAwaK"); - - $this->assertInstanceOf(Invoice::class, $invoice); - $this->assertEquals("invoice", $invoice->resource); - $this->assertEquals("inv_bsa6PvAwaK", $invoice->id); - $this->assertEquals("2018.190241", $invoice->reference); - $this->assertEquals("123456789B01", $invoice->vatNumber); - $this->assertEquals(InvoiceStatus::STATUS_PAID, $invoice->status); - $this->assertEquals("2018-05-02", $invoice->issuedAt); - $this->assertEquals("2018-05-02", $invoice->paidAt); - - $this->assertEquals((object) ["value" => "100.00", "currency" => "EUR"], $invoice->netAmount); - $this->assertEquals((object) ["value" => "0.00", "currency" => "EUR"], $invoice->vatAmount); - $this->assertEquals((object) ["value" => "100.00", "currency" => "EUR"], $invoice->grossAmount); - - $this->assertCount(2, $invoice->lines); - - $selfLink = (object)['href' => 'https://api.mollie.com/v2/invoices/inv_bsa6PvAwaK', 'type' => 'application/hal+json']; - $this->assertEquals($selfLink, $invoice->_links->self); - - $pdfLink = (object)['href' => 'https://www.mollie.com/merchant/download/invoice/bsa6PvAwaK/79aa10f49132b7844c0243648ade6985', 'type' => 'application/pdf']; - $this->assertEquals($pdfLink, $invoice->_links->pdf); - - $documentationLink = (object)['href' => 'https://docs.mollie.com/reference/v2/invoices-api/get-invoice', 'type' => 'text/html']; - $this->assertEquals($documentationLink, $invoice->_links->documentation); - } - - public function testListInvoices() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/invoices", - [], - '' - ), - new Response( - 200, - [], - '{ - "_embedded": { - "invoices": [ - { - "resource": "invoice", - "id": "inv_bsa6PvAwaK", - "reference": "2018.190241", - "vatNumber": "123456789B01", - "status": "paid", - "issuedAt": "2018-05-02", - "paidAt": "2018-05-02", - "netAmount": { - "value": "100.00", - "currency": "EUR" - }, - "vatAmount": { - "value": "0.00", - "currency": "EUR" - }, - "grossAmount": { - "value": "100.00", - "currency": "EUR" - }, - "lines": [ - { - "period": "2018-04", - "description": "iDEAL transaction costs: april 2018", - "count": 1337, - "vatPercentage": 0, - "amount": { - "value": "50.00", - "currency": "EUR" - } - }, - { - "period": "2018-04", - "description": "Refunds iDEAL: april 2018", - "count": 1337, - "vatPercentage": 0, - "amount": { - "value": "50.00", - "currency": "EUR" - } - } - ], - "_links": { - "self": { - "href": "https://api.mollie.com/v2/invoices/inv_bsa6PvAwaK", - "type": "application/hal+json" - }, - "pdf": { - "href": "https://www.mollie.com/merchant/download/invoice/bsa6PvAwaK/79aa10f49132b7844c0243648ade6985", - "type": "application/pdf" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/invoices-api/get-invoice", - "type": "text/html" - } - } - } - ] - }, - "count": 1, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/invoices-api/list-invoices", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.nl/v2/invoices?limit=50", - "type": "application/hal+json" - }, - "previous": null, - "next": null - } - }' - ) - ); - - $invoices = $this->apiClient->invoices->page(); - $this->assertInstanceOf(InvoiceCollection::class, $invoices); - - $documentationLink = (object)['href' => 'https://docs.mollie.com/reference/v2/invoices-api/list-invoices', 'type' => 'text/html']; - $this->assertEquals($documentationLink, $invoices->_links->documentation); - - $selfLink = (object)['href' => 'https://api.mollie.nl/v2/invoices?limit=50', 'type' => 'application/hal+json']; - $this->assertEquals($selfLink, $invoices->_links->self); - - $this->assertEmpty($invoices->_links->previous); - $this->assertEmpty($invoices->_links->next); - - foreach ($invoices as $invoice) { - $this->assertInstanceOf(Invoice::class, $invoice); - $this->assertEquals("invoice", $invoice->resource); - $this->assertNotEmpty($invoice->lines); - } - } - - public function testIterateInvoices() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/invoices", - [], - '' - ), - new Response( - 200, - [], - '{ - "_embedded": { - "invoices": [ - { - "resource": "invoice", - "id": "inv_bsa6PvAwaK", - "reference": "2018.190241", - "vatNumber": "123456789B01", - "status": "paid", - "issuedAt": "2018-05-02", - "paidAt": "2018-05-02", - "netAmount": { - "value": "100.00", - "currency": "EUR" - }, - "vatAmount": { - "value": "0.00", - "currency": "EUR" - }, - "grossAmount": { - "value": "100.00", - "currency": "EUR" - }, - "lines": [ - { - "period": "2018-04", - "description": "iDEAL transaction costs: april 2018", - "count": 1337, - "vatPercentage": 0, - "amount": { - "value": "50.00", - "currency": "EUR" - } - }, - { - "period": "2018-04", - "description": "Refunds iDEAL: april 2018", - "count": 1337, - "vatPercentage": 0, - "amount": { - "value": "50.00", - "currency": "EUR" - } - } - ], - "_links": { - "self": { - "href": "https://api.mollie.com/v2/invoices/inv_bsa6PvAwaK", - "type": "application/hal+json" - }, - "pdf": { - "href": "https://www.mollie.com/merchant/download/invoice/bsa6PvAwaK/79aa10f49132b7844c0243648ade6985", - "type": "application/pdf" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/invoices-api/get-invoice", - "type": "text/html" - } - } - } - ] - }, - "count": 1, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/invoices-api/list-invoices", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.nl/v2/invoices?limit=50", - "type": "application/hal+json" - }, - "previous": null, - "next": null - } - }' - ) - ); - - foreach ($this->apiClient->invoices->iterator() as $invoice) { - $this->assertInstanceOf(Invoice::class, $invoice); - $this->assertEquals("invoice", $invoice->resource); - $this->assertNotEmpty($invoice->lines); - } - } -} diff --git a/tests/Mollie/API/Endpoints/MandateEndpointTest.php b/tests/Mollie/API/Endpoints/MandateEndpointTest.php deleted file mode 100644 index 9efeb9083..000000000 --- a/tests/Mollie/API/Endpoints/MandateEndpointTest.php +++ /dev/null @@ -1,427 +0,0 @@ -mockApiCall( - new Request('POST', '/v2/customers/cst_FhQJRw4s2n/mandates'), - new Response( - 200, - [], - '{ - "resource": "mandate", - "id": "mdt_AcQl5fdL4h", - "status": "valid", - "method": "directdebit", - "details": { - "consumerName": "John Doe", - "consumerAccount": "NL55INGB0000000000", - "consumerBic": "INGBNL2A" - }, - "mandateReference": null, - "signatureDate": "2018-05-07", - "createdAt": "2018-05-07T10:49:08+00:00", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n/mandates/mdt_AcQl5fdL4h", - "type": "application/hal+json" - }, - "customer": { - "href": "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://mollie.com/en/docs/reference/customers/create-mandate", - "type": "text/html" - } - } - }' - ) - ); - - $customer = $this->getCustomer(); - - /** @var Mandate $mandate */ - $mandate = $customer->createMandate([ - "consumerName" => "John Doe", - "method" => "directdebit", - "consumerBic" => "INGBNL2A", - "consumerAccount" => "NL55INGB0000000000", - ]); - - $this->assertInstanceOf(Mandate::class, $mandate); - $this->assertEquals("mandate", $mandate->resource); - $this->assertEquals(MandateStatus::STATUS_VALID, $mandate->status); - $this->assertEquals("directdebit", $mandate->method); - $this->assertEquals((object) ["consumerName" => "John Doe", "consumerAccount" => "NL55INGB0000000000", "consumerBic" => "INGBNL2A"], $mandate->details); - $this->assertNull($mandate->mandateReference); - $this->assertEquals("2018-05-07", $mandate->signatureDate); - $this->assertEquals("2018-05-07T10:49:08+00:00", $mandate->createdAt); - - $selfLink = (object)["href" => "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n/mandates/mdt_AcQl5fdL4h", "type" => "application/hal+json"]; - $this->assertEquals($selfLink, $mandate->_links->self); - - $customerLink = (object)["href" => "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n", "type" => "application/hal+json"]; - $this->assertEquals($customerLink, $mandate->_links->customer); - - $documentationLink = (object)["href" => "https://mollie.com/en/docs/reference/customers/create-mandate", "type" => "text/html"]; - $this->assertEquals($documentationLink, $mandate->_links->documentation); - } - - public function testGetWorks() - { - $this->mockApiCall( - new Request('GET', '/v2/customers/cst_FhQJRw4s2n/mandates/mdt_AcQl5fdL4h'), - new Response( - 200, - [], - '{ - "resource": "mandate", - "id": "mdt_AcQl5fdL4h", - "status": "valid", - "method": "directdebit", - "details": { - "consumerName": "John Doe", - "consumerAccount": "NL55INGB0000000000", - "consumerBic": "INGBNL2A" - }, - "mandateReference": null, - "signatureDate": "2018-05-07", - "createdAt": "2018-05-07T10:49:08+00:00", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n/mandates/mdt_AcQl5fdL4h", - "type": "application/hal+json" - }, - "customer": { - "href": "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://mollie.com/en/docs/reference/customers/create-mandate", - "type": "text/html" - } - } - }' - ) - ); - - $customer = $this->getCustomer(); - - /** @var Mandate $mandate */ - $mandate = $customer->getMandate("mdt_AcQl5fdL4h"); - - $this->assertInstanceOf(Mandate::class, $mandate); - $this->assertEquals("mandate", $mandate->resource); - $this->assertEquals(MandateStatus::STATUS_VALID, $mandate->status); - $this->assertEquals(MandateMethod::DIRECTDEBIT, $mandate->method); - $this->assertEquals((object) ["consumerName" => "John Doe", "consumerAccount" => "NL55INGB0000000000", "consumerBic" => "INGBNL2A"], $mandate->details); - $this->assertNull($mandate->mandateReference); - $this->assertEquals("2018-05-07", $mandate->signatureDate); - $this->assertEquals("2018-05-07T10:49:08+00:00", $mandate->createdAt); - - $selfLink = (object)["href" => "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n/mandates/mdt_AcQl5fdL4h", "type" => "application/hal+json"]; - $this->assertEquals($selfLink, $mandate->_links->self); - - $customerLink = (object)["href" => "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n", "type" => "application/hal+json"]; - $this->assertEquals($customerLink, $mandate->_links->customer); - - $documentationLink = (object)["href" => "https://mollie.com/en/docs/reference/customers/create-mandate", "type" => "text/html"]; - $this->assertEquals($documentationLink, $mandate->_links->documentation); - } - - public function testListWorks() - { - $this->mockApiCall( - new Request('GET', '/v2/customers/cst_FhQJRw4s2n/mandates'), - new Response( - 200, - [], - '{ - "_embedded": { - "mandates": [ - { - "resource": "mandate", - "id": "mdt_AcQl5fdL4h", - "status": "valid", - "method": "directdebit", - "details": { - "consumerName": "John Doe", - "consumerAccount": "NL55INGB0000000000", - "consumerBic": "INGBNL2A" - }, - "mandateReference": null, - "signatureDate": "2018-05-07", - "createdAt": "2018-05-07T10:49:08+00:00", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n/mandates/mdt_AcQl5fdL4h", - "type": "application/hal+json" - }, - "customer": { - "href": "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n", - "type": "application/hal+json" - } - } - } - ] - }, - "count": 1, - "_links": { - "documentation": { - "href": "https://mollie.com/en/docs/reference/customers/list-mandates", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.com/v2/customers/cst_vzEExMcxj7/mandates?limit=50", - "type": "application/hal+json" - }, - "previous": null, - "next": null - } - }' - ) - ); - - $customer = $this->getCustomer(); - - /** @var MandateCollection $mandates */ - $mandates = $customer->mandates(); - $this->assertInstanceOf(MandateCollection::class, $mandates); - - /** @var Mandate $mandate */ - foreach ($mandates as $mandate) { - $this->assertInstanceOf(Mandate::class, $mandate); - $this->assertEquals("mandate", $mandate->resource); - $this->assertEquals(MandateStatus::STATUS_VALID, $mandate->status); - - $customerLink = (object)["href" => "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n", "type" => "application/hal+json"]; - $this->assertEquals($customerLink, $mandate->_links->customer); - } - - $selfLink = (object)["href" => "https://api.mollie.com/v2/customers/cst_vzEExMcxj7/mandates?limit=50", "type" => "application/hal+json"]; - $this->assertEquals($selfLink, $mandates->_links->self); - - $documentationLink = (object)["href" => "https://mollie.com/en/docs/reference/customers/list-mandates", "type" => "text/html"]; - $this->assertEquals($documentationLink, $mandates->_links->documentation); - } - - public function testCustomerHasValidMandateWhenTrue() - { - $this->mockApiCall( - new Request('GET', '/v2/customers/cst_FhQJRw4s2n/mandates'), - new Response( - 200, - [], - '{ - "_embedded": { - "mandates": [ - { - "resource": "mandate", - "id": "mdt_AcQl5fdL4h", - "status": "valid", - "method": "directdebit", - "details": { - "consumerName": "John Doe", - "consumerAccount": "NL55INGB0000000000", - "consumerBic": "INGBNL2A" - }, - "mandateReference": null, - "signatureDate": "2018-05-07", - "createdAt": "2018-05-07T10:49:08+00:00", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n/mandates/mdt_AcQl5fdL4h", - "type": "application/hal+json" - }, - "customer": { - "href": "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n", - "type": "application/hal+json" - } - } - } - ] - }, - "count": 1, - "_links": { - "documentation": { - "href": "https://mollie.com/en/docs/reference/customers/list-mandates", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.com/v2/customers/cst_vzEExMcxj7/mandates?limit=50", - "type": "application/hal+json" - }, - "previous": null, - "next": null - } - }' - ) - ); - - $customer = $this->getCustomer(); - - $this->assertTrue($customer->hasValidMandate()); - } - - public function testCustomerHasValidMandateWhenFalse() - { - $this->mockApiCall( - new Request('GET', '/v2/customers/cst_FhQJRw4s2n/mandates'), - new Response( - 200, - [], - '{ - "_embedded": { - "mandates": [] - }, - "count": 0, - "_links": { - "documentation": { - "href": "https://mollie.com/en/docs/reference/customers/list-mandates", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.com/v2/customers/cst_vzEExMcxj7/mandates?limit=50", - "type": "application/hal+json" - }, - "previous": null, - "next": null - } - }' - ) - ); - - $customer = $this->getCustomer(); - - $this->assertFalse($customer->hasValidMandate()); - } - - public function testCustomerHasValidMandateForMethodWhenFalse() - { - $this->mockApiCall( - new Request('GET', '/v2/customers/cst_FhQJRw4s2n/mandates'), - new Response( - 200, - [], - '{ - "_embedded": { - "mandates": [] - }, - "count": 0, - "_links": { - "documentation": { - "href": "https://mollie.com/en/docs/reference/customers/list-mandates", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.com/v2/customers/cst_vzEExMcxj7/mandates?limit=50", - "type": "application/hal+json" - }, - "previous": null, - "next": null - } - }' - ) - ); - - $customer = $this->getCustomer(); - - $this->assertFalse($customer->hasValidMandateForMethod('directdebit')); - } - - public function testCustomerHasValidMandateForMethodWhenTrue() - { - $this->mockApiCall( - new Request('GET', '/v2/customers/cst_FhQJRw4s2n/mandates'), - new Response( - 200, - [], - '{ - "_embedded": { - "mandates": [ - { - "resource": "mandate", - "id": "mdt_AcQl5fdL4h", - "status": "valid", - "method": "directdebit", - "details": { - "consumerName": "John Doe", - "consumerAccount": "NL55INGB0000000000", - "consumerBic": "INGBNL2A" - }, - "mandateReference": null, - "signatureDate": "2018-05-07", - "createdAt": "2018-05-07T10:49:08+00:00", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n/mandates/mdt_AcQl5fdL4h", - "type": "application/hal+json" - }, - "customer": { - "href": "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n", - "type": "application/hal+json" - } - } - } - ] - }, - "count": 1, - "_links": { - "documentation": { - "href": "https://mollie.com/en/docs/reference/customers/list-mandates", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.com/v2/customers/cst_vzEExMcxj7/mandates?limit=50", - "type": "application/hal+json" - }, - "previous": null, - "next": null - } - }' - ) - ); - - $customer = $this->getCustomer(); - - $this->assertTrue($customer->hasValidMandateForMethod('directdebit')); - } - - /** - * @return Customer - */ - private function getCustomer() - { - $customerJson = '{ - "resource": "customer", - "id": "cst_FhQJRw4s2n", - "mode": "test", - "name": "John Doe", - "email": "johndoe@example.org", - "locale": null, - "metadata": null, - "recentlyUsedMethods": [], - "createdAt": "2018-04-19T08:49:01+00:00", - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/customers-api/get-customer", - "type": "text/html" - } - } - }'; - - return $this->copy(json_decode($customerJson), new Customer($this->apiClient)); - } -} diff --git a/tests/Mollie/API/Endpoints/MethodEndpointTest.php b/tests/Mollie/API/Endpoints/MethodEndpointTest.php deleted file mode 100644 index b26ab8898..000000000 --- a/tests/Mollie/API/Endpoints/MethodEndpointTest.php +++ /dev/null @@ -1,644 +0,0 @@ -mockApiCall( - new Request('GET', '/v2/methods/ideal'), - new Response( - 200, - [], - '{ - "resource": "method", - "id": "ideal", - "description": "iDEAL", - "minimumAmount": { - "value": "0.01", - "currency": "EUR" - }, - "maximumAmount": { - "value": "50000.00", - "currency": "EUR" - }, - "image": { - "size1x": "https://www.mollie.com/images/payscreen/methods/ideal.png", - "size2x": "https://www.mollie.com/images/payscreen/methods/ideal%402x.png" - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/methods/ideal", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/methods-api/get-method", - "type": "text/html" - } - } - }' - ) - ); - - $idealMethod = $this->apiClient->methods->get('ideal'); - - $this->assertInstanceOf(Method::class, $idealMethod); - $this->assertEquals('ideal', $idealMethod->id); - $this->assertEquals('iDEAL', $idealMethod->description); - $this->assertAmountObject(0.01, 'EUR', $idealMethod->minimumAmount); - $this->assertAmountObject(50000, 'EUR', $idealMethod->maximumAmount); - $this->assertEquals('https://www.mollie.com/images/payscreen/methods/ideal.png', $idealMethod->image->size1x); - $this->assertEquals('https://www.mollie.com/images/payscreen/methods/ideal%402x.png', $idealMethod->image->size2x); - - $this->assertLinkObject( - 'https://api.mollie.com/v2/methods/ideal', - 'application/hal+json', - $idealMethod->_links->self - ); - - $this->assertLinkObject( - 'https://docs.mollie.com/reference/v2/methods-api/get-method', - 'text/html', - $idealMethod->_links->documentation - ); - } - - public function testGetMethodWithIncludeIssuers() - { - $this->mockApiCall( - new Request('GET', '/v2/methods/ideal?include=issuers'), - new Response( - 200, - [], - '{ - "resource": "method", - "id": "ideal", - "description": "iDEAL", - "minimumAmount": { - "value": "0.01", - "currency": "EUR" - }, - "maximumAmount": { - "value": "50000.00", - "currency": "EUR" - }, - "image": { - "size1x": "https://www.mollie.com/images/payscreen/methods/ideal.png", - "size2x": "https://www.mollie.com/images/payscreen/methods/ideal%402x.png" - }, - "issuers": [ - { - "resource": "issuer", - "id": "ideal_TESTNL99", - "name": "TBM Bank", - "method": "ideal", - "image": { - "size1x": "https://www.mollie.com/images/checkout/v2/ideal-issuer-icons/TESTNL99.png", - "size2x": "https://www.mollie.com/images/checkout/v2/ideal-issuer-icons/TESTNL99.png" - } - } - ], - - "_links": { - "self": { - "href": "https://api.mollie.com/v2/methods/ideal", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/methods-api/get-method", - "type": "text/html" - } - } - }' - ) - ); - - $idealMethod = $this->apiClient->methods->get('ideal', ['include' => 'issuers']); - - $this->assertInstanceOf(Method::class, $idealMethod); - $this->assertEquals('ideal', $idealMethod->id); - $this->assertEquals('iDEAL', $idealMethod->description); - $this->assertAmountObject(0.01, 'EUR', $idealMethod->minimumAmount); - $this->assertAmountObject(50000, 'EUR', $idealMethod->maximumAmount); - $this->assertEquals('https://www.mollie.com/images/payscreen/methods/ideal.png', $idealMethod->image->size1x); - $this->assertEquals('https://www.mollie.com/images/payscreen/methods/ideal%402x.png', $idealMethod->image->size2x); - - $issuers = $idealMethod->issuers(); - $this->assertInstanceOf(IssuerCollection::class, $issuers); - $this->assertCount(1, $issuers); - - $testIssuer = $issuers[0]; - - $this->assertInstanceOf(Issuer::class, $testIssuer); - $this->assertEquals('ideal_TESTNL99', $testIssuer->id); - $this->assertEquals('TBM Bank', $testIssuer->name); - $this->assertEquals('ideal', $testIssuer->method); - - $expectedSize1xImageLink = 'https://www.mollie.com/images/checkout/v2/ideal-issuer-icons/TESTNL99.png'; - $this->assertEquals($expectedSize1xImageLink, $testIssuer->image->size1x); - - $expectedSize2xImageLink = 'https://www.mollie.com/images/checkout/v2/ideal-issuer-icons/TESTNL99.png'; - $this->assertEquals($expectedSize2xImageLink, $testIssuer->image->size2x); - - $this->assertLinkObject( - 'https://api.mollie.com/v2/methods/ideal', - 'application/hal+json', - $idealMethod->_links->self - ); - - $this->assertLinkObject( - 'https://docs.mollie.com/reference/v2/methods-api/get-method', - 'text/html', - $idealMethod->_links->documentation - ); - } - - public function testGetMethodWithIncludePricing() - { - $this->mockApiCall( - new Request('GET', '/v2/methods/ideal?include=pricing'), - new Response( - 200, - [], - '{ - "resource": "method", - "id": "ideal", - "description": "iDEAL", - "minimumAmount": { - "value": "0.01", - "currency": "EUR" - }, - "maximumAmount": { - "value": "50000.00", - "currency": "EUR" - }, - "image": { - "size1x": "https://www.mollie.com/external/icons/payment-methods/ideal.png", - "size2x": "https://www.mollie.com/external/icons/payment-methods/ideal%402x.png", - "svg": "https://www.mollie.com/external/icons/payment-methods/ideal.svg" - }, - "pricing": [ - { - "description": "The Netherlands", - "fixed": { - "value": "0.29", - "currency": "EUR" - }, - "variable": "0" - } - ], - "_links": { - "self": { - "href": "https://api.mollie.com/v2/methods/ideal", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/methods-api/get-method", - "type": "text/html" - } - } - }' - ) - ); - - $method = $this->apiClient->methods->get('ideal', ['include' => 'pricing']); - - $this->assertInstanceOf(Method::class, $method); - $this->assertEquals('method', $method->resource); - $this->assertEquals('ideal', $method->id); - $this->assertEquals('iDEAL', $method->description); - $this->assertAmountObject(0.01, 'EUR', $method->minimumAmount); - $this->assertAmountObject(50000, 'EUR', $method->maximumAmount); - $this->assertEquals( - 'https://www.mollie.com/external/icons/payment-methods/ideal.png', - $method->image->size1x - ); - $this->assertEquals( - 'https://www.mollie.com/external/icons/payment-methods/ideal%402x.png', - $method->image->size2x - ); - - $this->assertEquals( - 'https://www.mollie.com/external/icons/payment-methods/ideal.svg', - $method->image->svg - ); - - $this->assertLinkObject( - 'https://api.mollie.com/v2/methods/ideal', - 'application/hal+json', - $method->_links->self - ); - - $this->assertLinkObject( - 'https://docs.mollie.com/reference/v2/methods-api/get-method', - 'text/html', - $method->_links->documentation - ); - - $price = $method->pricing[0]; - - $this->assertEquals('The Netherlands', $price->description); - $this->assertAmountObject(0.29, 'EUR', $price->fixed); - $this->assertEquals('0', $price->variable); - - $method_prices = $method->pricing(); - - $this->assertInstanceOf(MethodPriceCollection::class, $method_prices); - - $method_price = $method_prices[0]; - $this->assertInstanceOf(MethodPrice::class, $method_price); - $this->assertAmountObject(0.29, 'EUR', $method_price->fixed); - $this->assertEquals('0', $method_price->variable); - } - - public function testGetTranslatedMethod() - { - $this->mockApiCall( - new Request('GET', '/v2/methods/sofort?locale=de_DE'), - new Response( - 200, - [], - '{ - "resource": "method", - "id": "sofort", - "description": "SOFORT \u00dcberweisung", - "minimumAmount": { - "value": "0.01", - "currency": "EUR" - }, - "maximumAmount": { - "value": "50000.00", - "currency": "EUR" - }, - "image": { - "size1x": "https://www.mollie.com/images/payscreen/methods/sofort.png", - "size2x": "https://www.mollie.com/images/payscreen/methods/sofort%402x.png" - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/methods/sofort", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/methods-api/get-method", - "type": "text/html" - } - } - }' - ) - ); - - $method = $this->apiClient->methods->get('sofort', ['locale' => 'de_DE']); - - $this->assertInstanceOf(Method::class, $method); - $this->assertEquals('sofort', $method->id); - $this->assertEquals('SOFORT Überweisung', $method->description); - $this->assertAmountObject(0.01, 'EUR', $method->minimumAmount); - $this->assertAmountObject(50000, 'EUR', $method->maximumAmount); - - $amount = new Stdclass(); - $amount->size1x = 'https://www.mollie.com/images/payscreen/methods/sofort.png'; - $amount->size2x = 'https://www.mollie.com/images/payscreen/methods/sofort%402x.png'; - - $selfLink = (object)[ - 'href' => 'https://api.mollie.com/v2/methods/sofort', - 'type' => 'application/hal+json', - ]; - $this->assertEquals($selfLink, $method->_links->self); - - $documentationLink = (object)[ - 'href' => 'https://docs.mollie.com/reference/v2/methods-api/get-method', - 'type' => 'text/html', - ]; - - $this->assertEquals($documentationLink, $method->_links->documentation); - } - - public function testListAllActiveMethods() - { - $this->mockApiCall( - new Request('GET', '/v2/methods'), - new Response( - 200, - [], - '{ - "_embedded": { - "methods": [ - { - "resource": "method", - "id": "ideal", - "description": "iDEAL", - "minimumAmount": { - "value": "0.01", - "currency": "EUR" - }, - "maximumAmount": { - "value": "50000.00", - "currency": "EUR" - }, - "image": { - "size1x": "https://www.mollie.com/images/payscreen/methods/ideal.png", - "size2x": "https://www.mollie.com/images/payscreen/methods/ideal%402x.png" - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/methods/ideal", - "type": "application/hal+json" - } - } - }, - { - "resource": "method", - "id": "creditcard", - "description": "Credit card", - "minimumAmount": { - "value": "0.01", - "currency": "EUR" - }, - "maximumAmount": { - "value": "2000.00", - "currency": "EUR" - }, - "image": { - "size1x": "https://www.mollie.com/images/payscreen/methods/creditcard.png", - "size2x": "https://www.mollie.com/images/payscreen/methods/creditcard%402x.png" - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/methods/creditcard", - "type": "application/hal+json" - } - } - }, - { - "resource": "method", - "id": "mistercash", - "description": "Bancontact", - "minimumAmount": { - "value": "0.02", - "currency": "EUR" - }, - "maximumAmount": { - "value": "50000.00", - "currency": "EUR" - }, - "image": { - "size1x": "https://www.mollie.com/images/payscreen/methods/mistercash.png", - "size2x": "https://www.mollie.com/images/payscreen/methods/mistercash%402x.png" - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/methods/mistercash", - "type": "application/hal+json" - } - } - }, - { - "resource": "method", - "id": "giftcard", - "description": "Gift cards", - "minimumAmount": { - "value": "0.01", - "currency": "EUR" - }, - "maximumAmount": null, - "image": { - "size1x": "https://www.mollie.com/images/payscreen/methods/giftcard.png", - "size2x": "https://www.mollie.com/images/payscreen/methods/giftcard%402x.png" - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/methods/giftcard", - "type": "application/hal+json" - } - } - } - ] - }, - "count": 4, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/methods-api/list-methods", - "type": "text/html" - }, - "self": { - "href": "http://api.mollie.com/v2/methods", - "type": "application/hal+json" - } - } - }' - ) - ); - - $methods = $this->apiClient->methods->allActive(); - - $this->assertInstanceOf(MethodCollection::class, $methods); - $this->assertEquals(4, $methods->count); - $this->assertCount(4, $methods); - - $documentationLink = (object)[ - 'href' => 'https://docs.mollie.com/reference/v2/methods-api/list-methods', - 'type' => 'text/html', - ]; - $this->assertEquals($documentationLink, $methods->_links->documentation); - - $selfLink = (object)[ - 'href' => 'http://api.mollie.com/v2/methods', - 'type' => 'application/hal+json', - ]; - $this->assertEquals($selfLink, $methods->_links->self); - - $creditcardMethod = $methods[1]; - - $this->assertInstanceOf(Method::class, $creditcardMethod); - $this->assertEquals('creditcard', $creditcardMethod->id); - $this->assertEquals('Credit card', $creditcardMethod->description); - $this->assertAmountObject(0.01, 'EUR', $creditcardMethod->minimumAmount); - $this->assertAmountObject(2000, 'EUR', $creditcardMethod->maximumAmount); - $this->assertEquals('https://www.mollie.com/images/payscreen/methods/creditcard.png', $creditcardMethod->image->size1x); - $this->assertEquals('https://www.mollie.com/images/payscreen/methods/creditcard%402x.png', $creditcardMethod->image->size2x); - - $selfLink = (object)[ - 'href' => 'https://api.mollie.com/v2/methods/creditcard', - 'type' => 'application/hal+json', - ]; - $this->assertEquals($selfLink, $creditcardMethod->_links->self); - } - - public function testListAllAvailableMethods() - { - $this->mockApiCall( - new Request('GET', '/v2/methods/all?include=pricing'), - new Response( - 200, - [], - '{ - "_embedded": { - "methods": [ - { - "resource": "method", - "id": "ideal", - "description": "iDEAL", - "minimumAmount": { - "value": "0.01", - "currency": "EUR" - }, - "maximumAmount": { - "value": "50000.00", - "currency": "EUR" - }, - "image": { - "size1x": "https://www.mollie.com/images/payscreen/methods/ideal.png", - "size2x": "https://www.mollie.com/images/payscreen/methods/ideal%402x.png" - }, - "pricing": [ - { - "description": "Netherlands", - "fixed": { - "value": "0.29", - "currency": "EUR" - }, - "variable": "0" - } - ], - "_links": { - "self": { - "href": "https://api.mollie.com/v2/methods/ideal", - "type": "application/hal+json" - } - } - }, - { - "resource": "method", - "id": "creditcard", - "description": "Credit card", - "minimumAmount": { - "value": "0.01", - "currency": "EUR" - }, - "maximumAmount": { - "value": "2000.00", - "currency": "EUR" - }, - "image": { - "size1x": "https://www.mollie.com/images/payscreen/methods/creditcard.png", - "size2x": "https://www.mollie.com/images/payscreen/methods/creditcard%402x.png" - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/methods/creditcard", - "type": "application/hal+json" - } - } - }, - { - "resource": "method", - "id": "mistercash", - "description": "Bancontact", - "minimumAmount": { - "value": "0.02", - "currency": "EUR" - }, - "maximumAmount": { - "value": "50000.00", - "currency": "EUR" - }, - "image": { - "size1x": "https://www.mollie.com/images/payscreen/methods/mistercash.png", - "size2x": "https://www.mollie.com/images/payscreen/methods/mistercash%402x.png" - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/methods/mistercash", - "type": "application/hal+json" - } - } - }, - { - "resource": "method", - "id": "giftcard", - "description": "Gift cards", - "minimumAmount": { - "value": "0.01", - "currency": "EUR" - }, - "maximumAmount": null, - "image": { - "size1x": "https://www.mollie.com/images/payscreen/methods/giftcard.png", - "size2x": "https://www.mollie.com/images/payscreen/methods/giftcard%402x.png" - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/methods/giftcard", - "type": "application/hal+json" - } - } - } - ] - }, - "count": 4, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/methods-api/list-methods", - "type": "text/html" - }, - "self": { - "href": "http://api.mollie.com/v2/methods", - "type": "application/hal+json" - } - } - }' - ) - ); - - $methods = $this->apiClient->methods->allAvailable(['include' => 'pricing']); - - $this->assertInstanceOf(MethodCollection::class, $methods); - $this->assertEquals(4, $methods->count); - $this->assertCount(4, $methods); - - $this->assertLinkObject( - 'https://docs.mollie.com/reference/v2/methods-api/list-methods', - 'text/html', - $methods->_links->documentation - ); - - $this->assertLinkObject( - 'http://api.mollie.com/v2/methods', - 'application/hal+json', - $methods->_links->self - ); - - $creditcardMethod = $methods[1]; - - $this->assertInstanceOf(Method::class, $creditcardMethod); - $this->assertEquals('creditcard', $creditcardMethod->id); - $this->assertEquals('Credit card', $creditcardMethod->description); - $this->assertAmountObject(0.01, 'EUR', $creditcardMethod->minimumAmount); - $this->assertAmountObject(2000, 'EUR', $creditcardMethod->maximumAmount); - $this->assertEquals('https://www.mollie.com/images/payscreen/methods/creditcard.png', $creditcardMethod->image->size1x); - $this->assertEquals('https://www.mollie.com/images/payscreen/methods/creditcard%402x.png', $creditcardMethod->image->size2x); - - $this->assertLinkObject( - 'https://api.mollie.com/v2/methods/creditcard', - 'application/hal+json', - $creditcardMethod->_links->self - ); - } -} diff --git a/tests/Mollie/API/Endpoints/MethodIssuerEndpointTest.php b/tests/Mollie/API/Endpoints/MethodIssuerEndpointTest.php deleted file mode 100644 index a251c2b1a..000000000 --- a/tests/Mollie/API/Endpoints/MethodIssuerEndpointTest.php +++ /dev/null @@ -1,57 +0,0 @@ -mockApiCall( - new Request( - 'POST', - 'https://api.mollie.com/v2/profiles/pfl_QkEhN94Ba/methods/ideal/issuers/festivalcadeau' - ), - new Response( - 201, - [], - '{ - "resource": "issuer", - "id": "festivalcadeau", - "name": "Festival Cadeau", - "method": "ideal", - "image": { - "size1x": "https://www.mollie.com/images/payscreen/methods/ideal.png", - "size2x": "https://www.mollie.com/images/payscreen/methods/ideal%402x.png" - } - }' - ) - ); - - $response = $this->apiClient->methodIssuers->enable('pfl_QkEhN94Ba', 'ideal', 'festivalcadeau'); - $this->assertInstanceOf(Issuer::class, $response); - $this->assertEquals('festivalcadeau', $response->id); - } - - /** @test */ - public function testDisableIssuer() - { - $this->mockApiCall( - new Request( - 'DELETE', - 'https://api.mollie.com/v2/profiles/pfl_QkEhN94Ba/methods/ideal/issuers/festivalcadeau' - ), - new Response(204) - ); - - $response = $this->apiClient->methodIssuers->disable('pfl_QkEhN94Ba', 'ideal', 'festivalcadeau'); - - $this->assertNull($response); - } -} diff --git a/tests/Mollie/API/Endpoints/OnboardingEndpointTest.php b/tests/Mollie/API/Endpoints/OnboardingEndpointTest.php deleted file mode 100644 index af9d1afbf..000000000 --- a/tests/Mollie/API/Endpoints/OnboardingEndpointTest.php +++ /dev/null @@ -1,82 +0,0 @@ -mockApiCall( - new Request('GET', '/v2/onboarding/me'), - new Response( - 200, - [], - '{ - "resource": "onboarding", - "name": "Mollie B.V.", - "signedUpAt": "2018-12-20T10:49:08+00:00", - "status": "completed", - "canReceivePayments": true, - "canReceiveSettlements": true, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/onboarding/me", - "type": "application/hal+json" - }, - "dashboard": { - "href": "https://www.mollie.com/dashboard/onboarding", - "type": "text/html" - }, - "organization": { - "href": "https://api.mollie.com/v2/organization/org_12345", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/onboarding-api/get-onboarding-status", - "type": "text/html" - } - } - }' - ) - ); - - $onboarding = $this->apiClient->onboarding->get(); - - $this->assertInstanceOf(Onboarding::class, $onboarding); - $this->assertEquals("onboarding", $onboarding->resource); - $this->assertEquals("Mollie B.V.", $onboarding->name); - $this->assertEquals(OnboardingStatus::COMPLETED, $onboarding->status); - $this->assertEquals("2018-12-20T10:49:08+00:00", $onboarding->signedUpAt); - $this->assertEquals(true, $onboarding->canReceivePayments); - $this->assertEquals(true, $onboarding->canReceiveSettlements); - - $selfLink = (object)['href' => 'https://api.mollie.com/v2/onboarding/me', 'type' => 'application/hal+json']; - $this->assertEquals($selfLink, $onboarding->_links->self); - - $dashboardLink = (object)['href' => 'https://www.mollie.com/dashboard/onboarding', 'type' => 'text/html']; - $this->assertEquals($dashboardLink, $onboarding->_links->dashboard); - - $organizationLink = (object)['href' => 'https://api.mollie.com/v2/organization/org_12345', 'type' => 'application/hal+json']; - $this->assertEquals($organizationLink, $onboarding->_links->organization); - - $documentationLink = (object)['href' => 'https://docs.mollie.com/reference/v2/onboarding-api/get-onboarding-status', 'type' => 'text/html']; - $this->assertEquals($documentationLink, $onboarding->_links->documentation); - } - - public function testSubmitWorks() - { - $this->mockApiCall( - new Request('POST', '/v2/onboarding/me'), - new Response(204) - ); - - $this->apiClient->onboarding->submit(); - } -} diff --git a/tests/Mollie/API/Endpoints/OrderEndpointTest.php b/tests/Mollie/API/Endpoints/OrderEndpointTest.php deleted file mode 100644 index 998d7f281..000000000 --- a/tests/Mollie/API/Endpoints/OrderEndpointTest.php +++ /dev/null @@ -1,1191 +0,0 @@ -mockApiCall( - new Request( - "POST", - "/v2/orders", - [], - '{ - "amount": { - "value": "1027.99", - "currency": "EUR" - }, - "billingAddress": { - "organizationName": "Organization Name LTD.", - "streetAndNumber": "Keizersgracht 313", - "postalCode": "1016 EE", - "city": "Amsterdam", - "country": "nl", - "givenName": "Luke", - "familyName": "Skywalker", - "email": "luke@skywalker.com" - }, - "shippingAddress": { - "organizationName": "Organization Name LTD.", - "streetAndNumber": "Keizersgracht 313", - "postalCode": "1016 EE", - "city": "Amsterdam", - "country": "nl", - "givenName": "Luke", - "familyName": "Skywalker", - "email": "luke@skywalker.com" - }, - "metadata": { - "order_id": "1337", - "description": "Lego cars" - }, - "consumerDateOfBirth": "1958-01-31", - "orderNumber": "1337", - "locale": "nl_NL", - "method" : "klarnapaylater", - "redirectUrl": "https://example.org/redirect", - "webhookUrl": "https://example.org/webhook", - "lines": [ - { - "sku": "5702016116977", - "name": "LEGO 42083 Bugatti Chiron", - "productUrl": "https://shop.lego.com/nl-NL/Bugatti-Chiron-42083", - "imageUrl": "https://sh-s7-live-s.legocdn.com/is/image//LEGO/42083_alt1?$main$", - "quantity": 2, - "unitPrice": { - "currency": "EUR", - "value": "399.00" - }, - "vatRate": "21.00", - "vatAmount": { - "currency": "EUR", - "value": "121.14" - }, - "discountAmount": { - "currency": "EUR", - "value": "100.00" - }, - "totalAmount": { - "currency": "EUR", - "value": "698.00" - } - }, - { - "type": "digital", - "sku": "5702015594028", - "name": "LEGO 42056 Porsche 911 GT3 RS", - "productUrl": "https://shop.lego.com/nl-NL/Porsche-911-GT3-RS-42056", - "imageUrl": "https://sh-s7-live-s.legocdn.com/is/image/LEGO/42056?$PDPDefault$", - "quantity": 1, - "unitPrice": { - "currency": "EUR", - "value": "329.99" - }, - "vatRate": "21.00", - "vatAmount": { - "currency": "EUR", - "value": "57.27" - }, - "totalAmount": { - "currency": "EUR", - "value": "329.99" - } - } - ] - }' - ), - new Response( - 201, - [], - $this->getOrderResponseFixture("ord_pbjz8x") - ) - ); - - $order = $this->apiClient->orders->create([ - "amount" => [ - "value" => "1027.99", - "currency" => "EUR", - ], - "billingAddress" => [ - "organizationName" => "Organization Name LTD.", - "streetAndNumber" => "Keizersgracht 313", - "postalCode" => "1016 EE", - "city" => "Amsterdam", - "country" => "nl", - "givenName" => "Luke", - "familyName" => "Skywalker", - "email" => "luke@skywalker.com", - ], - "shippingAddress" => [ - "organizationName" => "Organization Name LTD.", - "streetAndNumber" => "Keizersgracht 313", - "postalCode" => "1016 EE", - "city" => "Amsterdam", - "country" => "nl", - "givenName" => "Luke", - "familyName" => "Skywalker", - "email" => "luke@skywalker.com", - ], - "metadata" => [ - "order_id" => "1337", - "description" => "Lego cars", - ], - "consumerDateOfBirth" => "1958-01-31", - "locale" => "nl_NL", - "orderNumber" => "1337", - "redirectUrl" => "https://example.org/redirect", - "webhookUrl" => "https://example.org/webhook", - "method" => "klarnapaylater", - "lines" => [ - [ - "sku" => "5702016116977", - "name" => "LEGO 42083 Bugatti Chiron", - "productUrl" => "https://shop.lego.com/nl-NL/Bugatti-Chiron-42083", - "imageUrl" => 'https://sh-s7-live-s.legocdn.com/is/image//LEGO/42083_alt1?$main$', - "quantity" => 2, - "vatRate" => "21.00", - "unitPrice" => [ - "currency" => "EUR", - "value" => "399.00", - ], - "totalAmount" => [ - "currency" => "EUR", - "value" => "698.00", - ], - "discountAmount" => [ - "currency" => "EUR", - "value" => "100.00", - ], - "vatAmount" => [ - "currency" => "EUR", - "value" => "121.14", - ], - ], - [ - "type" => "digital", - "sku" => "5702015594028", - "name" => "LEGO 42056 Porsche 911 GT3 RS", - "productUrl" => "https://shop.lego.com/nl-NL/Porsche-911-GT3-RS-42056", - "imageUrl" => 'https://sh-s7-live-s.legocdn.com/is/image/LEGO/42056?$PDPDefault$', - "quantity" => 1, - "vatRate" => "21.00", - "unitPrice" => [ - "currency" => "EUR", - "value" => "329.99", - ], - "totalAmount" => [ - "currency" => "EUR", - "value" => "329.99", - ], - "vatAmount" => [ - "currency" => "EUR", - "value" => "57.27", - ], - ], - ], - ]); - - $this->assertOrder($order, 'ord_pbjz8x'); - } - - public function testGetOrderDirectly() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/orders/ord_pbjz8x" - ), - new Response( - 200, - [], - $this->getOrderResponseFixture("ord_pbjz8x") - ) - ); - - $order = $this->apiClient->orders->get('ord_pbjz8x'); - - $this->assertOrder($order, 'ord_pbjz8x'); - } - - public function testGetOrderDirectlyIncludingPayments() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/orders/ord_kEn1PlbGa?embed=payments" - ), - new Response( - 200, - [], - '{ - "resource": "order", - "id": "ord_kEn1PlbGa", - "profileId": "pfl_URR55HPMGx", - "method": "klarnapaylater", - "amount": { - "value": "1027.99", - "currency": "EUR" - }, - "status": "created", - "isCancelable": true, - "metadata": null, - "createdAt": "2018-08-02T09:29:56+00:00", - "expiresAt": "2018-08-30T09:29:56+00:00", - "mode": "live", - "locale": "nl_NL", - "billingAddress": { - "organizationName": "Mollie B.V.", - "streetAndNumber": "Keizersgracht 313", - "postalCode": "1016 EE", - "city": "Amsterdam", - "country": "nl", - "givenName": "Luke", - "familyName": "Skywalker", - "email": "luke@skywalker.com" - }, - "orderNumber": "18475", - "shippingAddress": { - "organizationName": "Mollie B.V.", - "streetAndNumber": "Keizersgracht 313", - "postalCode": "1016 EE", - "city": "Amsterdam", - "country": "nl", - "givenName": "Luke", - "familyName": "Skywalker", - "email": "luke@skywalker.com" - }, - "redirectUrl": "https://example.org/redirect", - "lines": [ - { - "resource": "orderline", - "id": "odl_dgtxyl", - "orderId": "ord_pbjz8x", - "name": "LEGO 42083 Bugatti Chiron", - "sku": "5702016116977", - "type": "physical", - "status": "created", - "metadata": null, - "isCancelable": false, - "quantity": 2, - "quantityShipped": 0, - "amountShipped": { - "value": "0.00", - "currency": "EUR" - }, - "quantityRefunded": 0, - "amountRefunded": { - "value": "0.00", - "currency": "EUR" - }, - "quantityCanceled": 0, - "amountCanceled": { - "value": "0.00", - "currency": "EUR" - }, - "shippableQuantity": 0, - "refundableQuantity": 0, - "cancelableQuantity": 0, - "unitPrice": { - "value": "399.00", - "currency": "EUR" - }, - "vatRate": "21.00", - "vatAmount": { - "value": "121.14", - "currency": "EUR" - }, - "discountAmount": { - "value": "100.00", - "currency": "EUR" - }, - "totalAmount": { - "value": "698.00", - "currency": "EUR" - }, - "createdAt": "2018-08-02T09:29:56+00:00", - "_links": { - "productUrl": { - "href": "https://shop.lego.com/nl-NL/Bugatti-Chiron-42083", - "type": "text/html" - }, - "imageUrl": { - "href": "https://sh-s7-live-s.legocdn.com/is/image//LEGO/42083_alt1?$main$", - "type": "text/html" - } - } - }, - { - "resource": "orderline", - "id": "odl_jp31jz", - "orderId": "ord_pbjz8x", - "name": "LEGO 42056 Porsche 911 GT3 RS", - "sku": "5702015594028", - "type": "physical", - "status": "created", - "metadata": null, - "isCancelable": false, - "quantity": 1, - "quantityShipped": 0, - "amountShipped": { - "value": "0.00", - "currency": "EUR" - }, - "quantityRefunded": 0, - "amountRefunded": { - "value": "0.00", - "currency": "EUR" - }, - "quantityCanceled": 0, - "amountCanceled": { - "value": "0.00", - "currency": "EUR" - }, - "shippableQuantity": 0, - "refundableQuantity": 0, - "cancelableQuantity": 0, - "unitPrice": { - "value": "329.99", - "currency": "EUR" - }, - "vatRate": "21.00", - "vatAmount": { - "value": "57.27", - "currency": "EUR" - }, - "totalAmount": { - "value": "329.99", - "currency": "EUR" - }, - "createdAt": "2018-08-02T09:29:56+00:00", - "_links": { - "productUrl": { - "href": "https://shop.lego.com/nl-NL/Porsche-911-GT3-RS-42056", - "type": "text/html" - }, - "imageUrl": { - "href": "https://sh-s7-live-s.legocdn.com/is/image/LEGO/42056?$PDPDefault$", - "type": "text/html" - } - } - } - ], - "_embedded": { - "payments": [ - { - "resource": "payment", - "id": "tr_ncaPcAhuUV", - "mode": "live", - "createdAt": "2018-09-07T12:00:05+00:00", - "amount": { - "value": "1027.99", - "currency": "EUR" - }, - "description": "Order #1337 (Lego cars)", - "method": null, - "metadata": null, - "status": "open", - "isCancelable": false, - "locale": "nl_NL", - "profileId": "pfl_URR55HPMGx", - "orderId": "ord_kEn1PlbGa", - "sequenceType": "oneoff", - "redirectUrl": "https://example.org/redirect", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_ncaPcAhuUV", - "type": "application/hal+json" - }, - "checkout": { - "href": "https://www.mollie.com/payscreen/select-method/ncaPcAhuUV", - "type": "text/html" - }, - "order": { - "href": "https://api.mollie.com/v2/orders/ord_kEn1PlbGa", - "type": "application/hal+json" - } - } - } - ] - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/orders/ord_pbjz8x", - "type": "application/hal+json" - }, - "checkout": { - "href": "https://www.mollie.com/payscreen/order/checkout/pbjz8x", - "type": "text/html" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/orders-api/get-order", - "type": "text/html" - } - } - }' - ) - ); - - $order = $this->apiClient->orders->get('ord_kEn1PlbGa', ['embed' => 'payments']); - - $this->assertInstanceOf(Order::class, $order); - $this->assertEquals('ord_kEn1PlbGa', $order->id); - - $payments = $order->payments(); - $this->assertInstanceOf(PaymentCollection::class, $payments); - - $payment = $payments[0]; - $this->assertInstanceOf(Payment::class, $payment); - $this->assertEquals('tr_ncaPcAhuUV', $payment->id); - $this->assertEquals('2018-09-07T12:00:05+00:00', $payment->createdAt); - $this->assertAmountObject('1027.99', 'EUR', $payment->amount); - $this->assertEquals('Order #1337 (Lego cars)', $payment->description); - $this->assertNull($payment->method); - $this->assertNull($payment->metadata); - $this->assertEquals('open', $payment->status); - $this->assertFalse($payment->isCancelable); - $this->assertEquals('nl_NL', $payment->locale); - $this->assertEquals('pfl_URR55HPMGx', $payment->profileId); - $this->assertEquals('ord_kEn1PlbGa', $payment->orderId); - $this->assertEquals('oneoff', $payment->sequenceType); - $this->assertEquals('https://example.org/redirect', $payment->redirectUrl); - $this->assertLinkObject( - 'https://api.mollie.com/v2/payments/tr_ncaPcAhuUV', - 'application/hal+json', - $payment->_links->self - ); - $this->assertLinkObject( - 'https://www.mollie.com/payscreen/select-method/ncaPcAhuUV', - 'text/html', - $payment->_links->checkout - ); - $this->assertLinkObject( - 'https://api.mollie.com/v2/orders/ord_kEn1PlbGa', - 'application/hal+json', - $payment->_links->order - ); - } - - public function testGetOrderOnShipmentResource() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/orders/ord_pbjz8x" - ), - new Response( - 200, - [], - $this->getOrderResponseFixture("ord_pbjz8x") - ) - ); - - $shipment = $this->getShipment("shp_3wmsgCJN4U", "ord_pbjz8x"); - $order = $shipment->order(); - - $this->assertOrder($order, 'ord_pbjz8x'); - } - - public function testListOrders() - { - $this->mockApiCall( - new Request("GET", "/v2/orders"), - new Response( - 200, - [], - '{ - "count": 3, - "_embedded": { - "orders": [ - ' . $this->getOrderResponseFixture("ord_pbjz1x") . ', - ' . $this->getOrderResponseFixture("ord_pbjz2y") . ', - ' . $this->getOrderResponseFixture("ord_pbjz3z") . ' - ] - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/orders", - "type": "application/hal+json" - }, - "previous": null, - "next": { - "href": "https://api.mollie.com/v2/orders?from=ord_stTC2WHAuS", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/orders-api/list-orders", - "type": "text/html" - } - } - }' - ) - ); - - $orders = $this->apiClient->orders->page(); - - $this->assertInstanceOf(OrderCollection::class, $orders); - $this->assertEquals(3, $orders->count); - $this->assertEquals(3, count($orders)); - - $this->assertNull($orders->_links->previous); - $selfLink = $this->createLinkObject( - "https://api.mollie.com/v2/orders", - "application/hal+json" - ); - $this->assertEquals($selfLink, $orders->_links->self); - - $nextLink = $this->createLinkObject( - "https://api.mollie.com/v2/orders?from=ord_stTC2WHAuS", - "application/hal+json" - ); - $this->assertEquals($nextLink, $orders->_links->next); - - $documentationLink = $this->createLinkObject( - "https://docs.mollie.com/reference/v2/orders-api/list-orders", - "text/html" - ); - $this->assertEquals($documentationLink, $orders->_links->documentation); - - $this->assertOrder($orders[0], 'ord_pbjz1x'); - $this->assertOrder($orders[1], 'ord_pbjz2y'); - $this->assertOrder($orders[2], 'ord_pbjz3z'); - } - - public function testIterateOrders() - { - $this->mockApiCall( - new Request("GET", "/v2/orders"), - new Response( - 200, - [], - '{ - "count": 3, - "_embedded": { - "orders": [ - ' . $this->getOrderResponseFixture("ord_pbjz1x") . ', - ' . $this->getOrderResponseFixture("ord_pbjz2y") . ', - ' . $this->getOrderResponseFixture("ord_pbjz3z") . ' - ] - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/orders", - "type": "application/hal+json" - }, - "previous": null, - "next": null, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/orders-api/list-orders", - "type": "text/html" - } - } - }' - ) - ); - - foreach ($this->apiClient->orders->iterator() as $order) { - $this->assertInstanceOf(Order::class, $order); - } - } - - public function testCancelOrderDirectly() - { - $this->mockApiCall( - new Request("DELETE", "/v2/orders/ord_pbjz1x"), - new Response( - 200, - [], - $this->getOrderResponseFixture( - 'ord_pbjz1x', - OrderStatus::STATUS_CANCELED - ) - ) - ); - $order = $this->apiClient->orders->cancel('ord_pbjz1x'); - $this->assertOrder($order, 'ord_pbjz1x', OrderStatus::STATUS_CANCELED); - } - - public function testCancelOrderOnResource() - { - $this->mockApiCall( - new Request("DELETE", "/v2/orders/ord_pbjz1x"), - new Response( - 200, - [], - $this->getOrderResponseFixture( - 'ord_pbjz1x', - OrderStatus::STATUS_CANCELED - ) - ) - ); - $order = $this->getOrder('ord_pbjz1x'); - $canceledOrder = $order->cancel(); - $this->assertOrder($canceledOrder, 'ord_pbjz1x', OrderStatus::STATUS_CANCELED); - } - - public function testCancelOrderLines() - { - $this->mockApiCall( - new Request( - "DELETE", - "/v2/orders/ord_8wmqcHMN4U/lines", - [], - '{ - "lines": [ - { - "id": "odl_dgtxyl", - "quantity": 1 - } - ] - }' - ), - new Response(204) - ); - - $order = $this->getOrder('ord_8wmqcHMN4U'); - - $result = $order->cancelLines([ - 'lines' => [ - [ - 'id' => 'odl_dgtxyl', - 'quantity' => 1, - ], - ], - ]); - - $this->assertNull($result); - } - - public function testCancelAllOrderLines() - { - $this->mockApiCall( - new Request( - "DELETE", - "/v2/orders/ord_8wmqcHMN4U/lines", - [], - '{ - "lines": [], - "foo": "bar" - }' - ), - new Response(204) - ); - - $order = $this->getOrder('ord_8wmqcHMN4U'); - - $result = $order->cancelAllLines([ - 'foo' => 'bar', - ]); - - $this->assertNull($result); - } - - /** @test */ - public function testUpdateOrder() - { - $this->mockApiCall( - new Request( - "PATCH", - "/v2/orders/ord_pbjz8x", - [], - '{ - "billingAddress": { - "organizationName": "Organization Name LTD.", - "streetAndNumber": "Keizersgracht 313", - "postalCode": "1234AB", - "city": "Amsterdam", - "country": "NL", - "givenName": "Piet", - "familyName": "Mondriaan", - "email": "piet@mondriaan.com", - "region": "Noord-Holland", - "title": "Dhr", - "phone": "+31208202070" - }, - "shippingAddress": { - "organizationName": "Organization Name LTD.", - "streetAndNumber": "Keizersgracht 313", - "postalCode": "1016 EE", - "city": "Amsterdam", - "country": "nl", - "givenName": "Luke", - "familyName": "Skywalker", - "email": "luke@skywalker.com" - }, - "orderNumber": "16738", - "redirectUrl": "https://example.org/updated-redirect", - "cancelUrl": "https://example.org/updated-cancel-url", - "webhookUrl": "https://example.org/updated-webhook" - }' - ), - new Response( - 200, - [], - $this->getOrderResponseFixture( - "ord_pbjz8x", - OrderStatus::STATUS_CREATED, - "16738" - ) - ) - ); - - /** @var Order $order */ - $order = $this->getOrder("ord_pbjz8x"); - - $order->billingAddress->organizationName = "Organization Name LTD."; - $order->billingAddress->streetAndNumber = "Keizersgracht 313"; - $order->billingAddress->city = "Amsterdam"; - $order->billingAddress->region = "Noord-Holland"; - $order->billingAddress->postalCode = "1234AB"; - $order->billingAddress->country = "NL"; - $order->billingAddress->title = "Dhr"; - $order->billingAddress->givenName = "Piet"; - $order->billingAddress->familyName = "Mondriaan"; - $order->billingAddress->email = "piet@mondriaan.com"; - $order->billingAddress->phone = "+31208202070"; - $order->orderNumber = "16738"; - $order->redirectUrl = "https://example.org/updated-redirect"; - $order->cancelUrl = "https://example.org/updated-cancel-url"; - $order->webhookUrl = "https://example.org/updated-webhook"; - $order = $order->update(); - - $this->assertOrder($order, "ord_pbjz8x", OrderStatus::STATUS_CREATED, "16738"); - } - - public function testUpdateOrderLine() - { - $this->mockApiCall( - new Request( - "PATCH", - "/v2/orders/ord_pbjz8x/lines/odl_dgtxyl", - [], - '{ - "name": "LEGO 71043 Hogwarts™ Castle", - "productUrl": "https://shop.lego.com/en-GB/product/Hogwarts-Castle-71043", - "imageUrl": "https://sh-s7-live-s.legocdn.com/is/image//LEGO/71043_alt1?$main$", - "quantity": 2, - "vatRate": "21.00", - "sku": "5702016116977", - "unitPrice": { - "currency": "EUR", - "value": "349.00" - }, - "totalAmount": { - "currency": "EUR", - "value": "598.00" - }, - "discountAmount": { - "currency": "EUR", - "value": "100.00" - }, - "vatAmount": { - "currency": "EUR", - "value": "103.79" - }, - "metadata": { - "foo": "bar" - } - }' - ), - new Response(200, [], $this->getOrderResponseFixture('ord_pbjz8x')) - ); - - $orderLine = new OrderLine($this->apiClient); - $orderLine->id = 'odl_dgtxyl'; - $orderLine->orderId = 'ord_pbjz8x'; - $orderLine->name = 'LEGO 71043 Hogwarts™ Castle'; - $orderLine->productUrl = 'https://shop.lego.com/en-GB/product/Hogwarts-Castle-71043'; - $orderLine->imageUrl = 'https://sh-s7-live-s.legocdn.com/is/image//LEGO/71043_alt1?$main$'; - $orderLine->sku = '5702016116977'; - $orderLine->quantity = 2; - $orderLine->vatRate = '21.00'; - $orderLine->unitPrice = (object) ['currency' => 'EUR', 'value' => '349.00']; - $orderLine->totalAmount = (object) ['currency' => 'EUR', 'value' => '598.00']; - $orderLine->discountAmount = (object) ['currency' => 'EUR', 'value' => '100.00']; - $orderLine->vatAmount = (object) ['currency' => 'EUR', 'value' => '103.79']; - $orderLine->metadata = (object) ['foo' => 'bar']; - - $result = $orderLine->update(); - - $this->assertOrder($result, 'ord_pbjz8x'); - } - - protected function assertOrder($order, $order_id, $order_status = OrderStatus::STATUS_CREATED, $orderNumber = "1337") - { - $this->assertInstanceOf(Order::class, $order); - $this->assertEquals('order', $order->resource); - $this->assertEquals($order_id, $order->id); - $this->assertEquals('pfl_URR55HPMGx', $order->profileId); - $this->assertEquals('live', $order->mode); - $this->assertEquals('klarnapaylater', $order->method); - $this->assertEquals('2018-08-02T09:29:56+00:00', $order->createdAt); - $this->assertEquals('2018-09-02T09:29:56+00:00', $order->expiresAt); - - $this->assertAmountObject('1027.99', 'EUR', $order->amount); - $this->assertAmountObject('0.00', 'EUR', $order->amountCaptured); - $this->assertAmountObject('0.00', 'EUR', $order->amountRefunded); - - $this->assertEquals((object) [ - 'order_id' => '1337', - 'description' => 'Lego cars', - ], $order->metadata); - - $this->assertEquals($order_status, $order->status); - - $billingAddress = new stdClass(); - $billingAddress->organizationName = "Organization Name LTD."; - $billingAddress->streetAndNumber = "Keizersgracht 313"; - $billingAddress->postalCode = "1016 EE"; - $billingAddress->city = "Amsterdam"; - $billingAddress->country = "nl"; - $billingAddress->givenName = "Luke"; - $billingAddress->familyName = "Skywalker"; - $billingAddress->email = "luke@skywalker.com"; - $this->assertEquals($billingAddress, $order->billingAddress); - - $shippingAddress = new stdClass(); - $shippingAddress->organizationName = "Organization Name LTD."; - $shippingAddress->streetAndNumber = "Keizersgracht 313"; - $shippingAddress->postalCode = "1016 EE"; - $shippingAddress->city = "Amsterdam"; - $shippingAddress->country = "nl"; - $shippingAddress->givenName = "Luke"; - $shippingAddress->familyName = "Skywalker"; - $shippingAddress->email = "luke@skywalker.com"; - $this->assertEquals($shippingAddress, $order->shippingAddress); - - $this->assertEquals($orderNumber, $order->orderNumber); - $this->assertEquals('nl_NL', $order->locale); - - $this->assertEquals("https://example.org/redirect", $order->redirectUrl); - $this->assertEquals("https://example.org/webhook", $order->webhookUrl); - - $links = (object)[ - 'self' => $this->createLinkObject( - 'https://api.mollie.com/v2/orders/' . $order_id, - 'application/hal+json' - ), - 'checkout' => $this->createLinkObject( - 'https://www.mollie.com/payscreen/select-method/7UhSN1zuXS', - 'text/html' - ), - 'documentation' => $this->createLinkObject( - 'https://docs.mollie.com/reference/v2/orders-api/get-order', - 'text/html' - ), - ]; - $this->assertEquals($links, $order->_links); - - $line1 = new stdClass(); - $line1->resource = "orderline"; - $line1->id = "odl_dgtxyl"; - $line1->orderId = $order_id; - $line1->name = "LEGO 42083 Bugatti Chiron"; - $line1->productUrl = "https://shop.lego.com/nl-NL/Bugatti-Chiron-42083"; - $line1->imageUrl = 'https://sh-s7-live-s.legocdn.com/is/image//LEGO/42083_alt1?$main$'; - $line1->sku = "5702016116977"; - $line1->type = OrderLineType::TYPE_PHYSICAL; - $line1->status = OrderLineStatus::STATUS_CREATED; - $line1->isCancelable = true; - $line1->quantity = 2; - $line1->unitPrice = $this->createAmountObject("399.00", "EUR"); - $line1->vatRate = "21.00"; - $line1->vatAmount = $this->createAmountObject("121.14", "EUR"); - $line1->discountAmount = $this->createAmountObject("100.00", "EUR"); - $line1->totalAmount = $this->createAmountObject("698.00", "EUR"); - $line1->createdAt = "2018-08-02T09:29:56+00:00"; - $this->assertEquals($line1, $order->lines[0]); - - $line2 = new stdClass(); - $line2->resource = "orderline"; - $line2->id = "odl_jp31jz"; - $line2->orderId = $order_id; - $line2->name = "LEGO 42056 Porsche 911 GT3 RS"; - $line2->productUrl = "https://shop.lego.com/nl-NL/Porsche-911-GT3-RS-42056"; - $line2->imageUrl = 'https://sh-s7-live-s.legocdn.com/is/image/LEGO/42056?$PDPDefault$'; - $line2->sku = "5702015594028"; - $line2->type = OrderLineType::TYPE_DIGITAL; - $line2->status = OrderLineStatus::STATUS_CREATED; - $line2->isCancelable = true; - $line2->quantity = 1; - $line2->unitPrice = $this->createAmountObject("329.99", "EUR"); - $line2->vatRate = "21.00"; - $line2->vatAmount = $this->createAmountObject("57.27", "EUR"); - $line2->totalAmount = $this->createAmountObject("329.99", "EUR"); - $line2->createdAt = "2018-08-02T09:29:56+00:00"; - $this->assertEquals($line2, $order->lines[1]); - - $this->assertNull($order->payments()); - } - - protected function getOrder($id) - { - $orderJson = $this->getOrderResponseFixture($id); - - return $this->copy(json_decode($orderJson), new Order($this->apiClient)); - } - - protected function getOrderResponseFixture($order_id, $order_status = OrderStatus::STATUS_CREATED, $orderNumber = '1337') - { - return str_replace( - [ - "<>", - "<>", - ], - [ - $order_id, - $orderNumber, - ], - '{ - "resource": "order", - "id": "<>", - "profileId": "pfl_URR55HPMGx", - "amount": { - "value": "1027.99", - "currency": "EUR" - }, - "amountCaptured": { - "value": "0.00", - "currency": "EUR" - }, - "amountRefunded": { - "value": "0.00", - "currency": "EUR" - }, - "status": "' . $order_status . '", - "metadata": { - "order_id": "1337", - "description": "Lego cars" - }, - "consumerDateOfBirth": "1958-01-31", - "createdAt": "2018-08-02T09:29:56+00:00", - "expiresAt": "2018-09-02T09:29:56+00:00", - "mode": "live", - "billingAddress": { - "organizationName": "Organization Name LTD.", - "streetAndNumber": "Keizersgracht 313", - "postalCode": "1016 EE", - "city": "Amsterdam", - "country": "nl", - "givenName": "Luke", - "familyName": "Skywalker", - "email": "luke@skywalker.com" - }, - "shippingAddress": { - "organizationName": "Organization Name LTD.", - "streetAndNumber": "Keizersgracht 313", - "postalCode": "1016 EE", - "city": "Amsterdam", - "country": "nl", - "givenName": "Luke", - "familyName": "Skywalker", - "email": "luke@skywalker.com" - }, - "orderNumber": <>, - "locale": "nl_NL", - "method" : "klarnapaylater", - "isCancelable": true, - "redirectUrl": "https://example.org/redirect", - "webhookUrl": "https://example.org/webhook", - "lines": [ - { - "resource": "orderline", - "id": "odl_dgtxyl", - "orderId": "<>", - "name": "LEGO 42083 Bugatti Chiron", - "productUrl": "https://shop.lego.com/nl-NL/Bugatti-Chiron-42083", - "imageUrl": "https://sh-s7-live-s.legocdn.com/is/image//LEGO/42083_alt1?$main$", - "sku": "5702016116977", - "type": "physical", - "status": "created", - "isCancelable": true, - "quantity": 2, - "unitPrice": { - "value": "399.00", - "currency": "EUR" - }, - "vatRate": "21.00", - "vatAmount": { - "value": "121.14", - "currency": "EUR" - }, - "discountAmount": { - "value": "100.00", - "currency": "EUR" - }, - "totalAmount": { - "value": "698.00", - "currency": "EUR" - }, - "createdAt": "2018-08-02T09:29:56+00:00" - }, - { - "resource": "orderline", - "id": "odl_jp31jz", - "orderId": "<>", - "name": "LEGO 42056 Porsche 911 GT3 RS", - "productUrl": "https://shop.lego.com/nl-NL/Porsche-911-GT3-RS-42056", - "imageUrl": "https://sh-s7-live-s.legocdn.com/is/image/LEGO/42056?$PDPDefault$", - "sku": "5702015594028", - "type": "digital", - "status": "created", - "isCancelable": true, - "quantity": 1, - "unitPrice": { - "value": "329.99", - "currency": "EUR" - }, - "vatRate": "21.00", - "vatAmount": { - "value": "57.27", - "currency": "EUR" - }, - "totalAmount": { - "value": "329.99", - "currency": "EUR" - }, - "createdAt": "2018-08-02T09:29:56+00:00" - } - ], - "_links": { - "self": { - "href": "https://api.mollie.com/v2/orders/<>", - "type": "application/hal+json" - }, - "checkout": { - "href": "https://www.mollie.com/payscreen/select-method/7UhSN1zuXS", - "type": "text/html" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/orders-api/get-order", - "type": "text/html" - } - } - }' - ); - } - - protected function getShipment($shipmentId, $orderId, $orderlineStatus = OrderLineStatus::STATUS_SHIPPING) - { - $shipmentJson = $this->getShipmentResponseFixture( - $shipmentId, - $orderId, - $orderlineStatus - ); - - return $this->copy(json_decode($shipmentJson), new Shipment($this->apiClient)); - } - - protected function getShipmentResponseFixture($shipmentId, $orderId, $orderlineStatus = OrderLineStatus::STATUS_SHIPPING) - { - return str_replace( - [ - "<>", - "<>", - "<>", - ], - [ - $orderId, - $shipmentId, - $orderlineStatus, - ], - '{ - "resource": "shipment", - "id": "<>", - "orderId": "<>", - "createdAt": "2018-08-02T09:29:56+00:00", - "profileId": "pfl_URR55HPMGx", - "lines": [ - { - "resource": "orderline", - "id": "odl_dgtxyl", - "orderId": "<>", - "name": "LEGO 42083 Bugatti Chiron", - "productUrl": "https://shop.lego.com/nl-NL/Bugatti-Chiron-42083", - "imageUrl": "https://sh-s7-live-s.legocdn.com/is/image//LEGO/42083_alt1?$main$", - "sku": "5702016116977", - "type": "physical", - "status": "<>", - "quantity": 1, - "unitPrice": { - "value": "399.00", - "currency": "EUR" - }, - "vatRate": "21.00", - "vatAmount": { - "value": "121.14", - "currency": "EUR" - }, - "discountAmount": { - "value": "100.00", - "currency": "EUR" - }, - "totalAmount": { - "value": "698.00", - "currency": "EUR" - }, - "createdAt": "2018-08-02T09:29:56+00:00" - }, - { - "resource": "orderline", - "id": "odl_jp31jz", - "orderId": "<>", - "name": "LEGO 42056 Porsche 911 GT3 RS", - "productUrl": "https://shop.lego.com/nl-NL/Porsche-911-GT3-RS-42056", - "imageUrl": "https://sh-s7-live-s.legocdn.com/is/image/LEGO/42056?$PDPDefault$", - "sku": "5702015594028", - "type": "digital", - "status": "<>", - "quantity": 1, - "unitPrice": { - "value": "329.99", - "currency": "EUR" - }, - "vatRate": "21.00", - "vatAmount": { - "value": "57.27", - "currency": "EUR" - }, - "totalAmount": { - "value": "329.99", - "currency": "EUR" - }, - "createdAt": "2018-08-02T09:29:56+00:00" - } - ], - "_links": { - "self": { - "href": "https://api.mollie.com/v2/orders/<>/shipments/<>", - "type": "application/hal+json" - }, - "order": { - "href": "https://api.mollie.com/v2/orders/<>", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/shipments-api/get-shipment", - "type": "text/html" - } - } - }' - ); - } -} diff --git a/tests/Mollie/API/Endpoints/OrderLineEndpointTest.php b/tests/Mollie/API/Endpoints/OrderLineEndpointTest.php deleted file mode 100644 index 75079cec4..000000000 --- a/tests/Mollie/API/Endpoints/OrderLineEndpointTest.php +++ /dev/null @@ -1,303 +0,0 @@ -expectException(ApiException::class); - - $this->guzzleClient = $this->createMock(Client::class); - $this->apiClient = new MollieApiClient($this->guzzleClient); - - $this->apiClient->orderLines->cancelFor(new Order($this->apiClient), []); - } - - public function testUpdateMultipleOrderLines() - { - $this->mockApiCall( - new Request( - 'PATCH', - '/v2/orders/ord_pbjz8x/lines', - [], - '{ - "operations": [ - { - "operation": "update", - "data": { - "id": "odl_1.1l9vx0", - "name": "New order line name" - } - }, - { - "operation": "cancel", - "data": { - "id": "odl_1.4hqjw6" - } - }, - { - "operation": "add", - "data": { - "name": "Adding new orderline", - "quantity": 2, - "sku": "12345679", - "totalAmount": { - "currency": "EUR", - "value": "30.00" - }, - "type": "digital", - "unitPrice": { - "currency": "EUR", - "value": "15.00" - }, - "vatAmount": { - "currency": "EUR", - "value": "0.00" - }, - "vatRate": "0.00" - } - } - ] - }' - ), - new Response( - 200, - [], - '{ - "resource": "order", - "id": "ord_pbjz8x", - "profileId": "pfl_h7UgNeDGTA", - "method": "klarnapaylater", - "amount": { - "value": "50.00", - "currency": "EUR" - }, - "status": "created", - "isCancelable": true, - "metadata": null, - "createdAt": "2022-06-09T13:49:10+00:00", - "expiresAt": "2022-07-07T13:49:10+00:00", - "mode": "live", - "locale": "en_US", - "billingAddress": { - "streetAndNumber": "Herengracht 1", - "postalCode": "1052CB", - "city": "Amsterdam", - "country": "NL", - "givenName": "mollie", - "familyName": "test", - "email": "test@test.com" - }, - "shopperCountryMustMatchBillingCountry": false, - "orderNumber": "1", - "redirectUrl": "https://api.platform.mollielabs.net", - "webhookUrl": "https://api.platform.mollielabs.net", - "lines": [ - { - "resource": "orderline", - "id": "odl_1.1l9vx0", - "orderId": "ord_pbjz8x", - "name": "New orderline name", - "sku": "123456", - "type": "digital", - "status": "created", - "metadata": null, - "isCancelable": false, - "quantity": 2, - "quantityShipped": 0, - "amountShipped": { - "value": "0.00", - "currency": "EUR" - }, - "quantityRefunded": 0, - "amountRefunded": { - "value": "0.00", - "currency": "EUR" - }, - "quantityCanceled": 0, - "amountCanceled": { - "value": "0.00", - "currency": "EUR" - }, - "shippableQuantity": 0, - "refundableQuantity": 0, - "cancelableQuantity": 0, - "unitPrice": { - "value": "10.00", - "currency": "EUR" - }, - "vatRate": "0.00", - "vatAmount": { - "value": "0.00", - "currency": "EUR" - }, - "totalAmount": { - "value": "20.00", - "currency": "EUR" - }, - "createdAt": "2022-06-09T13:49:10+00:00" - }, - { - "resource": "orderline", - "id": "odl_1.4hqjw6", - "orderId": "ord_pbjz8x", - "name": "A cancelled orderline", - "sku": "1234444", - "type": "digital", - "status": "canceled", - "metadata": null, - "isCancelable": true, - "quantity": 1, - "quantityShipped": 0, - "amountShipped": { - "value": "0.00", - "currency": "EUR" - }, - "quantityRefunded": 0, - "amountRefunded": { - "value": "0.00", - "currency": "EUR" - }, - "quantityCanceled": 1, - "amountCanceled": { - "value": "5.00", - "currency": "EUR" - }, - "shippableQuantity": 0, - "refundableQuantity": 0, - "cancelableQuantity": 0, - "unitPrice": { - "value": "5.00", - "currency": "EUR" - }, - "vatRate": "0.00", - "vatAmount": { - "value": "0.00", - "currency": "EUR" - }, - "totalAmount": { - "value": "5.00", - "currency": "EUR" - }, - "createdAt": "2022-06-10T11:05:21+00:00" - }, - { - "resource": "orderline", - "id": "odl_1.3ccpk8", - "orderId": "ord_pbjz8x", - "name": "Adding new orderline", - "sku": "12345679", - "type": "digital", - "status": "created", - "metadata": null, - "isCancelable": true, - "quantity": 2, - "quantityShipped": 0, - "amountShipped": { - "value": "0.00", - "currency": "EUR" - }, - "quantityRefunded": 0, - "amountRefunded": { - "value": "0.00", - "currency": "EUR" - }, - "quantityCanceled": 0, - "amountCanceled": { - "value": "0.00", - "currency": "EUR" - }, - "shippableQuantity": 0, - "refundableQuantity": 0, - "cancelableQuantity": 0, - "unitPrice": { - "value": "15.00", - "currency": "EUR" - }, - "vatRate": "0.00", - "vatAmount": { - "value": "0.00", - "currency": "EUR" - }, - "totalAmount": { - "value": "30.00", - "currency": "EUR" - }, - "createdAt": "2022-06-10T11:16:49+00:00" - } - ], - "_links": { - "self": { - "href": "https://api.mollie.com/v2/orders/ord_pbjz8x", - "type": "application/hal+json" - }, - "dashboard": { - "href": "https://www.mollie.com/dashboard/org_2816091/orders/ord_pbjz8x", - "type": "text/html" - }, - "checkout": { - "href": "https://www.mollie.com/checkout/order/xvb27g", - "type": "text/html" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/orders-api/get-order", - "type": "text/html" - } - } - }' - ) - ); - - $order = $this->apiClient->orderLines->updateMultiple( - 'ord_pbjz8x', - [ - [ - "operation" => "update", - "data" => [ - "id" => "odl_1.1l9vx0", - "name" => "New order line name", - ], - ], - [ - "operation" => "cancel", - "data" => [ - "id" => "odl_1.4hqjw6", - ], - ], - [ - "operation" => "add", - "data" => [ - "name" => "Adding new orderline", - "quantity" => 2, - "sku" => "12345679", - "totalAmount" => [ - "currency" => "EUR", - "value" => "30.00", - ], - "type" => "digital", - "unitPrice" => [ - "currency" => "EUR", - "value" => "15.00", - ], - "vatAmount" => [ - "currency" => "EUR", - "value" => "0.00", - ], - "vatRate" => "0.00", - ], - ], - ] - ); - - $this->assertInstanceOf(Order::class, $order); - $this->assertEquals('ord_pbjz8x', $order->id); - } -} diff --git a/tests/Mollie/API/Endpoints/OrderPaymentEndpointTest.php b/tests/Mollie/API/Endpoints/OrderPaymentEndpointTest.php deleted file mode 100644 index e3eb923e4..000000000 --- a/tests/Mollie/API/Endpoints/OrderPaymentEndpointTest.php +++ /dev/null @@ -1,285 +0,0 @@ -mockApiCall( - new Request( - "POST", - "/v2/orders/ord_stTC2WHAuS/payments", - [], - '{ - "method": "banktransfer", - "dueDate": "2018-12-21" - }' - ), - new Response( - 201, - [], - '{ - "resource": "payment", - "id": "tr_WDqYK6vllg", - "mode": "test", - "amount": { - "currency": "EUR", - "value": "698.00" - }, - "status": "open", - "description": "Order #1337 (Lego cars)", - "createdAt": "2018-12-01T17:09:02+00:00", - "method": "banktransfer", - "metadata": null, - "orderId": "ord_stTC2WHAuS", - "isCancelable": true, - "locale": "nl_NL", - "profileId": "pfl_URR55HPMGx", - "sequenceType": "oneoff", - "settlementAmount": { - "value": "698.00", - "currency": "EUR" - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_WDqYK6vllg", - "type": "application/hal+json" - }, - "order": { - "href": "https://api.mollie.com/v2/orders/ord_stTC2WHAuS", - "type": "application/hal+json" - }, - "checkout": { - "href": "https://www.mollie.com/paymentscreen/testmode/?method=banktransfer&token=fgnwdh", - "type": "text/html" - }, - "status": { - "href": "https://www.mollie.com/paymentscreen/banktransfer/status/fgnwdh", - "type": "text/html" - }, - "payOnline": { - "href": "https://www.mollie.com/paymentscreen/banktransfer/pay-online/fgnwdh", - "type": "text/html" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/orders-api/create-order-payment", - "type": "text/html" - } - } - }' - ) - ); - - $order = $this->getOrder('ord_stTC2WHAuS'); - - $payment = $order->createPayment([ - 'method' => 'banktransfer', - 'dueDate' => '2018-12-21', - ]); - - $this->assertNotNull($payment); - $this->assertInstanceOf(Payment::class, $payment); - $this->assertEquals('payment', $payment->resource); - $this->assertEquals('tr_WDqYK6vllg', $payment->id); - $this->assertEquals('test', $payment->mode); - $this->assertAmountObject(698, 'EUR', $payment->amount); - $this->assertEquals('open', $payment->status); - $this->assertEquals(PaymentStatus::STATUS_OPEN, $payment->status); - $this->assertEquals('Order #1337 (Lego cars)', $payment->description); - $this->assertEquals('2018-12-01T17:09:02+00:00', $payment->createdAt); - $this->assertEquals(PaymentMethod::BANKTRANSFER, $payment->method); - $this->assertNull($payment->metadata); - $this->assertEquals('ord_stTC2WHAuS', $payment->orderId); - $this->assertTrue($payment->isCancelable); - $this->assertEquals('nl_NL', $payment->locale); - $this->assertEquals('pfl_URR55HPMGx', $payment->profileId); - $this->assertEquals(SequenceType::SEQUENCETYPE_ONEOFF, $payment->sequenceType); - $this->assertAmountObject(698, 'EUR', $payment->settlementAmount); - - $this->assertLinkObject( - 'https://api.mollie.com/v2/payments/tr_WDqYK6vllg', - 'application/hal+json', - $payment->_links->self - ); - $this->assertLinkObject( - 'https://api.mollie.com/v2/orders/ord_stTC2WHAuS', - 'application/hal+json', - $payment->_links->order - ); - $this->assertLinkObject( - 'https://www.mollie.com/paymentscreen/testmode/?method=banktransfer&token=fgnwdh', - 'text/html', - $payment->_links->checkout - ); - $this->assertLinkObject( - 'https://www.mollie.com/paymentscreen/banktransfer/status/fgnwdh', - 'text/html', - $payment->_links->status - ); - $this->assertLinkObject( - 'https://www.mollie.com/paymentscreen/banktransfer/pay-online/fgnwdh', - 'text/html', - $payment->_links->payOnline - ); - $this->assertLinkObject( - 'https://docs.mollie.com/reference/v2/orders-api/create-order-payment', - 'text/html', - $payment->_links->documentation - ); - } - - protected function getOrder($id) - { - $orderJson = $this->getOrderResponseFixture($id); - - return $this->copy(json_decode($orderJson), new Order($this->apiClient)); - } - - protected function getOrderResponseFixture($order_id, $order_status = OrderStatus::STATUS_CREATED) - { - return str_replace( - "<>", - $order_id, - '{ - "resource": "order", - "id": "<>", - "profileId": "pfl_URR55HPMGx", - "amount": { - "value": "1027.99", - "currency": "EUR" - }, - "amountCaptured": { - "value": "0.00", - "currency": "EUR" - }, - "amountRefunded": { - "value": "0.00", - "currency": "EUR" - }, - "status": "' . $order_status . '", - "metadata": { - "order_id": "1337", - "description": "Lego cars" - }, - "consumerDateOfBirth": "1958-01-31", - "createdAt": "2018-08-02T09:29:56+00:00", - "mode": "live", - "billingAddress": { - "organizationName": "Organization Name LTD.", - "streetAndNumber": "Keizersgracht 313", - "postalCode": "1016 EE", - "city": "Amsterdam", - "country": "nl", - "givenName": "Luke", - "familyName": "Skywalker", - "email": "luke@skywalker.com" - }, - "shippingAddress": { - "organizationName": "Organization Name LTD.", - "streetAndNumber": "Keizersgracht 313", - "postalCode": "1016 EE", - "city": "Amsterdam", - "country": "nl", - "givenName": "Luke", - "familyName": "Skywalker", - "email": "luke@skywalker.com" - }, - "orderNumber": "1337", - "locale": "nl_NL", - "method" : "klarnapaylater", - "isCancelable": true, - "redirectUrl": "https://example.org/redirect", - "webhookUrl": "https://example.org/webhook", - "lines": [ - { - "resource": "orderline", - "id": "odl_dgtxyl", - "orderId": "<>", - "name": "LEGO 42083 Bugatti Chiron", - "productUrl": "https://shop.lego.com/nl-NL/Bugatti-Chiron-42083", - "imageUrl": "https://sh-s7-live-s.legocdn.com/is/image//LEGO/42083_alt1?$main$", - "sku": "5702016116977", - "type": "physical", - "status": "created", - "isCancelable": true, - "quantity": 2, - "unitPrice": { - "value": "399.00", - "currency": "EUR" - }, - "vatRate": "21.00", - "vatAmount": { - "value": "121.14", - "currency": "EUR" - }, - "discountAmount": { - "value": "100.00", - "currency": "EUR" - }, - "totalAmount": { - "value": "698.00", - "currency": "EUR" - }, - "createdAt": "2018-08-02T09:29:56+00:00" - }, - { - "resource": "orderline", - "id": "odl_jp31jz", - "orderId": "<>", - "name": "LEGO 42056 Porsche 911 GT3 RS", - "productUrl": "https://shop.lego.com/nl-NL/Porsche-911-GT3-RS-42056", - "imageUrl": "https://sh-s7-live-s.legocdn.com/is/image/LEGO/42056?$PDPDefault$", - "sku": "5702015594028", - "type": "digital", - "status": "created", - "isCancelable": true, - "quantity": 1, - "unitPrice": { - "value": "329.99", - "currency": "EUR" - }, - "vatRate": "21.00", - "vatAmount": { - "value": "57.27", - "currency": "EUR" - }, - "totalAmount": { - "value": "329.99", - "currency": "EUR" - }, - "createdAt": "2018-08-02T09:29:56+00:00" - } - ], - "_links": { - "self": { - "href": "https://api.mollie.com/v2/orders/<>", - "type": "application/hal+json" - }, - "checkout": { - "href": "https://www.mollie.com/payscreen/select-method/7UhSN1zuXS", - "type": "text/html" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/orders-api/get-order", - "type": "text/html" - } - } - }' - ); - } -} diff --git a/tests/Mollie/API/Endpoints/OrderRefundEndpointTest.php b/tests/Mollie/API/Endpoints/OrderRefundEndpointTest.php deleted file mode 100644 index 87819fb0c..000000000 --- a/tests/Mollie/API/Endpoints/OrderRefundEndpointTest.php +++ /dev/null @@ -1,427 +0,0 @@ -mockApiCall( - new Request( - "POST", - "/v2/orders/ord_stTC2WHAuS/refunds", - [], - '{ - "lines": [ - { - "id": "odl_dgtxyl", - "quantity": 1 - } - ] - }' - ), - new Response( - 201, - [], - $this->getOrderRefundResponseFixture('re_4qqhO89gsT', 'ord_stTC2WHAuS') - ) - ); - - $order = $this->getOrder('ord_stTC2WHAuS'); - - $refund = $order->refund([ - 'lines' => [ - [ - 'id' => 'odl_dgtxyl', - 'quantity' => 1, - ], - ], - ]); - - $this->assertOrderRefund($refund, 're_4qqhO89gsT'); - } - - public function testCreateCompleteOrderRefund() - { - $this->mockApiCall( - new Request( - "POST", - "/v2/orders/ord_stTC2WHAuS/refunds", - [], - '{ - "lines": [] - }' - ), - new Response( - 201, - [], - $this->getOrderRefundResponseFixture('re_4qqhO89gsT', 'ord_stTC2WHAuS') - ) - ); - - $order = $this->getOrder('ord_stTC2WHAuS'); - - $refund = $order->refundAll(); - - $this->assertOrderRefund($refund, 're_4qqhO89gsT'); - } - - public function testListOrderRefunds() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/orders/ord_stTC2WHAuS/refunds" - ), - new Response( - 200, - [], - '{ - "count": 1, - "_embedded": { - "refunds": [ - { - "resource": "refund", - "id": "re_4qqhO89gsT", - "amount": { - "currency": "EUR", - "value": "698.00" - }, - "status": "pending", - "createdAt": "2018-03-19T12:33:37+00:00", - "description": "Item not in stock, refunding", - "paymentId": "tr_WDqYK6vllg", - "orderId": "ord_pbjz8x", - "lines": [ - { - "resource": "orderline", - "id": "odl_dgtxyl", - "orderId": "ord_pbjz8x", - "name": "LEGO 42083 Bugatti Chiron", - "productUrl": "https://shop.lego.com/nl-NL/Bugatti-Chiron-42083", - "imageUrl": "https://sh-s7-live-s.legocdn.com/is/image//LEGO/42083_alt1?$main$", - "sku": "5702016116977", - "type": "physical", - "status": "refunded", - "quantity": 2, - "unitPrice": { - "value": "399.00", - "currency": "EUR" - }, - "vatRate": "21.00", - "vatAmount": { - "value": "121.14", - "currency": "EUR" - }, - "discountAmount": { - "value": "100.00", - "currency": "EUR" - }, - "totalAmount": { - "value": "698.00", - "currency": "EUR" - }, - "createdAt": "2018-08-02T09:29:56+00:00" - } - ], - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_WDqYK6vllg/refunds/re_4qqhO89gsT", - "type": "application/hal+json" - }, - "payment": { - "href": "https://api.mollie.com/v2/payments/tr_WDqYK6vllg", - "type": "application/hal+json" - }, - "order": { - "href": "https://api.mollie.com/v2/orders/ord_pbjz8x", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/refunds-api/get-refund", - "type": "text/html" - } - } - } - ] - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_7UhSN1zuXS/refunds?limit=5", - "type": "application/hal+json" - }, - "previous": null, - "next": { - "href": "https://api.mollie.com/v2/payments/tr_7UhSN1zuXS/refunds?from=re_APBiGPH2vV&limit=5", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/orders-api/list-order-refunds", - "type": "text/html" - } - } - }' - ) - ); - - $order = $this->getOrder('ord_stTC2WHAuS'); - - $refunds = $order->refunds(); - - $this->assertInstanceOf(RefundCollection::class, $refunds); - $this->assertEquals(1, $refunds->count); - $this->assertCount(1, $refunds); - - $this->assertOrderRefund($refunds[0], 're_4qqhO89gsT'); - } - - protected function assertOrderRefund($refund, $refund_id, $refund_status = RefundStatus::STATUS_PENDING) - { - $this->assertInstanceOf(Refund::class, $refund); - $this->assertEquals($refund_id, $refund->id); - $this->assertAmountObject('698.00', 'EUR', $refund->amount); - - $this->assertEquals($refund_status, $refund->status); - $this->assertEquals("2018-03-19T12:33:37+00:00", $refund->createdAt); - $this->assertEquals("Item not in stock, refunding", $refund->description); - $this->assertEquals("tr_WDqYK6vllg", $refund->paymentId); - - $this->assertLinkObject( - "https://api.mollie.com/v2/payments/tr_WDqYK6vllg/refunds/{$refund_id}", - 'application/hal+json', - $refund->_links->self - ); - - $this->assertLinkObject( - 'https://docs.mollie.com/reference/v2/refunds-api/get-refund', - 'text/html', - $refund->_links->documentation - ); - } - - protected function getOrderRefundResponseFixture($refund_id, $order_id) - { - return str_replace( - ["<>", "<>"], - [$refund_id, $order_id], - '{ - "resource": "refund", - "id": "<>", - "amount": { - "currency": "EUR", - "value": "698.00" - }, - "status": "pending", - "createdAt": "2018-03-19T12:33:37+00:00", - "description": "Item not in stock, refunding", - "paymentId": "tr_WDqYK6vllg", - "orderId": "<>", - "lines": [ - { - "resource": "orderline", - "id": "odl_dgtxyl", - "orderId": "<>", - "name": "LEGO 42083 Bugatti Chiron", - "productUrl": "https://shop.lego.com/nl-NL/Bugatti-Chiron-42083", - "imageUrl": "https://sh-s7-live-s.legocdn.com/is/image//LEGO/42083_alt1?$main$", - "sku": "5702016116977", - "type": "physical", - "status": "refunded", - "quantity": 2, - "unitPrice": { - "value": "399.00", - "currency": "EUR" - }, - "vatRate": "21.00", - "vatAmount": { - "value": "121.14", - "currency": "EUR" - }, - "discountAmount": { - "value": "100.00", - "currency": "EUR" - }, - "totalAmount": { - "value": "698.00", - "currency": "EUR" - }, - "createdAt": "2018-08-02T09:29:56+00:00" - } - ], - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_WDqYK6vllg/refunds/<>", - "type": "application/hal+json" - }, - "payment": { - "href": "https://api.mollie.com/v2/payments/tr_WDqYK6vllg", - "type": "application/hal+json" - }, - "order": { - "href": "https://api.mollie.com/v2/orders/<>", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/refunds-api/get-refund", - "type": "text/html" - } - } - }' - ); - } - - protected function getOrder($id) - { - $orderJson = $this->getOrderResponseFixture($id); - - return $this->copy(json_decode($orderJson), new Order($this->apiClient)); - } - - protected function getOrderResponseFixture($order_id, $order_status = OrderStatus::STATUS_CREATED) - { - return str_replace( - "<>", - $order_id, - '{ - "resource": "order", - "id": "<>", - "profileId": "pfl_URR55HPMGx", - "amount": { - "value": "1027.99", - "currency": "EUR" - }, - "amountCaptured": { - "value": "0.00", - "currency": "EUR" - }, - "amountRefunded": { - "value": "0.00", - "currency": "EUR" - }, - "status": "' . $order_status . '", - "metadata": { - "order_id": "1337", - "description": "Lego cars" - }, - "consumerDateOfBirth": "1958-01-31", - "createdAt": "2018-08-02T09:29:56+00:00", - "mode": "live", - "billingAddress": { - "streetAndNumber": "Keizersgracht 313", - "postalCode": "1016 EE", - "city": "Amsterdam", - "country": "nl", - "givenName": "Luke", - "familyName": "Skywalker", - "email": "luke@skywalker.com" - }, - "shippingAddress": { - "streetAndNumber": "Keizersgracht 313", - "postalCode": "1016 EE", - "city": "Amsterdam", - "country": "nl", - "givenName": "Luke", - "familyName": "Skywalker", - "email": "luke@skywalker.com" - }, - "orderNumber": "1337", - "locale": "nl_NL", - "method" : "klarnapaylater", - "isCancelable": true, - "redirectUrl": "https://example.org/redirect", - "webhookUrl": "https://example.org/webhook", - "lines": [ - { - "resource": "orderline", - "id": "odl_dgtxyl", - "orderId": "<>", - "name": "LEGO 42083 Bugatti Chiron", - "productUrl": "https://shop.lego.com/nl-NL/Bugatti-Chiron-42083", - "imageUrl": "https://sh-s7-live-s.legocdn.com/is/image//LEGO/42083_alt1?$main$", - "sku": "5702016116977", - "type": "physical", - "status": "created", - "isCancelable": true, - "quantity": 2, - "unitPrice": { - "value": "399.00", - "currency": "EUR" - }, - "vatRate": "21.00", - "vatAmount": { - "value": "121.14", - "currency": "EUR" - }, - "discountAmount": { - "value": "100.00", - "currency": "EUR" - }, - "totalAmount": { - "value": "698.00", - "currency": "EUR" - }, - "createdAt": "2018-08-02T09:29:56+00:00" - }, - { - "resource": "orderline", - "id": "odl_jp31jz", - "orderId": "<>", - "name": "LEGO 42056 Porsche 911 GT3 RS", - "productUrl": "https://shop.lego.com/nl-NL/Porsche-911-GT3-RS-42056", - "imageUrl": "https://sh-s7-live-s.legocdn.com/is/image/LEGO/42056?$PDPDefault$", - "sku": "5702015594028", - "type": "digital", - "status": "created", - "isCancelable": true, - "quantity": 1, - "unitPrice": { - "value": "329.99", - "currency": "EUR" - }, - "vatRate": "21.00", - "vatAmount": { - "value": "57.27", - "currency": "EUR" - }, - "totalAmount": { - "value": "329.99", - "currency": "EUR" - }, - "createdAt": "2018-08-02T09:29:56+00:00" - } - ], - "_links": { - "refunds": { - "href": "https://api.mollie.com/v2/orders/<>/refunds", - "type": "application/hal+json" - }, - "self": { - "href": "https://api.mollie.com/v2/orders/<>", - "type": "application/hal+json" - }, - "checkout": { - "href": "https://www.mollie.com/payscreen/select-method/7UhSN1zuXS", - "type": "text/html" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/orders-api/get-order", - "type": "text/html" - } - } - }' - ); - } -} diff --git a/tests/Mollie/API/Endpoints/OrganizationEndpointTest.php b/tests/Mollie/API/Endpoints/OrganizationEndpointTest.php deleted file mode 100644 index 21cb3f07b..000000000 --- a/tests/Mollie/API/Endpoints/OrganizationEndpointTest.php +++ /dev/null @@ -1,125 +0,0 @@ -mockApiCall( - new Request("GET", "/v2/organizations/org_12345678"), - new Response( - 200, - [], - '{ - "resource": "organization", - "id": "org_12345678", - "name": "Mollie B.V.", - "email": "info@mollie.com", - "locale": "nl_NL", - "address": { - "streetAndNumber": "Keizersgracht 313", - "postalCode": "1016 EE", - "city": "Amsterdam", - "country": "NL" - }, - "registrationNumber": "30204462", - "vatNumber": "NL815839091B01", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/organizations/org_12345678", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/organizations-api/get-organization", - "type": "text/html" - } - } - }' - ) - ); - - $organization = $this->apiClient->organizations->get('org_12345678'); - - $this->assertOrganization($organization); - } - - public function testGetCurrentOrganization() - { - $this->mockApiCall( - new Request("GET", "/v2/organizations/me"), - new Response( - 200, - [], - '{ - "resource": "organization", - "id": "org_12345678", - "name": "Mollie B.V.", - "email": "info@mollie.com", - "locale": "nl_NL", - "address": { - "streetAndNumber": "Keizersgracht 313", - "postalCode": "1016 EE", - "city": "Amsterdam", - "country": "NL" - }, - "registrationNumber": "30204462", - "vatNumber": "NL815839091B01", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/organizations/org_12345678", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/organizations-api/get-organization", - "type": "text/html" - } - } - }' - ) - ); - - $organization = $this->apiClient->organizations->current(); - - $this->assertOrganization($organization); - } - - protected function assertOrganization($organization) - { - $this->assertInstanceOf(Organization::class, $organization); - - $this->assertEquals('org_12345678', $organization->id); - $this->assertEquals('Mollie B.V.', $organization->name); - $this->assertEquals('info@mollie.com', $organization->email); - $this->assertEquals('nl_NL', $organization->locale); - - $this->assertEquals((object) [ - 'streetAndNumber' => 'Keizersgracht 313', - 'postalCode' => '1016 EE', - 'city' => 'Amsterdam', - 'country' => 'NL', - ], $organization->address); - - $this->assertEquals('30204462', $organization->registrationNumber); - $this->assertEquals('NL815839091B01', $organization->vatNumber); - - $this->assertLinkObject( - 'https://api.mollie.com/v2/organizations/org_12345678', - 'application/hal+json', - $organization->_links->self - ); - - $this->assertLinkObject( - 'https://docs.mollie.com/reference/v2/organizations-api/get-organization', - 'text/html', - $organization->_links->documentation - ); - } -} diff --git a/tests/Mollie/API/Endpoints/OrganizationPartnerEndpointTest.php b/tests/Mollie/API/Endpoints/OrganizationPartnerEndpointTest.php deleted file mode 100644 index 6a9c9d5e1..000000000 --- a/tests/Mollie/API/Endpoints/OrganizationPartnerEndpointTest.php +++ /dev/null @@ -1,58 +0,0 @@ -mockApiCall( - new Request('GET', '/v2/organizations/me/partner'), - new Response( - 200, - [], - '{ - "resource": "partner", - "partnerType": "signuplink", - "partnerContractSignedAt": "2018-03-20T13:13:37+00:00", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/organizations/me/partner", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/organizations-api/get-partner", - "type": "text/html" - }, - "signuplink": { - "href": "https://www.mollie.com/dashboard/signup/myCode?lang=en", - "type": "text/html" - } - } - }' - ) - ); - - $partner = $this->apiClient->organizationPartners->get(); - - $this->assertInstanceOf(Partner::class, $partner); - $this->assertEquals("partner", $partner->resource); - $this->assertEquals("signuplink", $partner->partnerType); - $this->assertEquals("2018-03-20T13:13:37+00:00", $partner->partnerContractSignedAt); - - $selfLink = (object)['href' => 'https://api.mollie.com/v2/organizations/me/partner', 'type' => 'application/hal+json']; - $this->assertEquals($selfLink, $partner->_links->self); - - $signUpLink = (object)['href' => 'https://www.mollie.com/dashboard/signup/myCode?lang=en', 'type' => 'text/html']; - $this->assertEquals($signUpLink, $partner->_links->signuplink); - - $documentationLink = (object)['href' => 'https://docs.mollie.com/reference/v2/organizations-api/get-partner', 'type' => 'text/html']; - $this->assertEquals($documentationLink, $partner->_links->documentation); - } -} diff --git a/tests/Mollie/API/Endpoints/PaymentCaptureEndpointTest.php b/tests/Mollie/API/Endpoints/PaymentCaptureEndpointTest.php deleted file mode 100644 index ce41a62eb..000000000 --- a/tests/Mollie/API/Endpoints/PaymentCaptureEndpointTest.php +++ /dev/null @@ -1,311 +0,0 @@ -mockApiCall( - new Request( - 'POST', - '/v2/payments/tr_WDqYK6vllg/captures' - ), - new Response( - 201, - [], - $this->getCaptureFixture('tr_WDqYK6vllg', 'cpt_4qqhO89gsT') - ) - ); - - $capture = $this->apiClient->paymentCaptures->createFor( - $this->getPayment('tr_WDqYK6vllg'), - [ - 'amount' => [ - "value" => "1027.99", - "currency" => "EUR", - ], - ] - ); - - $this->assertCapture($capture); - } - - public function testGetCaptureForPaymentResource() - { - $this->mockApiCall( - new Request( - 'GET', - '/v2/payments/tr_WDqYK6vllg/captures/cpt_4qqhO89gsT' - ), - new Response( - 200, - [], - $this->getCaptureFixture('tr_WDqYK6vllg', 'cpt_4qqhO89gsT') - ) - ); - - $capture = $this->apiClient->paymentCaptures->getFor( - $this->getPayment('tr_WDqYK6vllg'), - 'cpt_4qqhO89gsT' - ); - - $this->assertCapture($capture); - } - - public function testGetCaptureOnPaymentResource() - { - $this->mockApiCall( - new Request( - 'GET', - '/v2/payments/tr_WDqYK6vllg/captures/cpt_4qqhO89gsT' - ), - new Response( - 200, - [], - $this->getCaptureFixture('tr_WDqYK6vllg', 'cpt_4qqhO89gsT') - ) - ); - - $capture = $this->getPayment('tr_WDqYK6vllg')->getCapture('cpt_4qqhO89gsT'); - - $this->assertCapture($capture); - } - - public function testListCapturesOnPaymentResource() - { - $this->mockApiCall( - new Request( - 'GET', - '/v2/payments/tr_WDqYK6vllg/captures' - ), - new Response( - 200, - [], - '{ - "_embedded": { - "captures": [ - ' . $this->getCaptureFixture('tr_WDqYK6vllg', 'cpt_4qqhO89gsT') . ' - ] - }, - "count": 1, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/captures-api/list-captures", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.dev/v2/payments/tr_WDqYK6vllg/captures?limit=50", - "type": "application/hal+json" - }, - "previous": null, - "next": null - } - }' - ) - ); - - $captures = $this->getPayment('tr_WDqYK6vllg')->captures(); - - $this->assertEquals(1, $captures->count); - - $this->assertLinkObject( - 'https://docs.mollie.com/reference/v2/captures-api/list-captures', - 'text/html', - $captures->_links->documentation - ); - - $this->assertLinkObject( - 'https://api.mollie.dev/v2/payments/tr_WDqYK6vllg/captures?limit=50', - 'application/hal+json', - $captures->_links->self - ); - - $this->assertNull($captures->_links->previous); - $this->assertNull($captures->_links->next); - - $this->assertCapture($captures[0]); - } - - protected function assertCapture($capture) - { - $this->assertInstanceOf(Capture::class, $capture); - - $this->assertEquals('capture', $capture->resource); - $this->assertEquals('cpt_4qqhO89gsT', $capture->id); - $this->assertEquals('live', $capture->mode); - $this->assertEquals('tr_WDqYK6vllg', $capture->paymentId); - $this->assertEquals('shp_3wmsgCJN4U', $capture->shipmentId); - $this->assertEquals('stl_jDk30akdN', $capture->settlementId); - - $this->assertAmountObject('1027.99', 'EUR', $capture->amount); - $this->assertAmountObject('399.00', 'EUR', $capture->settlementAmount); - - $this->assertEquals('2018-08-02T09:29:56+00:00', $capture->createdAt); - - $this->assertLinkObject( - 'https://api.mollie.com/v2/payments/tr_WDqYK6vllg/captures/cpt_4qqhO89gsT', - 'application/hal+json', - $capture->_links->self - ); - - $this->assertLinkObject( - 'https://api.mollie.com/v2/payments/tr_WDqYK6vllg', - 'application/hal+json', - $capture->_links->payment - ); - - $this->assertLinkObject( - 'https://api.mollie.com/v2/orders/ord_8wmqcHMN4U/shipments/shp_3wmsgCJN4U', - 'application/hal+json', - $capture->_links->shipment - ); - - $this->assertLinkObject( - 'https://api.mollie.com/v2/settlements/stl_jDk30akdN', - 'application/hal+json', - $capture->_links->settlement - ); - - $this->assertLinkObject( - 'https://docs.mollie.com/reference/v2/captures-api/get-capture', - 'text/html', - $capture->_links->documentation - ); - } - - protected function getCaptureFixture( - $payment_id = 'tr_WDqYK6vllg', - $capture_id = 'cpt_4qqhO89gsT' - ) { - return str_replace( - [ - '<>', - '<>', - ], - [ - $payment_id, - $capture_id, - ], - '{ - "resource": "capture", - "id": "<>", - "mode": "live", - "amount": { - "value": "1027.99", - "currency": "EUR" - }, - "settlementAmount": { - "value": "399.00", - "currency": "EUR" - }, - "paymentId": "<>", - "shipmentId": "shp_3wmsgCJN4U", - "settlementId": "stl_jDk30akdN", - "createdAt": "2018-08-02T09:29:56+00:00", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/<>/captures/<>", - "type": "application/hal+json" - }, - "payment": { - "href": "https://api.mollie.com/v2/payments/<>", - "type": "application/hal+json" - }, - "shipment": { - "href": "https://api.mollie.com/v2/orders/ord_8wmqcHMN4U/shipments/shp_3wmsgCJN4U", - "type": "application/hal+json" - }, - "settlement": { - "href": "https://api.mollie.com/v2/settlements/stl_jDk30akdN", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/captures-api/get-capture", - "type": "text/html" - } - } - }' - ); - } - - /** - * @return Payment - */ - protected function getPayment($payment_id = 'tr_44aKxzEbr8') - { - $paymentJson = '{ - "resource":"payment", - "id":"<>", - "mode":"test", - "createdAt":"2018-03-19T12:17:57+00:00", - "amount":{ - "value":"20.00", - "currency":"EUR" - }, - "description":"My first API payment", - "method":"ideal", - "metadata":{ - "order_id":1234 - }, - "status":"paid", - "paidAt":"2018-03-19T12:18:35+00:00", - "amountRefunded":{ - "value":"0.00", - "currency":"EUR" - }, - "amountRemaining":{ - "value":"20.00", - "currency":"EUR" - }, - "details":{ - "consumerName":"T. TEST", - "consumerAccount":"NL17RABO0213698412", - "consumerBic":"TESTNL99" - }, - "locale":"nl_NL", - "countryCode":"NL", - "profileId":"pfl_2A1gacu42V", - "sequenceType":"oneoff", - "redirectUrl":"https://example.org/redirect", - "webhookUrl":"https://example.org/webhook", - "settlementAmount":{ - "value":"20.00", - "currency":"EUR" - }, - "_links":{ - "self":{ - "href":"https://api.mollie.com/v2/payments/<>", - "type":"application/hal+json" - }, - "documentation":{ - "href":"https://docs.mollie.com/reference/v2/payments-api/get-payment", - "type":"text/html" - }, - "refunds":{ - "href":"https://api.mollie.com/v2/payments/<>/refunds", - "type":"application/hal+json" - }, - "captures":{ - "href":"https://api.mollie.com/v2/payments/<>/captures", - "type":"application/hal+json" - } - } - }'; - - $paymentJson = str_replace('<>', $payment_id, $paymentJson); - - return $this->copy(json_decode($paymentJson), new Payment($this->apiClient)); - } -} diff --git a/tests/Mollie/API/Endpoints/PaymentChargebackEndpointTest.php b/tests/Mollie/API/Endpoints/PaymentChargebackEndpointTest.php deleted file mode 100644 index b1d71199d..000000000 --- a/tests/Mollie/API/Endpoints/PaymentChargebackEndpointTest.php +++ /dev/null @@ -1,403 +0,0 @@ -mockApiCall( - new Request( - "GET", - "/v2/payments/tr_44aKxzEbr8/chargebacks" - ), - new Response( - 200, - [], - '{ - "_embedded":{ - "chargebacks":[ - { - "resource":"chargeback", - "id":"chb_n9z0tp", - "amount":{ - "value":"-13.00", - "currency":"EUR" - }, - "createdAt":"2018-03-28T11:44:32+00:00", - "paymentId":"tr_44aKxzEbr8", - "settlementAmount":{ - "value":"-13.00", - "currency":"EUR" - }, - "_links":{ - "self":{ - "href":"https://api.mollie.com/v2/payments/tr_44aKxzEbr8/chargebacks/chb_n9z0tp", - "type":"application/hal+json" - }, - "payment":{ - "href":"https://api.mollie.com/v2/payments/tr_44aKxzEbr8", - "type":"application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/chargebacks-api/get-chargeback", - "type": "text/html" - } - } - }, - { - "resource":"chargeback", - "id":"chb_6cqlwf", - "amount":{ - "value":"-0.37", - "currency":"EUR" - }, - "createdAt":"2018-03-28T11:44:32+00:00", - "paymentId":"tr_44aKxzEbr8", - "settlementAmount":{ - "value":"-0.37", - "currency":"EUR" - }, - "_links":{ - "self":{ - "href":"https://api.mollie.com/v2/payments/tr_44aKxzEbr8/chargebacks/chb_6cqlwf", - "type":"application/hal+json" - }, - "payment":{ - "href":"https://api.mollie.com/v2/payments/tr_44aKxzEbr8", - "type":"application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/chargebacks-api/get-chargeback", - "type": "text/html" - } - } - } - ] - }, - "_links":{ - "documentation":{ - "href":"https://docs.mollie.com/reference/v2/chargebacks-api/list-chargebacks", - "type":"text/html" - }, - "self":{ - "href":"https://api.mollie.com/v2/payments/tr_44aKxzEbr8/chargebacks", - "type":"application/hal+json" - } - }, - "count": 2 - }' - ) - ); - - $chargebacks = $this->getPayment()->chargebacks(); - - $this->assertInstanceOf(ChargebackCollection::class, $chargebacks); - $this->assertEquals(2, $chargebacks->count); - $this->assertCount(2, $chargebacks); - - $this->assertLinkObject( - "https://docs.mollie.com/reference/v2/chargebacks-api/list-chargebacks", - "text/html", - $chargebacks->_links->documentation - ); - - $this->assertLinkObject( - "https://api.mollie.com/v2/payments/tr_44aKxzEbr8/chargebacks", - "application/hal+json", - $chargebacks->_links->self - ); - - $this->assertChargeback($chargebacks[0], 'tr_44aKxzEbr8', 'chb_n9z0tp', "-13.00"); - $this->assertChargeback($chargebacks[1], 'tr_44aKxzEbr8', 'chb_6cqlwf', "-0.37"); - } - - public function testGetChargebackOnPaymentResource() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/payments/tr_44aKxzEbr8/chargebacks/chb_n9z0tp" - ), - new Response( - 200, - [], - '{ - "resource":"chargeback", - "id":"chb_n9z0tp", - "amount":{ - "value":"-13.00", - "currency":"EUR" - }, - "createdAt":"2018-03-28T11:44:32+00:00", - "paymentId":"tr_44aKxzEbr8", - "settlementAmount":{ - "value":"-13.00", - "currency":"EUR" - }, - "_links":{ - "self":{ - "href":"https://api.mollie.com/v2/payments/tr_44aKxzEbr8/chargebacks/chb_n9z0tp", - "type":"application/hal+json" - }, - "payment":{ - "href":"https://api.mollie.com/v2/payments/tr_44aKxzEbr8", - "type":"application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/chargebacks-api/get-chargeback", - "type": "text/html" - } - } - }' - ) - ); - - $chargeback = $this->getPayment()->getChargeback("chb_n9z0tp"); - - $this->assertChargeback($chargeback, 'tr_44aKxzEbr8', 'chb_n9z0tp', "-13.00"); - } - - public function testPaymentChargebacksListForIdPaymentChargebackEndpoint() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/payments/tr_44aKxzEbr8/chargebacks" - ), - new Response( - 200, - [], - '{ - "count": 3, - "_embedded": { - "chargebacks": [ - { - "resource": "chargeback", - "id": "chb_n9z0tp", - "amount": { - "currency": "EUR", - "value": "43.38" - }, - "settlementAmount": { - "currency": "EUR", - "value": "-35.07" - }, - "createdAt": "2018-03-14T17:00:52.0Z", - "reversedAt": null, - "paymentId": "tr_44aKxzEbr8", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_WDqYK6vllg/chargebacks/chb_n9z0tp", - "type": "application/hal+json" - }, - "payment": { - "href": "https://api.mollie.com/v2/payments/tr_WDqYK6vllg", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/chargebacks-api/get-payment-chargeback", - "type": "text/html" - } - } - }, - { }, - { } - ] - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_7UhSN1zuXS/chargebacks", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/chargebacks-api/list-payment-chargebacks", - "type": "text/html" - } - } - }' - ) - ); - - $chargebacks = $this->apiClient->paymentChargebacks->listForId('tr_44aKxzEbr8'); - - $this->assertInstanceOf(ChargebackCollection::class, $chargebacks); - $this->assertEquals($chargebacks[0]->id, 'chb_n9z0tp'); - $this->assertAmountObject('43.38', 'EUR', $chargebacks[0]->amount); - $this->assertEquals($chargebacks[0]->paymentId, 'tr_44aKxzEbr8'); - } - - public function testPaymentChargebacksListForPaymentChargebackEndpoint() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/payments/tr_44aKxzEbr8/chargebacks" - ), - new Response( - 200, - [], - '{ - "count": 3, - "_embedded": { - "chargebacks": [ - { - "resource": "chargeback", - "id": "chb_n9z0tp", - "amount": { - "currency": "USD", - "value": "43.38" - }, - "settlementAmount": { - "currency": "EUR", - "value": "-35.07" - }, - "createdAt": "2018-03-14T17:00:52.0Z", - "reversedAt": null, - "paymentId": "tr_44aKxzEbr8", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_WDqYK6vllg/chargebacks/chb_n9z0tp", - "type": "application/hal+json" - }, - "payment": { - "href": "https://api.mollie.com/v2/payments/tr_WDqYK6vllg", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/chargebacks-api/get-payment-chargeback", - "type": "text/html" - } - } - }, - { }, - { } - ] - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_7UhSN1zuXS/chargebacks", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/chargebacks-api/list-payment-chargebacks", - "type": "text/html" - } - } - }' - ) - ); - $payment = $this->getPayment(); - - $chargebacks = $this->apiClient->paymentChargebacks->listFor($payment); - - $this->assertInstanceOf(ChargebackCollection::class, $chargebacks); - $this->assertEquals($chargebacks[0]->id, 'chb_n9z0tp'); - $this->assertEquals($chargebacks[0]->paymentId, 'tr_44aKxzEbr8'); - } - - protected function assertChargeback($chargeback, $paymentId, $chargebackId, $amount) - { - $this->assertInstanceOf(Chargeback::class, $chargeback); - $this->assertEquals("chargeback", $chargeback->resource); - $this->assertEquals($chargebackId, $chargeback->id); - - $this->assertAmountObject($amount, "EUR", $chargeback->amount); - $this->assertAmountObject($amount, "EUR", $chargeback->settlementAmount); - - $this->assertEquals("2018-03-28T11:44:32+00:00", $chargeback->createdAt); - $this->assertEquals($paymentId, $chargeback->paymentId); - - $this->assertLinkObject( - "https://api.mollie.com/v2/payments/{$paymentId}/chargebacks/{$chargebackId}", - "application/hal+json", - $chargeback->_links->self - ); - - $this->assertLinkObject( - "https://api.mollie.com/v2/payments/{$paymentId}", - "application/hal+json", - $chargeback->_links->payment - ); - - $this->assertLinkObject( - "https://docs.mollie.com/reference/v2/chargebacks-api/get-chargeback", - "text/html", - $chargeback->_links->documentation - ); - } - - /** - * @return Payment - */ - protected function getPayment() - { - $paymentJson = '{ - "resource":"payment", - "id":"tr_44aKxzEbr8", - "mode":"test", - "createdAt":"2018-03-19T12:17:57+00:00", - "amount":{ - "value":"20.00", - "currency":"EUR" - }, - "description":"My first API payment", - "method":"ideal", - "metadata":{ - "order_id":1234 - }, - "status":"paid", - "paidAt":"2018-03-19T12:18:35+00:00", - "amountRefunded":{ - "value":"0.00", - "currency":"EUR" - }, - "amountRemaining":{ - "value":"20.00", - "currency":"EUR" - }, - "details":{ - "consumerName":"T. TEST", - "consumerAccount":"NL17RABO0213698412", - "consumerBic":"TESTNL99" - }, - "locale":"nl_NL", - "countryCode":"NL", - "profileId":"pfl_2A1gacu42V", - "sequenceType":"oneoff", - "redirectUrl":"https://example.org/redirect", - "webhookUrl":"https://example.org/webhook", - "settlementAmount":{ - "value":"20.00", - "currency":"EUR" - }, - "_links":{ - "self":{ - "href":"https://api.mollie.com/v2/payments/tr_44aKxzEbr8", - "type":"application/hal+json" - }, - "documentation":{ - "href":"https://docs.mollie.com/reference/v2/payments-api/get-payment", - "type":"text/html" - }, - "chargebacks":{ - "href":"https://api.mollie.com/v2/payments/tr_44aKxzEbr8/chargebacks", - "type":"application/hal+json" - } - } - }'; - - return $this->copy(json_decode($paymentJson), new Payment($this->apiClient)); - } -} diff --git a/tests/Mollie/API/Endpoints/PaymentEndpointTest.php b/tests/Mollie/API/Endpoints/PaymentEndpointTest.php deleted file mode 100644 index f742501d5..000000000 --- a/tests/Mollie/API/Endpoints/PaymentEndpointTest.php +++ /dev/null @@ -1,628 +0,0 @@ -mockApiCall( - new Request( - "POST", - "/v2/payments", - [], - '{ - "amount":{ - "value":"20.00", - "currency":"EUR" - }, - "description": "My first API payment", - "redirectUrl": "https://example.org/redirect", - "webhookUrl": "https://example.org/webhook", - "metadata": { - "order_id": "1234" - } - }' - ), - new Response( - 201, - [], - '{ - "resource":"payment", - "id":"tr_44aKxzEbr8", - "mode":"test", - "createdAt":"2018-03-13T14:02:29+00:00", - "amount":{ - "value":"20.00", - "currency":"EUR" - }, - "description":"My first API payment", - "method":null, - "metadata":{ - "order_id":"1234" - }, - "status":"open", - "isCancelable":false, - "expiresAt":"2018-03-13T14:17:29+00:00", - "details":null, - "profileId":"pfl_2A1gacu42V", - "sequenceType":"oneoff", - "redirectUrl":"https://example.org/redirect", - "webhookUrl":"https://example.org/webhook", - "_links":{ - "self":{ - "href":"https://api.mollie.com/v2/payments/tr_44aKxzEbr8", - "type":"application/hal+json" - }, - "checkout":{ - "href":"https://www.mollie.com/payscreen/select-method/44aKxzEbr8", - "type":"text/html" - }, - "documentation":{ - "href":"https://docs.mollie.com/reference/v2/payments-api/create-payment", - "type":"text/html" - } - } - }' - ) - ); - - $payment = $this->apiClient->payments->create([ - "amount" => [ - "currency" => "EUR", - "value" => "20.00", - ], - "description" => "My first API payment", - "redirectUrl" => "https://example.org/redirect", - "webhookUrl" => "https://example.org/webhook", - "metadata" => [ - "order_id" => "1234", - ], - ]); - - $this->assertInstanceOf(Payment::class, $payment); - $this->assertEquals('tr_44aKxzEbr8', $payment->id); - $this->assertEquals('test', $payment->mode); - $this->assertEquals("2018-03-13T14:02:29+00:00", $payment->createdAt); - - $amount = new Stdclass(); - $amount->value = '20.00'; - $amount->currency = "EUR"; - $this->assertEquals($amount, $payment->amount); - - $this->assertEquals('My first API payment', $payment->description); - $this->assertNull($payment->method); - $this->assertEquals((object)["order_id" => "1234"], $payment->metadata); - $this->assertEquals(PaymentStatus::STATUS_OPEN, $payment->status); - $this->assertFalse($payment->isCancelable); - $this->assertEquals("2018-03-13T14:17:29+00:00", $payment->expiresAt); - $this->assertNull($payment->details); - $this->assertEquals("pfl_2A1gacu42V", $payment->profileId); - $this->assertEquals(SequenceType::SEQUENCETYPE_ONEOFF, $payment->sequenceType); - $this->assertEquals("https://example.org/redirect", $payment->redirectUrl); - $this->assertEquals("https://example.org/webhook", $payment->webhookUrl); - - $selfLink = (object)["href" => "https://api.mollie.com/v2/payments/tr_44aKxzEbr8", "type" => "application/hal+json"]; - $this->assertEquals($selfLink, $payment->_links->self); - - $checkoutLink = (object)["href" => "https://www.mollie.com/payscreen/select-method/44aKxzEbr8", "type" => "text/html"]; - $this->assertEquals($checkoutLink, $payment->_links->checkout); - - $documentationLink = (object)["href" => "https://docs.mollie.com/reference/v2/payments-api/create-payment", "type" => "text/html"]; - $this->assertEquals($documentationLink, $payment->_links->documentation); - } - - public function testUpdatePayment() - { - $this->mockApiCall( - new Request( - "PATCH", - "/v2/payments/tr_7UhSN1zuXS", - [], - '{ - "description":"Order #98765", - "redirectUrl":"https://example.org/webshop/order/98765/", - "cancelUrl":"https://example.org/webshop/order/98765/canceled/", - "webhookUrl":"https://example.org/webshop/payments/webhook/", - "restrictPaymentMethodsToCountry": null, - "metadata":{ - "order_id":"98765" - }, - "dueDate":null, - "locale":null - }' - ), - new Response( - 200, - [], - '{ - "resource": "payment", - "id": "tr_7UhSN1zuXS", - "mode": "test", - "createdAt": "2018-03-20T09:13:37+00:00", - "amount": { - "value": "10.00", - "currency": "EUR" - }, - "description": "Order #98765", - "method": null, - "metadata": { - "order_id": "98765" - }, - "status": "open", - "isCancelable": false, - "expiresAt": "2018-03-20T09:28:37+00:00", - "details": null, - "profileId": "pfl_QkEhN94Ba", - "sequenceType": "oneoff", - "redirectUrl": "https://example.org/webshop/order/98765/", - "webhookUrl": "https://example.org/webshop/payments/webhook/", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_7UhSN1zuXS", - "type": "application/json" - }, - "checkout": { - "href": "https://www.mollie.com/payscreen/select-method/7UhSN1zuXS", - "type": "text/html" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/payments-api/update-payment", - "type": "text/html" - } - } - }' - ) - ); - - // Get Payment stub - $payment = new Payment($this->apiClient); - $payment->id = "tr_7UhSN1zuXS"; - $payment->_links = $this->createNamedLinkObject( - "self", - "https://api.mollie.com/v2/payments/tr_7UhSN1zuXS", - "application/json" - ); - - // Modify fields - $payment->description = "Order #98765"; - $payment->redirectUrl = "https://example.org/webshop/order/98765/"; - $payment->webhookUrl = "https://example.org/webshop/payments/webhook/"; - $payment->metadata = ["order_id" => "98765"]; - $payment->cancelUrl = "https://example.org/webshop/order/98765/canceled/"; - - $payment = $payment->update(); - - $this->assertEquals("payment", $payment->resource); - $this->assertEquals("tr_7UhSN1zuXS", $payment->id); - - $this->assertEquals("Order #98765", $payment->description); - $this->assertEquals("https://example.org/webshop/order/98765/", $payment->redirectUrl); - $this->assertEquals("https://example.org/webshop/payments/webhook/", $payment->webhookUrl); - $this->assertEquals((object) ["order_id" => "98765"], $payment->metadata); - $this->assertEquals("oneoff", $payment->sequenceType); - $this->assertEquals("pfl_QkEhN94Ba", $payment->profileId); - $this->assertNull($payment->details); - - $this->assertLinkObject( - "https://api.mollie.com/v2/payments/tr_7UhSN1zuXS", - "application/json", - $payment->_links->self - ); - - $this->assertLinkObject( - "https://www.mollie.com/payscreen/select-method/7UhSN1zuXS", - "text/html", - $payment->_links->checkout - ); - - $this->assertLinkObject( - "https://docs.mollie.com/reference/v2/payments-api/update-payment", - "text/html", - $payment->_links->documentation - ); - } - - public function testGetPayment() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/payments/tr_44aKxzEbr8?testmode=true", - [], - '' - ), - new Response( - 200, - [], - '{ - "resource":"payment", - "id":"tr_44aKxzEbr8", - "mode":"test", - "createdAt":"2018-03-13T14:02:29+00:00", - "amount":{ - "value":"20.00", - "currency":"EUR" - }, - "description":"My first API payment", - "method":"ideal", - "metadata":{ - "order_id":"1234" - }, - "status":"paid", - "paidAt":"2018-03-19T12:18:35+00:00", - "amountRefunded":{ - "value":"0.00", - "currency":"EUR" - }, - "amountRemaining":{ - "value":"20.00", - "currency":"EUR" - }, - "details":{ - "consumerName":"T. TEST", - "consumerAccount":"NL17RABO0213698412", - "consumerBic":"TESTNL99" - }, - "locale":"nl_NL", - "countryCode":"NL", - "profileId":"pfl_2A1gacu42V", - "sequenceType":"oneoff", - "redirectUrl":"https://example.org/redirect", - "webhookUrl":"https://example.org/webhook", - "settlementAmount":{ - "value":"20.00", - "currency":"EUR" - }, - "_links":{ - "self":{ - "href":"https://api.mollie.com/v2/payments/tr_44aKxzEbr8", - "type":"application/hal+json" - }, - "documentation":{ - "href":"https://docs.mollie.com/reference/v2/payments-api/get-payment", - "type":"text/html" - } - } - }' - ) - ); - - $payment = $this->apiClient->payments->get("tr_44aKxzEbr8", ["testmode" => true]); - - $this->assertInstanceOf(Payment::class, $payment); - $this->assertEquals('tr_44aKxzEbr8', $payment->id); - $this->assertEquals('test', $payment->mode); - $this->assertEquals("2018-03-13T14:02:29+00:00", $payment->createdAt); - - $amount = new Stdclass(); - $amount->value = '20.00'; - $amount->currency = "EUR"; - $this->assertEquals($amount, $payment->amount); - - $this->assertEquals('My first API payment', $payment->description); - $this->assertEquals("ideal", $payment->method); - $this->assertEquals((object)["order_id" => "1234"], $payment->metadata); - $this->assertEquals(PaymentStatus::STATUS_PAID, $payment->status); - - $amountRefunded = new Stdclass(); - $amountRefunded->value = '0.00'; - $amountRefunded->currency = "EUR"; - $this->assertEquals($amountRefunded, $payment->amountRefunded); - - $amountRemaining = new Stdclass(); - $amountRemaining->value = '20.00'; - $amountRemaining->currency = "EUR"; - $this->assertEquals($amountRemaining, $payment->amountRemaining); - - $details = (object)[ - 'consumerName' => 'T. TEST', - 'consumerAccount' => 'NL17RABO0213698412', - 'consumerBic' => 'TESTNL99', - ]; - - $this->assertEquals($details, $payment->details); - $this->assertEquals("pfl_2A1gacu42V", $payment->profileId); - $this->assertEquals(SequenceType::SEQUENCETYPE_ONEOFF, $payment->sequenceType); - $this->assertEquals("https://example.org/redirect", $payment->redirectUrl); - $this->assertEquals("https://example.org/webhook", $payment->webhookUrl); - - $selfLink = (object)["href" => "https://api.mollie.com/v2/payments/tr_44aKxzEbr8", "type" => "application/hal+json"]; - $this->assertEquals($selfLink, $payment->_links->self); - - $documentationLink = (object)["href" => "https://docs.mollie.com/reference/v2/payments-api/get-payment", "type" => "text/html"]; - $this->assertEquals($documentationLink, $payment->_links->documentation); - } - - public function testListPayment() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/payments?limit=3", - [], - '' - ), - new Response( - 200, - [], - '{ - "_embedded": { - "payments": [ - { - "resource": "payment", - "id": "tr_admNa2tFfa", - "mode": "test", - "createdAt": "2018-03-19T15:00:50+00:00", - "amount": { - "value": "100.00", - "currency": "EUR" - }, - "description": "Payment no 1", - "method": null, - "metadata": null, - "status": "open", - "isCancelable": false, - "expiresAt": "2018-03-19T15:15:50+00:00", - "details": null, - "locale": "nl_NL", - "profileId": "pfl_7N5qjbu42V", - "sequenceType": "oneoff", - "redirectUrl": "https://www.example.org/", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_admNa2tFfa", - "type": "application/hal+json" - }, - "checkout": { - "href": "https://www.mollie.com/payscreen/select-method/admNa2tFfa", - "type": "text/html" - } - } - }, - { - "resource": "payment", - "id": "tr_bcaLc7hFfa", - "mode": "test", - "createdAt": "2018-03-19T15:00:50+00:00", - "amount": { - "value": "100.00", - "currency": "EUR" - }, - "description": "Payment no 2", - "method": null, - "metadata": null, - "status": "open", - "isCancelable": false, - "expiresAt": "2018-03-19T15:15:50+00:00", - "details": null, - "locale": "nl_NL", - "profileId": "pfl_7N5qjbu42V", - "sequenceType": "oneoff", - "redirectUrl": "https://www.example.org/", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_bcaLc7hFfa", - "type": "application/hal+json" - }, - "checkout": { - "href": "https://www.mollie.com/payscreen/select-method/bcaLc7hFfa", - "type": "text/html" - } - } - }, - { - "resource": "payment", - "id": "tr_pslHy1tFfa", - "mode": "test", - "createdAt": "2018-03-19T15:00:50+00:00", - "amount": { - "value": "100.00", - "currency": "EUR" - }, - "description": "Payment no 3", - "method": null, - "metadata": null, - "status": "open", - "isCancelable": false, - "expiresAt": "2018-03-19T15:15:50+00:00", - "details": null, - "locale": "nl_NL", - "profileId": "pfl_7N5qjbu42V", - "sequenceType": "oneoff", - "redirectUrl": "https://www.example.org/", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_pslHy1tFfa", - "type": "application/hal+json" - }, - "checkout": { - "href": "https://www.mollie.com/payscreen/select-method/pslHy1tFfa", - "type": "text/html" - } - } - } - ] - }, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/payments-api/list-payments", - "type": "text/html" - }, - "self": { - "href": "http://api.mollie.com/v2/payments?limit=3", - "type": "application/hal+json" - }, - "previous": null, - "next": { - "href": "http://api.mollie.com/v2/payments?from=tr_eW8f5kzUkF&limit=3", - "type": "application/hal+json" - } - }, - "count": 3 - }' - ) - ); - - $payments = $this->apiClient->payments->page(null, 3); - - $this->assertInstanceOf(PaymentCollection::class, $payments); - $this->assertEquals(3, $payments->count); - $this->assertEquals(3, count($payments)); - - $documentationLink = (object)["href" => "https://docs.mollie.com/reference/v2/payments-api/list-payments", "type" => "text/html"]; - $this->assertEquals($documentationLink, $payments->_links->documentation); - - $selfLink = (object)["href" => "http://api.mollie.com/v2/payments?limit=3", "type" => "application/hal+json"]; - $this->assertEquals($selfLink, $payments->_links->self); - - $this->assertNull($payments->_links->previous); - - $nextLink = (object)["href" => "http://api.mollie.com/v2/payments?from=tr_eW8f5kzUkF&limit=3", "type" => "application/hal+json"]; - $this->assertEquals($nextLink, $payments->_links->next); - } - - public function testIteratePayment() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/payments", - [], - '' - ), - new Response( - 200, - [], - '{ - "_embedded": { - "payments": [ - { - "resource": "payment", - "id": "tr_admNa2tFfa", - "mode": "test", - "createdAt": "2018-03-19T15:00:50+00:00", - "amount": { - "value": "100.00", - "currency": "EUR" - }, - "description": "Payment no 1", - "method": null, - "metadata": null, - "status": "open", - "isCancelable": false, - "expiresAt": "2018-03-19T15:15:50+00:00", - "details": null, - "locale": "nl_NL", - "profileId": "pfl_7N5qjbu42V", - "sequenceType": "oneoff", - "redirectUrl": "https://www.example.org/", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_admNa2tFfa", - "type": "application/hal+json" - }, - "checkout": { - "href": "https://www.mollie.com/payscreen/select-method/admNa2tFfa", - "type": "text/html" - } - } - }, - { - "resource": "payment", - "id": "tr_bcaLc7hFfa", - "mode": "test", - "createdAt": "2018-03-19T15:00:50+00:00", - "amount": { - "value": "100.00", - "currency": "EUR" - }, - "description": "Payment no 2", - "method": null, - "metadata": null, - "status": "open", - "isCancelable": false, - "expiresAt": "2018-03-19T15:15:50+00:00", - "details": null, - "locale": "nl_NL", - "profileId": "pfl_7N5qjbu42V", - "sequenceType": "oneoff", - "redirectUrl": "https://www.example.org/", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_bcaLc7hFfa", - "type": "application/hal+json" - }, - "checkout": { - "href": "https://www.mollie.com/payscreen/select-method/bcaLc7hFfa", - "type": "text/html" - } - } - }, - { - "resource": "payment", - "id": "tr_pslHy1tFfa", - "mode": "test", - "createdAt": "2018-03-19T15:00:50+00:00", - "amount": { - "value": "100.00", - "currency": "EUR" - }, - "description": "Payment no 3", - "method": null, - "metadata": null, - "status": "open", - "isCancelable": false, - "expiresAt": "2018-03-19T15:15:50+00:00", - "details": null, - "locale": "nl_NL", - "profileId": "pfl_7N5qjbu42V", - "sequenceType": "oneoff", - "redirectUrl": "https://www.example.org/", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_pslHy1tFfa", - "type": "application/hal+json" - }, - "checkout": { - "href": "https://www.mollie.com/payscreen/select-method/pslHy1tFfa", - "type": "text/html" - } - } - } - ] - }, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/payments-api/list-payments", - "type": "text/html" - }, - "self": { - "href": "http://api.mollie.com/v2/payments?limit=3", - "type": "application/hal+json" - }, - "previous": null, - "next": null - }, - "count": 3 - }' - ) - ); - - foreach ($this->apiClient->payments->iterator() as $payment) { - $this->assertInstanceOf(Payment::class, $payment); - $this->assertEquals("payment", $payment->resource); - } - } -} diff --git a/tests/Mollie/API/Endpoints/PaymentLinkEndpointTest.php b/tests/Mollie/API/Endpoints/PaymentLinkEndpointTest.php deleted file mode 100644 index db3c11cd9..000000000 --- a/tests/Mollie/API/Endpoints/PaymentLinkEndpointTest.php +++ /dev/null @@ -1,353 +0,0 @@ -mockApiCall( - new Request( - "GET", - "/v2/payment-links", - [], - '' - ), - new Response( - 200, - [], - '{ - "count": 1, - "_embedded": { - "payment_links": [ - { - "resource": "payment-link", - "id": "pl_4Y0eZitmBnQ6IDoMqZQKh", - "mode": "live", - "description": "Bicycle tires", - "amount": { - "currency": "EUR", - "value": "24.95" - }, - "archived": false, - "redirectUrl": "https://webshop.example.org/thanks", - "webhookUrl": "https://webshop.example.org/payment-links/webhook", - "profileId": "pfl_QkEhN94Ba", - "createdAt": "2021-03-20T09:29:56+00:00", - "expiresAt": "2023-06-06T11:00:00+00:00", - "_links": { - "self": { - "href": "...", - "type": "application/hal+json" - }, - "paymentLink": { - "href": "https://paymentlink.mollie.com/payment/4Y0eZitmBnQ6IDoMqZQKh", - "type": "text/html" - } - } - } - ] - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payment-links/", - "type": "application/hal+json" - }, - "previous": null, - "next": { - "href": "https://api.mollie.com/v2/payment-links?from=pl_ayGNzD4TYuQtUaxNyu8aH&limit=5", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/list-payment-links", - "type": "text/html" - } - } - }' - ) - ); - - $paymentLinks = $this->apiClient->paymentLinks->page(); - $this->assertEquals(1, $paymentLinks->count()); - $this->assertEquals('pl_4Y0eZitmBnQ6IDoMqZQKh', $paymentLinks[0]->id); - // No need to test all attributes as these are mapped dynamically. - } - - /** @test */ - public function testIteratePaymentLinks() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/payment-links", - [], - '' - ), - new Response( - 200, - [], - '{ - "count": 1, - "_embedded": { - "payment_links": [ - { - "resource": "payment-link", - "id": "pl_4Y0eZitmBnQ6IDoMqZQKh", - "mode": "live", - "description": "Bicycle tires", - "amount": { - "currency": "EUR", - "value": "24.95" - }, - "archived": false, - "redirectUrl": "https://webshop.example.org/thanks", - "webhookUrl": "https://webshop.example.org/payment-links/webhook", - "profileId": "pfl_QkEhN94Ba", - "createdAt": "2021-03-20T09:29:56+00:00", - "expiresAt": "2023-06-06T11:00:00+00:00", - "_links": { - "self": { - "href": "...", - "type": "application/hal+json" - }, - "paymentLink": { - "href": "https://paymentlink.mollie.com/payment/4Y0eZitmBnQ6IDoMqZQKh", - "type": "text/html" - } - } - } - ] - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payment-links/", - "type": "application/hal+json" - }, - "previous": null, - "next": null, - "documentation": { - "href": "https://docs.mollie.com/reference/list-payment-links", - "type": "text/html" - } - } - }' - ) - ); - foreach ($this->apiClient->paymentLinks->iterator() as $paymentLink) { - $this->assertInstanceOf(PaymentLink::class, $paymentLink); - $this->assertEquals("payment-link", $paymentLink->resource); - // No need to test all attributes as these are mapped dynamically. - } - } - - /** @test */ - public function testGetPaymentLink() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/payment-links/pl_4Y0eZitmBnQ6IDoMqZQKh?testmode=true", - [], - '' - ), - new Response( - 200, - [], - '{ - "resource": "payment-link", - "id": "pl_4Y0eZitmBnQ6IDoMqZQKh", - "mode": "live", - "description": "Bicycle tires", - "amount": { - "currency": "EUR", - "value": "24.95" - }, - "archived": false, - "redirectUrl": "https://webshop.example.org/thanks", - "webhookUrl": "https://webshop.example.org/payment-links/webhook", - "profileId": "pfl_QkEhN94Ba", - "createdAt": "2021-03-20T09:29:56+00:00", - "expiresAt": "2023-06-06T11:00:00+00:00", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payment-links/pl_4Y0eZitmBnQ6IDoMqZQKh?testmode=true", - "type": "application/hal+json" - }, - "paymentLink": { - "href": "https://paymentlink.mollie.com/payment/4Y0eZitmBnQ6IDoMqZQKh", - "type": "text/html" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/get-payment-link", - "type": "text/html" - } - } - }' - ) - ); - - $paymentLink = $this->apiClient->paymentLinks->get("pl_4Y0eZitmBnQ6IDoMqZQKh", ["testmode" => true]); - $this->assertInstanceOf(PaymentLink::class, $paymentLink); - $this->assertEquals("payment-link", $paymentLink->resource); - $this->assertEquals("pl_4Y0eZitmBnQ6IDoMqZQKh", $paymentLink->id); - // No need to test all attributes as these are mapped dynamically. - } - - /** @test */ - public function testCreatePaymentLink() - { - $this->mockApiCall( - new Request( - "POST", - "/v2/payment-links", - [], - '{ - "description": "Bicycle tires", - "amount": { - "currency": "EUR", - "value": "24.95" - }, - "webhookUrl": "https://webshop.example.org/payment-links/webhook/", - "redirectUrl": "https://webshop.example.org/thanks", - "expiresAt": "2023-06-06T11:00:00+00:00" - }' - ), - new Response( - 201, - [], - '{ - "resource": "payment-link", - "id": "pl_4Y0eZitmBnQ6IDoMqZQKh", - "mode": "live", - "description": "Bicycle tires", - "amount": { - "currency": "EUR", - "value": "24.95" - }, - "archived": false, - "redirectUrl": "https://webshop.example.org/thanks", - "webhookUrl": "https://webshop.example.org/payment-links/webhook", - "profileId": "pfl_QkEhN94Ba", - "createdAt": "2021-03-20T09:29:56+00:00", - "expiresAt": "2023-06-06T11:00:00+00:00", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payment-links/pl_4Y0eZitmBnQ6IDoMqZQKh?testmode=true", - "type": "application/hal+json" - }, - "paymentLink": { - "href": "https://paymentlink.mollie.com/payment/4Y0eZitmBnQ6IDoMqZQKh", - "type": "text/html" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/create-payment-link", - "type": "text/html" - } - } - }' - ) - ); - - $paymentLink = $this->apiClient->paymentLinks->create([ - "description" => "Bicycle tires", - "amount" => [ - "currency" => "EUR", - "value" => "24.95", - ], - "webhookUrl" => "https://webshop.example.org/payment-links/webhook/", - "redirectUrl" => "https://webshop.example.org/thanks", - "expiresAt" => "2023-06-06T11:00:00+00:00", - ]); - - $this->assertInstanceOf(PaymentLink::class, $paymentLink); - $this->assertEquals('payment-link', $paymentLink->resource); - $this->assertEquals('pl_4Y0eZitmBnQ6IDoMqZQKh', $paymentLink->id); - // No need to test all attributes as these are mapped dynamically. - } - - /** @test */ - public function testUpdatePaymentLink() - { - $this->mockApiCall( - new Request( - "PATCH", - "/v2/payment-links/pl_4Y0eZitmBnQ6IDoMqZQKh", - [], - '{ - "description":"Bicycle tires", - "archived": true - }' - ), - new Response( - 200, - [], - '{ - "resource": "payment-link", - "id": "pl_4Y0eZitmBnQ6IDoMqZQKh", - "mode": "live", - "description": "Bicycle tires", - "amount": { - "currency": "EUR", - "value": "24.95" - }, - "archived": true, - "redirectUrl": "https://webshop.example.org/thanks", - "webhookUrl": "https://webshop.example.org/payment-links/webhook", - "profileId": "pfl_QkEhN94Ba", - "createdAt": "2021-03-20T09:29:56+00:00", - "expiresAt": "2023-06-06T11:00:00+00:00", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payment-links/pl_4Y0eZitmBnQ6IDoMqZQKh?testmode=true", - "type": "application/hal+json" - }, - "paymentLink": { - "href": "https://paymentlink.mollie.com/payment/4Y0eZitmBnQ6IDoMqZQKh", - "type": "text/html" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/update-payment-link", - "type": "text/html" - } - } - }' - ) - ); - - $paymentLink = $this->apiClient->paymentLinks->update('pl_4Y0eZitmBnQ6IDoMqZQKh', [ - 'description' => 'Bicycle tires', - 'archived' => true, - ]); - - $this->assertInstanceOf(PaymentLink::class, $paymentLink); - $paymentLink->resource = 'payment-link'; - $paymentLink->id = 'pl_4Y0eZitmBnQ6IDoMqZQKh'; - $paymentLink->archived = true; - // No need to test all attributes as these are mapped dynamically. - } - - /** @test */ - public function testDeletePaymentLink() - { - $this->mockApiCall( - new Request( - "DELETE", - "/v2/payment-links/pl_4Y0eZitmBnQ6IDoMqZQKh" - ), - new Response( - 204, - [], - null - ) - ); - - $this->assertNull($this->apiClient->paymentLinks->delete('pl_4Y0eZitmBnQ6IDoMqZQKh')); - } -} diff --git a/tests/Mollie/API/Endpoints/PaymentLinkPaymentEndpointTest.php b/tests/Mollie/API/Endpoints/PaymentLinkPaymentEndpointTest.php deleted file mode 100644 index 722f642c6..000000000 --- a/tests/Mollie/API/Endpoints/PaymentLinkPaymentEndpointTest.php +++ /dev/null @@ -1,90 +0,0 @@ -mockApiCall( - new Request( - "GET", - "/v2/payment-links/pl_4Y0eZitmBnQ6IDoMqZQKh/payments" - ), - new Response( - 200, - [], - '{ - "count": 1, - "_embedded": { - "payments": [ - { - "resource": "payment", - "id": "tr_7UhSN1zuXS", - "mode": "live", - "status": "open", - "isCancelable": false, - "amount": { - "value": "75.00", - "currency": "GBP" - }, - "description": "Order #12345", - "method": "ideal", - "metadata": null, - "details": null, - "profileId": "pfl_QkEhN94Ba", - "redirectUrl": "https://webshop.example.org/order/12345/", - "createdAt": "2024-02-12T11:58:35.0Z", - "expiresAt": "2024-02-12T12:13:35.0Z", - "_links": { - "self": { - "href": "...", - "type": "application/hal+json" - }, - "checkout": { - "href": "https://www.mollie.com/checkout/issuer/select/ideal/7UhSN1zuXS", - "type": "text/html" - }, - "dashboard": { - "href": "https://www.mollie.com/dashboard/org_12345678/payments/tr_7UhSN1zuXS", - "type": "text/html" - } - } - } - ] - }, - "_links": { - "self": { - "href": "...", - "type": "application/hal+json" - }, - "previous": null, - "next": { - "href": "https://api.mollie.com/v2/payment-links/pl_4Y0eZitmBnQ6IDoMqZQKh/payments?from=tr_SDkzMggpvx&limit=5", - "type": "application/hal+json" - }, - "documentation": { - "href": "...", - "type": "text/html" - } - } - }' - ) - ); - - $response = $this->apiClient->paymentLinkPayments->pageForId("pl_4Y0eZitmBnQ6IDoMqZQKh"); - - $this->assertInstanceOf(PaymentCollection::class, $response); - $this->assertInstanceOf(Payment::class, $response[0]); - $this->assertEquals($response[0]->id, "tr_7UhSN1zuXS"); - // Not necessary to test all fields... - } -} diff --git a/tests/Mollie/API/Endpoints/PaymentRefundEndpointTest.php b/tests/Mollie/API/Endpoints/PaymentRefundEndpointTest.php deleted file mode 100644 index e3b2eeddb..000000000 --- a/tests/Mollie/API/Endpoints/PaymentRefundEndpointTest.php +++ /dev/null @@ -1,602 +0,0 @@ -mockApiCall( - new Request( - "GET", - "/v2/payments/tr_44aKxzEbr8/refunds/re_PsAvxvLsnm" - ), - new Response( - 200, - [], - '{ - "resource":"refund", - "id":"re_PsAvxvLsnm", - "amount":{ - "value":"20.00", - "currency":"EUR" - }, - "status":"pending", - "createdAt":"2018-03-19T12:33:37+00:00", - "description":"My first API payment", - "paymentId":"tr_44aKxzEbr8", - "settlementAmount":{ - "value":"-20.00", - "currency":"EUR" - }, - "_links":{ - "self":{ - "href":"https://api.mollie.com/v2/payments/tr_Tgxm3amJBT/refunds/re_PmEtpvSsnm", - "type":"application/hal+json" - }, - "payment":{ - "href":"https://api.mollie.com/v2/payments/tr_44aKxzEbr8", - "type":"application/hal+json" - }, - "documentation":{ - "href":"https://docs.mollie.com/reference/v2/refunds-api/get-refund", - "type":"text/html" - } - } - }' - ) - ); - - $refund = $this->apiClient->paymentRefunds->getFor($this->getPayment(), "re_PsAvxvLsnm"); - - $this->assertInstanceOf(Refund::class, $refund); - $this->assertEquals("re_PsAvxvLsnm", $refund->id); - - $amount = new Stdclass(); - $amount->value = '20.00'; - $amount->currency = "EUR"; - $this->assertEquals($amount, $refund->amount); - - $this->assertEquals("pending", $refund->status); - $this->assertEquals("2018-03-19T12:33:37+00:00", $refund->createdAt); - $this->assertEquals("My first API payment", $refund->description); - $this->assertEquals("tr_44aKxzEbr8", $refund->paymentId); - - $amount = new Stdclass(); - $amount->value = '-20.00'; - $amount->currency = "EUR"; - $this->assertEquals($amount, $refund->settlementAmount); - - $selfLink = (object)["href" => "https://api.mollie.com/v2/payments/tr_Tgxm3amJBT/refunds/re_PmEtpvSsnm", "type" => "application/hal+json"]; - $this->assertEquals($selfLink, $refund->_links->self); - - $paymentLink = (object)["href" => "https://api.mollie.com/v2/payments/tr_44aKxzEbr8", "type" => "application/hal+json"]; - $this->assertEquals($paymentLink, $refund->_links->payment); - - $documentationLink = (object)["href" => "https://docs.mollie.com/reference/v2/refunds-api/get-refund", "type" => "text/html"]; - $this->assertEquals($documentationLink, $refund->_links->documentation); - } - - public function testCreateRefundForPaymentResource() - { - $this->mockApiCall( - new Request( - "POST", - "/v2/payments/tr_44aKxzEbr8/refunds" - ), - new Response( - 201, - [], - '{ - "resource": "refund", - "id": "re_4qqhO89gsT", - "amount": { - "currency": "EUR", - "value": "20.00" - }, - "status": "pending", - "createdAt": "2018-03-14T17:09:02.0Z", - "description": "Order #33", - "metadata": { - "bookkeeping_id": 12345 - }, - "paymentId": "tr_WDqYK6vllg", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_WDqYK6vllg/refunds/re_4qqhO89gsT", - "type": "application/hal+json" - }, - "payment": { - "href": "https://api.mollie.com/v2/payments/tr_WDqYK6vllg", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/refunds-api/create-payment-refund", - "type": "text/html" - } - } - }' - ) - ); - $payment = $this->getPayment(); - $refundData = [ - "amount" => [ - "currency" => "EUR", - "value" => "20.00", - ], - ]; - $refund = $this->apiClient->paymentRefunds->createFor($payment, $refundData); - - $this->assertInstanceOf(Refund::class, $refund); - $this->assertEquals("re_4qqhO89gsT", $refund->id); - - $amount = new Stdclass(); - $amount->value = '20.00'; - $amount->currency = "EUR"; - $this->assertEquals($amount, $refund->amount); - - $this->assertEquals("pending", $refund->status); - $this->assertEquals("2018-03-14T17:09:02.0Z", $refund->createdAt); - $this->assertEquals("Order #33", $refund->description); - $this->assertEquals("tr_WDqYK6vllg", $refund->paymentId); - - - $selfLink = (object)["href" => "https://api.mollie.com/v2/payments/tr_WDqYK6vllg/refunds/re_4qqhO89gsT", "type" => "application/hal+json"]; - $this->assertEquals($selfLink, $refund->_links->self); - - $paymentLink = (object)["href" => "https://api.mollie.com/v2/payments/tr_WDqYK6vllg", "type" => "application/hal+json"]; - $this->assertEquals($paymentLink, $refund->_links->payment); - - $documentationLink = (object)["href" => "https://docs.mollie.com/reference/v2/refunds-api/create-payment-refund", "type" => "text/html"]; - $this->assertEquals($documentationLink, $refund->_links->documentation); - } - - public function testGetRefundOnPaymentResource() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/payments/tr_44aKxzEbr8/refunds/re_PsAvxvLsnm" - ), - new Response( - 201, - [], - '{ - "resource":"refund", - "id":"re_PsAvxvLsnm", - "amount":{ - "value":"20.00", - "currency":"EUR" - }, - "status":"pending", - "createdAt":"2018-03-19T12:33:37+00:00", - "description":"My first API payment", - "paymentId":"tr_44aKxzEbr8", - "settlementAmount":{ - "value":"-20.00", - "currency":"EUR" - }, - "_links":{ - "self":{ - "href":"https://api.mollie.com/v2/payments/tr_Tgxm3amJBT/refunds/re_PmEtpvSsnm", - "type":"application/hal+json" - }, - "payment":{ - "href":"https://api.mollie.com/v2/payments/tr_44aKxzEbr8", - "type":"application/hal+json" - }, - "documentation":{ - "href":"https://docs.mollie.com/reference/v2/refunds-api/create-refund", - "type":"text/html" - } - } - }' - ) - ); - - $refund = $this->getPayment()->getRefund("re_PsAvxvLsnm"); - - $this->assertInstanceOf(Refund::class, $refund); - $this->assertEquals("re_PsAvxvLsnm", $refund->id); - - $amount = new Stdclass(); - $amount->value = '20.00'; - $amount->currency = "EUR"; - $this->assertEquals($amount, $refund->amount); - - $this->assertEquals("pending", $refund->status); - $this->assertEquals("2018-03-19T12:33:37+00:00", $refund->createdAt); - $this->assertEquals("My first API payment", $refund->description); - $this->assertEquals("tr_44aKxzEbr8", $refund->paymentId); - - $amount = new Stdclass(); - $amount->value = '-20.00'; - $amount->currency = "EUR"; - $this->assertEquals($amount, $refund->settlementAmount); - - $selfLink = (object)["href" => "https://api.mollie.com/v2/payments/tr_Tgxm3amJBT/refunds/re_PmEtpvSsnm", "type" => "application/hal+json"]; - $this->assertEquals($selfLink, $refund->_links->self); - - $paymentLink = (object)["href" => "https://api.mollie.com/v2/payments/tr_44aKxzEbr8", "type" => "application/hal+json"]; - $this->assertEquals($paymentLink, $refund->_links->payment); - - $documentationLink = (object)["href" => "https://docs.mollie.com/reference/v2/refunds-api/create-refund", "type" => "text/html"]; - $this->assertEquals($documentationLink, $refund->_links->documentation); - } - - public function testCreateRefund() - { - $this->mockApiCall( - new Request( - "POST", - "/v2/payments/tr_44aKxzEbr8/refunds", - [], - '{"amount":{"currency":"EUR","value":"20.00"}}' - ), - new Response( - 201, - [], - '{ - "resource":"refund", - "id":"re_PsAvxvLsnm", - "amount":{ - "value":"20.00", - "currency":"EUR" - }, - "status":"pending", - "createdAt":"2018-03-19T12:33:37+00:00", - "description":"My first API payment", - "paymentId":"tr_44aKxzEbr8", - "settlementAmount":{ - "value":"-20.00", - "currency":"EUR" - }, - "_links":{ - "self":{ - "href":"https://api.mollie.com/v2/payments/tr_Tgxm3amJBT/refunds/re_PmEtpvSsnm", - "type":"application/hal+json" - }, - "payment":{ - "href":"https://api.mollie.com/v2/payments/tr_44aKxzEbr8", - "type":"application/hal+json" - }, - "documentation":{ - "href":"https://docs.mollie.com/reference/v2/refunds-api/create-refund", - "type":"text/html" - } - } - }' - ) - ); - - $refund = $this->getPayment()->refund([ - "amount" => [ - "currency" => "EUR", - "value" => "20.00", - ], - ]); - - $this->assertInstanceOf(Refund::class, $refund); - $this->assertEquals("re_PsAvxvLsnm", $refund->id); - - $amount = new Stdclass(); - $amount->value = '20.00'; - $amount->currency = "EUR"; - $this->assertEquals($amount, $refund->amount); - - $this->assertEquals("pending", $refund->status); - $this->assertEquals("2018-03-19T12:33:37+00:00", $refund->createdAt); - $this->assertEquals("My first API payment", $refund->description); - $this->assertEquals("tr_44aKxzEbr8", $refund->paymentId); - - $amount = new Stdclass(); - $amount->value = '-20.00'; - $amount->currency = "EUR"; - $this->assertEquals($amount, $refund->settlementAmount); - - $selfLink = (object)["href" => "https://api.mollie.com/v2/payments/tr_Tgxm3amJBT/refunds/re_PmEtpvSsnm", "type" => "application/hal+json"]; - $this->assertEquals($selfLink, $refund->_links->self); - - $paymentLink = (object)["href" => "https://api.mollie.com/v2/payments/tr_44aKxzEbr8", "type" => "application/hal+json"]; - $this->assertEquals($paymentLink, $refund->_links->payment); - - $documentationLink = (object)["href" => "https://docs.mollie.com/reference/v2/refunds-api/create-refund", "type" => "text/html"]; - $this->assertEquals($documentationLink, $refund->_links->documentation); - } - - public function testGetRefundsOnPaymentResource() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/payments/tr_44aKxzEbr8/refunds", - [], - '' - ), - new Response( - 201, - [], - '{ - "_embedded": { - "refunds": [ - { - "resource": "refund", - "id": "re_haCsig5aru", - "amount": { - "value": "2.00", - "currency": "EUR" - }, - "status": "pending", - "createdAt": "2018-03-28T10:56:10+00:00", - "description": "My first API payment", - "paymentId": "tr_44aKxzEbr8", - "settlementAmount": { - "value": "-2.00", - "currency": "EUR" - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_44aKxzEbr8/refunds/re_haCsig5aru", - "type": "application/hal+json" - }, - "payment": { - "href": "https://api.mollie.com/v2/payments/tr_44aKxzEbr8", - "type": "application/hal+json" - } - } - } - ] - }, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/refunds-api/list-refunds", - "type": "text/html" - }, - "self": { - "href": "http://api.mollie.nl/v2/payments/tr_44aKxzEbr8/refunds?limit=10", - "type": "application/hal+json" - }, - "previous": null, - "next": null - }, - "count": 1 - }' - ) - ); - - $refunds = $this->getPayment()->refunds(); - - $this->assertInstanceOf(RefundCollection::class, $refunds); - $this->assertEquals(1, $refunds->count); - $this->assertCount(1, $refunds); - - $refund = $refunds[0]; - - $this->assertInstanceOf(Refund::class, $refund); - $this->assertEquals("re_haCsig5aru", $refund->id); - $this->assertEquals("2.00", $refund->amount->value); - $this->assertEquals("EUR", $refund->amount->currency); - $this->assertEquals("pending", $refund->status); - $this->assertEquals("2018-03-28T10:56:10+00:00", $refund->createdAt); - $this->assertEquals("My first API payment", $refund->description); - $this->assertEquals("tr_44aKxzEbr8", $refund->paymentId); - $this->assertEquals("-2.00", $refund->settlementAmount->value); - $this->assertEquals("EUR", $refund->settlementAmount->currency); - - $selfLink = (object)["href" => "https://api.mollie.com/v2/payments/tr_44aKxzEbr8/refunds/re_haCsig5aru", "type" => "application/hal+json"]; - $this->assertEquals($selfLink, $refund->_links->self); - - $paymentLink = (object)["href" => "https://api.mollie.com/v2/payments/tr_44aKxzEbr8", "type" => "application/hal+json"]; - $this->assertEquals($paymentLink, $refund->_links->payment); - } - - public function testListRefundsOnPaymentResource() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/payments/tr_44aKxzEbr8/refunds", - [], - '' - ), - new Response( - 201, - [], - '{ - "_embedded": { - "refunds": [ - { - "resource": "refund", - "id": "re_b63hJyxbap", - "amount": { - "value": "1.00", - "currency": "EUR" - }, - "createdAt": "2021-01-17T20:57:40+00:00", - "description": "Order #1610620820", - "paymentId": "tr_4NydwvhQDd", - "orderId": null, - "lines": null, - "settlementAmount": { - "value": "-1.00", - "currency": "EUR" - }, - "status": "refunded", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_4NydwvhQDd/refunds/re_b63hJyxbap", - "type": "application/hal+json" - }, - "payment": { - "href": "https://api.mollie.com/v2/payments/tr_4NydwvhQDd", - "type": "application/hal+json" - } - }, - "metadata": null - }, - { - "resource": "refund", - "id": "re_SpBqRM9rcn", - "amount": { - "value": "2.00", - "currency": "EUR" - }, - "createdAt": "2021-01-17T20:26:10+00:00", - "description": "test", - "paymentId": "tr_4NydwvhQDd", - "orderId": null, - "lines": null, - "settlementAmount": { - "value": "-2.00", - "currency": "EUR" - }, - "status": "refunded", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_4NydwvhQDd/refunds/re_SpBqRM9rcn", - "type": "application/hal+json" - }, - "payment": { - "href": "https://api.mollie.com/v2/payments/tr_4NydwvhQDd", - "type": "application/hal+json" - } - }, - "metadata": null - } - ] - }, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/refunds-api/list-refunds", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.com/v2/payments/tr_4NydwvhQDd/refunds?limit=50", - "type": "application/hal+json" - }, - "previous": null, - "next": null - }, - "count": 2 - }' - ) - ); - - $refunds = $this->getPayment()->listRefunds(); - - $this->assertInstanceOf(RefundCollection::class, $refunds); - - /** @var RefundCollection $refunds */ - $this->assertEquals(2, $refunds->count); - $this->assertCount(2, $refunds); - - $refund = $refunds[0]; - $this->assertInstanceOf(Refund::class, $refund); - $this->assertEquals("re_b63hJyxbap", $refund->id); - $this->assertEquals("1.00", $refund->amount->value); - $this->assertEquals("EUR", $refund->amount->currency); - $this->assertEquals("refunded", $refund->status); - $this->assertEquals("2021-01-17T20:57:40+00:00", $refund->createdAt); - $this->assertEquals("Order #1610620820", $refund->description); - $this->assertEquals("tr_4NydwvhQDd", $refund->paymentId); - $this->assertEquals("-1.00", $refund->settlementAmount->value); - $this->assertEquals("EUR", $refund->settlementAmount->currency); - - $selfLink = (object)["href" => "https://api.mollie.com/v2/payments/tr_4NydwvhQDd/refunds/re_b63hJyxbap", "type" => "application/hal+json"]; - $this->assertEquals($selfLink, $refund->_links->self); - - $paymentLink = (object)["href" => "https://api.mollie.com/v2/payments/tr_4NydwvhQDd", "type" => "application/hal+json"]; - $this->assertEquals($paymentLink, $refund->_links->payment); - } - - public function testCancelRefundForPayment() - { - $this->mockApiCall( - new Request( - "DELETE", - "/v2/payments/tr_44aKxzEbr8/refunds/re_4qqhO89gsT", - [], - '{"testmode":true}' - ), - new Response(204) - ); - - $response = $this->apiClient->paymentRefunds->cancelForPayment( - $this->getPayment(), - "re_4qqhO89gsT", - [ 'testmode' => true ] - ); - - $this->assertNull($response); - } - - /** - * @return Payment - */ - private function getPayment() - { - $paymentJson = '{ - "resource":"payment", - "id":"tr_44aKxzEbr8", - "mode":"test", - "createdAt":"2018-03-19T12:17:57+00:00", - "amount":{ - "value":"20.00", - "currency":"EUR" - }, - "description":"My first API payment", - "method":"ideal", - "metadata":{ - "order_id":1234 - }, - "status":"paid", - "paidAt":"2018-03-19T12:18:35+00:00", - "amountRefunded":{ - "value":"0.00", - "currency":"EUR" - }, - "amountRemaining":{ - "value":"20.00", - "currency":"EUR" - }, - "details":{ - "consumerName":"T. TEST", - "consumerAccount":"NL17RABO0213698412", - "consumerBic":"TESTNL99" - }, - "locale":"nl_NL", - "countryCode":"NL", - "profileId":"pfl_2A1gacu42V", - "sequenceType":"oneoff", - "redirectUrl":"https://example.org/redirect", - "webhookUrl":"https://example.org/webhook", - "settlementAmount":{ - "value":"20.00", - "currency":"EUR" - }, - "_links":{ - "self":{ - "href":"https://api.mollie.com/v2/payments/tr_44aKxzEbr8", - "type":"application/hal+json" - }, - "documentation":{ - "href":"https://docs.mollie.com/reference/v2/payments-api/get-payment", - "type":"text/html" - }, - "refunds":{ - "href":"https://api.mollie.com/v2/payments/tr_44aKxzEbr8/refunds", - "type":"application/hal+json" - } - } - }'; - - return $this->copy(json_decode($paymentJson), new Payment($this->apiClient)); - } -} diff --git a/tests/Mollie/API/Endpoints/PaymentRouteEndpointTest.php b/tests/Mollie/API/Endpoints/PaymentRouteEndpointTest.php deleted file mode 100644 index 7f0e21e94..000000000 --- a/tests/Mollie/API/Endpoints/PaymentRouteEndpointTest.php +++ /dev/null @@ -1,49 +0,0 @@ -mockApiCall( - new Request( - "PATCH", - "/v2/payments/tr_2qkhcMzypH/routes/rt_9dk4al1n", - [], - '{ - "releaseDate": "2021-09-14", - "testmode": false - }' - ), - new Response( - 201, - [], - '{ - "resource": "route", - "id": "rt_9dk4al1n", - "createdAt": "2021-08-28T14:02:29+00:00", - "amount": { - "value": "7.50", - "currency": "EUR" - }, - "destination": { - "type": "organization", - "organizationId": "org_23456" - }, - "releaseDate": "2021-09-14" - }' - ) - ); - - $route = $this->apiClient->paymentRoutes->updateReleaseDateForPaymentId('tr_2qkhcMzypH', 'rt_9dk4al1n', '2021-09-14'); - - $this->assertInstanceOf(Route::class, $route); - $this->assertEquals('rt_9dk4al1n', $route->id); - $this->assertEquals("2021-09-14", $route->releaseDate); - } -} diff --git a/tests/Mollie/API/Endpoints/PermissionEndpointTest.php b/tests/Mollie/API/Endpoints/PermissionEndpointTest.php deleted file mode 100644 index d745482c1..000000000 --- a/tests/Mollie/API/Endpoints/PermissionEndpointTest.php +++ /dev/null @@ -1,169 +0,0 @@ -mockApiCall( - new Request('GET', '/v2/permissions/' . $permissionId), - new Response( - 200, - [], - '{ - "resource": "permission", - "id": "' . $permissionId . '", - "description": "Some dummy permission description", - "granted": true, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/permissions/' . $permissionId . '", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/permissions-api/get-permission", - "type": "text/html" - } - } - }' - ) - ); - - $permission = $this->apiClient->permissions->get($permissionId); - - $this->assertPermission($permission, $permissionId); - } - - public function dpTestGetPermissionIds() - { - return [ - ['payments.read'], - ['payments.write'], - ['refunds.read'], - ['refunds.write'], - ['customers.read'], - ['customers.write'], - ['mandates.read'], - ['mandates.write'], - ['subscriptions.read'], - ['subscriptions.write'], - ['profiles.read'], - ['profiles.write'], - ['invoices.read'], - ['invoices.write'], - ['settlements.read'], - ['settlements.write'], - ['orders.read'], - ['orders.write'], - ['organizations.read'], - ['organizations.write'], - ]; - } - - protected function assertPermission($permission, $permissionId) - { - $this->assertInstanceOf(Permission::class, $permission); - $this->assertEquals('permission', $permission->resource); - $this->assertEquals($permissionId, $permission->id); - $this->assertEquals( - 'Some dummy permission description', - $permission->description - ); - $this->assertTrue($permission->granted); - - $this->assertLinkObject( - 'https://api.mollie.com/v2/permissions/' . $permissionId, - 'application/hal+json', - $permission->_links->self - ); - - $this->assertLinkObject( - 'https://docs.mollie.com/reference/v2/permissions-api/get-permission', - 'text/html', - $permission->_links->documentation - ); - } - - public function testListPermissions() - { - $this->mockApiCall( - new Request('GET', '/v2/permissions'), - new Response( - 200, - [], - '{ - "_embedded": { - "permissions": [ - { - "resource": "permission", - "id": "payments.write", - "description": "Some dummy permission description", - "granted": true, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/permissions/payments.write", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/permissions-api/get-permission", - "type": "text/html" - } - } - }, - { - "resource": "permission", - "id": "payments.read", - "description": "Some dummy permission description", - "granted": true, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/permissions/payments.read", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/permissions-api/get-permission", - "type": "text/html" - } - } - } - ] - }, - "count": 2, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/permissions-api/list-permissions", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.com/v2/permissions", - "type": "application/hal+json" - } - } - }' - ) - ); - - $permissions = $this->apiClient->permissions->all(); - - $this->assertInstanceOf(PermissionCollection::class, $permissions); - - $this->assertCount(2, $permissions); - - $this->assertPermission($permissions[0], 'payments.write'); - $this->assertPermission($permissions[1], 'payments.read'); - } -} diff --git a/tests/Mollie/API/Endpoints/ProfileEndpointTest.php b/tests/Mollie/API/Endpoints/ProfileEndpointTest.php deleted file mode 100644 index 05ad639e3..000000000 --- a/tests/Mollie/API/Endpoints/ProfileEndpointTest.php +++ /dev/null @@ -1,500 +0,0 @@ -mockApiCall( - new Request( - "GET", - "/v2/profiles/pfl_ahe8z8OPut", - [], - '' - ), - new Response( - 200, - [], - '{ - "resource": "profile", - "id": "pfl_ahe8z8OPut", - "mode": "live", - "name": "My website name", - "website": "http://www.mywebsite.com", - "email": "info@mywebsite.com", - "phone": "31123456789", - "categoryCode": 5399, - "status": "verified", - "review": { - "status": "pending" - }, - "createdAt": "2016-01-11T13:03:55+00:00", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/profiles/pfl_ahe8z8OPut", - "type": "application/hal+json" - }, - "chargebacks": { - "href": "https://api.mollie.com/v2/chargebacks?profileId=pfl_ahe8z8OPut", - "type": "application/hal+json" - }, - "methods": { - "href": "https://api.mollie.com/v2/methods?profileId=pfl_ahe8z8OPut", - "type": "application/hal+json" - }, - "payments": { - "href": "https://api.mollie.com/v2/payments?profileId=pfl_ahe8z8OPut", - "type": "application/hal+json" - }, - "refunds": { - "href": "https://api.mollie.com/v2/refunds?profileId=pfl_ahe8z8OPut", - "type": "application/hal+json" - }, - "checkoutPreviewUrl": { - "href": "https://www.mollie.com/payscreen/preview/pfl_ahe8z8OPut", - "type": "text/html" - } - } - }' - ) - ); - - $profile = $this->apiClient->profiles->get('pfl_ahe8z8OPut'); - - $this->assertInstanceOf(Profile::class, $profile); - $this->assertEquals("pfl_ahe8z8OPut", $profile->id); - $this->assertEquals("live", $profile->mode); - $this->assertEquals("My website name", $profile->name); - $this->assertEquals("http://www.mywebsite.com", $profile->website); - $this->assertEquals("info@mywebsite.com", $profile->email); - $this->assertEquals("31123456789", $profile->phone); - $this->assertEquals(5399, $profile->categoryCode); - $this->assertEquals(ProfileStatus::STATUS_VERIFIED, $profile->status); - $this->assertEquals((object) ["status" => "pending"], $profile->review); - - $selfLink = (object)["href" => "https://api.mollie.com/v2/profiles/pfl_ahe8z8OPut", "type" => "application/hal+json"]; - $this->assertEquals($selfLink, $profile->_links->self); - - $chargebacksLink = (object)["href" => "https://api.mollie.com/v2/chargebacks?profileId=pfl_ahe8z8OPut", "type" => "application/hal+json"]; - $this->assertEquals($chargebacksLink, $profile->_links->chargebacks); - - $methodsLink = (object)["href" => "https://api.mollie.com/v2/methods?profileId=pfl_ahe8z8OPut", "type" => "application/hal+json"]; - $this->assertEquals($methodsLink, $profile->_links->methods); - - $paymentsLink = (object)["href" => "https://api.mollie.com/v2/payments?profileId=pfl_ahe8z8OPut", "type" => "application/hal+json"]; - $this->assertEquals($paymentsLink, $profile->_links->payments); - - $refundsLink = (object)["href" => "https://api.mollie.com/v2/refunds?profileId=pfl_ahe8z8OPut", "type" => "application/hal+json"]; - $this->assertEquals($refundsLink, $profile->_links->refunds); - - $checkoutPreviewLink = (object)["href" => "https://www.mollie.com/payscreen/preview/pfl_ahe8z8OPut", "type" => "text/html"]; - $this->assertEquals($checkoutPreviewLink, $profile->_links->checkoutPreviewUrl); - } - - public function testGetProfileUsingMe() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/profiles/me", - [], - '' - ), - new Response( - 200, - [], - '{ - "resource": "profile", - "id": "pfl_ahe8z8OPut", - "mode": "live", - "name": "My website name", - "website": "http://www.mywebsite.com", - "email": "info@mywebsite.com", - "phone": "31123456789", - "categoryCode": 5399, - "status": "verified", - "review": { - "status": "pending" - }, - "createdAt": "2016-01-11T13:03:55+00:00", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/profiles/pfl_ahe8z8OPut", - "type": "application/hal+json" - }, - "chargebacks": { - "href": "https://api.mollie.com/v2/chargebacks?profileId=pfl_ahe8z8OPut", - "type": "application/hal+json" - }, - "methods": { - "href": "https://api.mollie.com/v2/methods?profileId=pfl_ahe8z8OPut", - "type": "application/hal+json" - }, - "payments": { - "href": "https://api.mollie.com/v2/payments?profileId=pfl_ahe8z8OPut", - "type": "application/hal+json" - }, - "refunds": { - "href": "https://api.mollie.com/v2/refunds?profileId=pfl_ahe8z8OPut", - "type": "application/hal+json" - }, - "checkoutPreviewUrl": { - "href": "https://www.mollie.com/payscreen/preview/pfl_ahe8z8OPut", - "type": "text/html" - } - } - }' - ) - ); - - $profile = $this->apiClient->profiles->get('me'); - - $this->assertInstanceOf(CurrentProfile::class, $profile); - $this->assertEquals("pfl_ahe8z8OPut", $profile->id); - - // No need to test it all again... - } - - public function testGetCurrentProfile() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/profiles/me", - [], - '' - ), - new Response( - 200, - [], - '{ - "resource": "profile", - "id": "pfl_ahe8z8OPut", - "mode": "live", - "name": "My website name", - "website": "http://www.mywebsite.com", - "email": "info@mywebsite.com", - "phone": "31123456789", - "categoryCode": 5399, - "status": "verified", - "review": { - "status": "pending" - }, - "createdAt": "2016-01-11T13:03:55+00:00", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/profiles/pfl_ahe8z8OPut", - "type": "application/hal+json" - }, - "chargebacks": { - "href": "https://api.mollie.com/v2/chargebacks", - "type": "application/hal+json" - }, - "methods": { - "href": "https://api.mollie.com/v2/methods", - "type": "application/hal+json" - }, - "payments": { - "href": "https://api.mollie.com/v2/payments", - "type": "application/hal+json" - }, - "refunds": { - "href": "https://api.mollie.com/v2/refunds", - "type": "application/hal+json" - }, - "checkoutPreviewUrl": { - "href": "https://www.mollie.com/payscreen/preview/pfl_ahe8z8OPut", - "type": "text/html" - } - } - }' - ) - ); - - $profile = $this->apiClient->profiles->getCurrent(); - - $this->assertInstanceOf(CurrentProfile::class, $profile); - $this->assertEquals("pfl_ahe8z8OPut", $profile->id); - $this->assertEquals("live", $profile->mode); - $this->assertEquals("My website name", $profile->name); - $this->assertEquals("http://www.mywebsite.com", $profile->website); - $this->assertEquals("info@mywebsite.com", $profile->email); - $this->assertEquals("31123456789", $profile->phone); - $this->assertEquals(5399, $profile->categoryCode); - $this->assertEquals(ProfileStatus::STATUS_VERIFIED, $profile->status); - $this->assertEquals((object) ["status" => "pending"], $profile->review); - - $selfLink = (object)["href" => "https://api.mollie.com/v2/profiles/pfl_ahe8z8OPut", "type" => "application/hal+json"]; - $this->assertEquals($selfLink, $profile->_links->self); - - $chargebacksLink = (object)["href" => "https://api.mollie.com/v2/chargebacks", "type" => "application/hal+json"]; - $this->assertEquals($chargebacksLink, $profile->_links->chargebacks); - - $methodsLink = (object)["href" => "https://api.mollie.com/v2/methods", "type" => "application/hal+json"]; - $this->assertEquals($methodsLink, $profile->_links->methods); - - $paymentsLink = (object)["href" => "https://api.mollie.com/v2/payments", "type" => "application/hal+json"]; - $this->assertEquals($paymentsLink, $profile->_links->payments); - - $refundsLink = (object)["href" => "https://api.mollie.com/v2/refunds", "type" => "application/hal+json"]; - $this->assertEquals($refundsLink, $profile->_links->refunds); - - $checkoutPreviewLink = (object)["href" => "https://www.mollie.com/payscreen/preview/pfl_ahe8z8OPut", "type" => "text/html"]; - $this->assertEquals($checkoutPreviewLink, $profile->_links->checkoutPreviewUrl); - } - - public function testListProfiles() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/profiles", - [], - '' - ), - new Response( - 200, - [], - '{ - "_embedded": { - "profiles": [{ - "resource": "profile", - "id": "pfl_ahe8z8OPut", - "mode": "live", - "name": "My website name", - "website": "http://www.mywebsite.com", - "email": "info@mywebsite.com", - "phone": "31123456789", - "categoryCode": 5399, - "status": "verified", - "review": { - "status": "pending" - }, - "createdAt": "2016-01-11T13:03:55+00:00", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/profiles/pfl_ahe8z8OPut", - "type": "application/hal+json" - }, - "chargebacks": { - "href": "https://api.mollie.com/v2/chargebacks?profileId=pfl_ahe8z8OPut", - "type": "application/hal+json" - }, - "methods": { - "href": "https://api.mollie.com/v2/methods?profileId=pfl_ahe8z8OPut", - "type": "application/hal+json" - }, - "payments": { - "href": "https://api.mollie.com/v2/payments?profileId=pfl_ahe8z8OPut", - "type": "application/hal+json" - }, - "refunds": { - "href": "https://api.mollie.com/v2/refunds?profileId=pfl_ahe8z8OPut", - "type": "application/hal+json" - }, - "checkoutPreviewUrl": { - "href": "https://www.mollie.com/payscreen/preview/pfl_ahe8z8OPut", - "type": "text/html" - } - } - }, - { - "resource": "profile", - "id": "pfl_znNaTRkJs5", - "mode": "live", - "name": "My website name 2", - "website": "http://www.mywebsite2.com", - "email": "info@mywebsite2.com", - "phone": "31123456789", - "categoryCode": 5399, - "status": "verified", - "review": { - "status": "pending" - }, - "createdAt": "2016-01-11T13:03:55+00:00", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/profiles/pfl_znNaTRkJs5", - "type": "application/hal+json" - }, - "chargebacks": { - "href": "https://api.mollie.com/v2/chargebacks?profileId=pfl_znNaTRkJs5", - "type": "application/hal+json" - }, - "methods": { - "href": "https://api.mollie.com/v2/methods?profileId=pfl_znNaTRkJs5", - "type": "application/hal+json" - }, - "payments": { - "href": "https://api.mollie.com/v2/payments?profileId=pfl_znNaTRkJs5", - "type": "application/hal+json" - }, - "refunds": { - "href": "https://api.mollie.com/v2/refunds?profileId=pfl_znNaTRkJs5", - "type": "application/hal+json" - }, - "checkoutPreviewUrl": { - "href": "https://www.mollie.com/payscreen/preview/pfl_znNaTRkJs5", - "type": "text/html" - } - } - } - ] - }, - "count": 2, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/profiles-api/list-profiles", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.nl/v2/profiles?limit=50", - "type": "application/hal+json" - }, - "previous": null, - "next": null - } - }' - ) - ); - - $profiles = $this->apiClient->profiles->page(); - $this->assertInstanceOf(ProfileCollection::class, $profiles); - $this->assertEquals(2, $profiles->count); - - foreach ($profiles as $profile) { - $this->assertInstanceOf(Profile::class, $profile); - } - - $selfLink = (object)["href" => "https://api.mollie.nl/v2/profiles?limit=50", "type" => "application/hal+json"]; - $this->assertEquals($selfLink, $profiles->_links->self); - - $documentationLink = (object)["href" => "https://docs.mollie.com/reference/v2/profiles-api/list-profiles", "type" => "text/html"]; - $this->assertEquals($documentationLink, $profiles->_links->documentation); - } - - public function testUpdateProfile() - { - $expectedWebsiteName = 'Mollie'; - $expectedEmail = 'mollie@mollie.com'; - $expectedPhone = '31123456766'; - - $this->mockApiCall( - new Request('PATCH', '/v2/profiles/pfl_ahe8z8OPut'), - new Response( - 200, - [], - '{ - "resource": "profile", - "id": "pfl_ahe8z8OPut", - "mode": "live", - "name": "' . $expectedWebsiteName . '", - "website": "http://www.mywebsite.com", - "email": "' . $expectedEmail . '", - "phone": "' . $expectedPhone . '", - "categoryCode": 5399, - "status": "verified", - "review": { - "status": "pending" - }, - "createdAt": "2016-01-11T13:03:55+00:00", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/profiles/pfl_ahe8z8OPut", - "type": "application/hal+json" - }, - "chargebacks": { - "href": "https://api.mollie.com/v2/chargebacks?profileId=pfl_ahe8z8OPut", - "type": "application/hal+json" - }, - "methods": { - "href": "https://api.mollie.com/v2/methods?profileId=pfl_ahe8z8OPut", - "type": "application/hal+json" - }, - "payments": { - "href": "https://api.mollie.com/v2/payments?profileId=pfl_ahe8z8OPut", - "type": "application/hal+json" - }, - "refunds": { - "href": "https://api.mollie.com/v2/refunds?profileId=pfl_ahe8z8OPut", - "type": "application/hal+json" - }, - "checkoutPreviewUrl": { - "href": "https://www.mollie.com/payscreen/preview/pfl_ahe8z8OPut", - "type": "text/html" - } - } - }' - ) - ); - - $profile = $this->getProfile(); - $profile->name = $expectedWebsiteName; - $profile->email = $expectedEmail; - $profile->phone = $expectedPhone; - - $updatedProfile = $profile->update(); - - $this->assertEquals($expectedWebsiteName, $updatedProfile->name); - $this->assertEquals($expectedEmail, $updatedProfile->email); - $this->assertEquals($expectedPhone, $updatedProfile->phone); - } - - /** - * @return Profile - */ - private function getProfile() - { - $json = '{ - "resource": "profile", - "id": "pfl_ahe8z8OPut", - "mode": "live", - "name": "My website name", - "website": "http://www.mywebsite.com", - "email": "info@mywebsite.com", - "phone": "31123456789", - "categoryCode": 5399, - "status": "verified", - "review": { - "status": "pending" - }, - "createdAt": "2016-01-11T13:03:55+00:00", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/profiles/pfl_ahe8z8OPut", - "type": "application/hal+json" - }, - "chargebacks": { - "href": "https://api.mollie.com/v2/chargebacks?profileId=pfl_ahe8z8OPut", - "type": "application/hal+json" - }, - "methods": { - "href": "https://api.mollie.com/v2/methods?profileId=pfl_ahe8z8OPut", - "type": "application/hal+json" - }, - "payments": { - "href": "https://api.mollie.com/v2/payments?profileId=pfl_ahe8z8OPut", - "type": "application/hal+json" - }, - "refunds": { - "href": "https://api.mollie.com/v2/refunds?profileId=pfl_ahe8z8OPut", - "type": "application/hal+json" - }, - "checkoutPreviewUrl": { - "href": "https://www.mollie.com/payscreen/preview/pfl_ahe8z8OPut", - "type": "text/html" - } - } - }'; - - return $this->copy(json_decode($json), new Profile($this->apiClient)); - } -} diff --git a/tests/Mollie/API/Endpoints/ProfileMethodEndpointTest.php b/tests/Mollie/API/Endpoints/ProfileMethodEndpointTest.php deleted file mode 100644 index 31ef34114..000000000 --- a/tests/Mollie/API/Endpoints/ProfileMethodEndpointTest.php +++ /dev/null @@ -1,230 +0,0 @@ -mockApiCall( - new Request( - "POST", - "/v2/profiles/pfl_v9hTwCvYqw/methods/bancontact" - ), - new Response( - 201, - [], - '{ - "resource": "method", - "id": "bancontact", - "description": "Bancontact", - "image": { - "size1x": "https://www.mollie.com/external/icons/payment-methods/bancontact.png", - "size2x": "https://www.mollie.com/external/icons/payment-methods/bancontact%402x.png", - "svg": "https://www.mollie.com/external/icons/payment-methods/bancontact.svg" - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/methods/bancontact", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/profiles-api/activate-method", - "type": "text/html" - } - } - }' - ) - ); - - $profile = $this->getProfile(); - $method = $profile->enableMethod('bancontact'); - - $this->assertInstanceOf(Method::class, $method); - $this->assertEquals('bancontact', $method->id); - $this->assertEquals('Bancontact', $method->description); - $this->assertEquals('https://www.mollie.com/external/icons/payment-methods/bancontact.png', $method->image->size1x); - $this->assertEquals('https://www.mollie.com/external/icons/payment-methods/bancontact%402x.png', $method->image->size2x); - $this->assertEquals('https://www.mollie.com/external/icons/payment-methods/bancontact.svg', $method->image->svg); - - $this->assertLinkObject( - "https://api.mollie.com/v2/methods/bancontact", - "application/hal+json", - $method->_links->self - ); - - $this->assertLinkObject( - "https://docs.mollie.com/reference/v2/profiles-api/activate-method", - "text/html", - $method->_links->documentation - ); - } - - public function testDisableProfileMethod() - { - $this->mockApiCall( - new Request( - "DELETE", - "/v2/profiles/pfl_v9hTwCvYqw/methods/bancontact" - ), - new Response(204) - ); - - $profile = $this->getProfile(); - $result = $profile->disableMethod('bancontact'); - - $this->assertNull($result); - } - - public function testEnableCurrentProfileMethod() - { - $this->mockApiCall( - new Request( - "POST", - "/v2/profiles/me/methods/bancontact" - ), - new Response( - 201, - [], - '{ - "resource": "method", - "id": "bancontact", - "description": "Bancontact", - "image": { - "size1x": "https://www.mollie.com/external/icons/payment-methods/bancontact.png", - "size2x": "https://www.mollie.com/external/icons/payment-methods/bancontact%402x.png", - "svg": "https://www.mollie.com/external/icons/payment-methods/bancontact.svg" - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/methods/bancontact", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/profiles-api/activate-method", - "type": "text/html" - } - } - }' - ) - ); - - $profile = $this->getCurrentProfile(); - $method = $profile->enableMethod('bancontact'); - - $this->assertInstanceOf(Method::class, $method); - $this->assertEquals('bancontact', $method->id); - $this->assertEquals('Bancontact', $method->description); - $this->assertEquals('https://www.mollie.com/external/icons/payment-methods/bancontact.png', $method->image->size1x); - $this->assertEquals('https://www.mollie.com/external/icons/payment-methods/bancontact%402x.png', $method->image->size2x); - $this->assertEquals('https://www.mollie.com/external/icons/payment-methods/bancontact.svg', $method->image->svg); - - $this->assertLinkObject( - "https://api.mollie.com/v2/methods/bancontact", - "application/hal+json", - $method->_links->self - ); - - $this->assertLinkObject( - "https://docs.mollie.com/reference/v2/profiles-api/activate-method", - "text/html", - $method->_links->documentation - ); - } - - public function testDisableCurrentProfileMethod() - { - $this->mockApiCall( - new Request( - "DELETE", - "/v2/profiles/me/methods/bancontact" - ), - new Response(204) - ); - - $profile = $this->getCurrentProfile(); - - $result = $profile->disableMethod('bancontact'); - - $this->assertNull($result); - } - - /** - * @return CurrentProfile - */ - private function getCurrentProfile() - { - return $this->copy( - json_decode($this->getProfileFixture()), - new CurrentProfile($this->apiClient) - ); - } - - /** - * @return Profile - */ - private function getProfile() - { - return $this->copy( - json_decode($this->getProfileFixture()), - new Profile($this->apiClient) - ); - } - - /** - * @return string - */ - private function getProfileFixture() - { - return '{ - "resource": "profile", - "id": "pfl_v9hTwCvYqw", - "mode": "live", - "name": "My website name", - "website": "http://www.mywebsite.com", - "email": "info@mywebsite.com", - "phone": "31123456789", - "categoryCode": 5399, - "status": "verified", - "review": { - "status": "pending" - }, - "createdAt": "2016-01-11T13:03:55+00:00", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/profiles/pfl_v9hTwCvYqw", - "type": "application/hal+json" - }, - "chargebacks": { - "href": "https://api.mollie.com/v2/chargebacks?profileId=pfl_v9hTwCvYqw", - "type": "application/hal+json" - }, - "methods": { - "href": "https://api.mollie.com/v2/methods?profileId=pfl_v9hTwCvYqw", - "type": "application/hal+json" - }, - "payments": { - "href": "https://api.mollie.com/v2/payments?profileId=pfl_v9hTwCvYqw", - "type": "application/hal+json" - }, - "refunds": { - "href": "https://api.mollie.com/v2/refunds?profileId=pfl_v9hTwCvYqw", - "type": "application/hal+json" - }, - "checkoutPreviewUrl": { - "href": "https://www.mollie.com/payscreen/preview/pfl_v9hTwCvYqw", - "type": "text/html" - } - } - }'; - } -} diff --git a/tests/Mollie/API/Endpoints/RefundEndpointTest.php b/tests/Mollie/API/Endpoints/RefundEndpointTest.php deleted file mode 100644 index 351e2b461..000000000 --- a/tests/Mollie/API/Endpoints/RefundEndpointTest.php +++ /dev/null @@ -1,163 +0,0 @@ -mockApiCall( - new Request( - "GET", - "/v2/refunds", - [], - '' - ), - new Response( - 200, - [], - '{ - "_embedded": { - "refunds": [ - { - "resource": "refund", - "id": "re_haCsig5aru", - "amount": { - "value": "2.00", - "currency": "EUR" - }, - "status": "pending", - "createdAt": "2018-03-28T10:56:10+00:00", - "description": "My first API payment", - "paymentId": "tr_44aKxzEbr8", - "settlementAmount": { - "value": "-2.00", - "currency": "EUR" - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_44aKxzEbr8/refunds/re_haCsig5aru", - "type": "application/hal+json" - }, - "payment": { - "href": "https://api.mollie.com/v2/payments/tr_44aKxzEbr8", - "type": "application/hal+json" - } - } - } - ] - }, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/refunds-api/list-refunds", - "type": "text/html" - }, - "self": { - "href": "http://api.mollie.nl/v2/refunds?limit=10", - "type": "application/hal+json" - }, - "previous": null, - "next": null - }, - "count": 1 - }' - ) - ); - - $refunds = $this->apiClient->refunds->page(); - - $this->assertInstanceOf(RefundCollection::class, $refunds); - $this->assertEquals(1, $refunds->count); - $this->assertCount(1, $refunds); - - $refund = $refunds[0]; - - $this->assertInstanceOf(Refund::class, $refund); - $this->assertEquals("re_haCsig5aru", $refund->id); - $this->assertEquals("2.00", $refund->amount->value); - $this->assertEquals("EUR", $refund->amount->currency); - $this->assertEquals("pending", $refund->status); - $this->assertEquals("2018-03-28T10:56:10+00:00", $refund->createdAt); - $this->assertEquals("My first API payment", $refund->description); - $this->assertEquals("tr_44aKxzEbr8", $refund->paymentId); - $this->assertEquals("-2.00", $refund->settlementAmount->value); - $this->assertEquals("EUR", $refund->settlementAmount->currency); - - $selfLink = (object)["href" => "https://api.mollie.com/v2/payments/tr_44aKxzEbr8/refunds/re_haCsig5aru", "type" => "application/hal+json"]; - $this->assertEquals($selfLink, $refund->_links->self); - - $paymentLink = (object)["href" => "https://api.mollie.com/v2/payments/tr_44aKxzEbr8", "type" => "application/hal+json"]; - $this->assertEquals($paymentLink, $refund->_links->payment); - } - - public function testIterateRefunds() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/refunds", - [], - '' - ), - new Response( - 200, - [], - '{ - "_embedded": { - "refunds": [ - { - "resource": "refund", - "id": "re_haCsig5aru", - "amount": { - "value": "2.00", - "currency": "EUR" - }, - "status": "pending", - "createdAt": "2018-03-28T10:56:10+00:00", - "description": "My first API payment", - "paymentId": "tr_44aKxzEbr8", - "settlementAmount": { - "value": "-2.00", - "currency": "EUR" - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_44aKxzEbr8/refunds/re_haCsig5aru", - "type": "application/hal+json" - }, - "payment": { - "href": "https://api.mollie.com/v2/payments/tr_44aKxzEbr8", - "type": "application/hal+json" - } - } - } - ] - }, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/refunds-api/list-refunds", - "type": "text/html" - }, - "self": { - "href": "http://api.mollie.nl/v2/refunds?limit=10", - "type": "application/hal+json" - }, - "previous": null, - "next": null - }, - "count": 1 - }' - ) - ); - - foreach ($this->apiClient->refunds->iterator() as $refund) { - $this->assertInstanceOf(Refund::class, $refund); - $this->assertEquals("refund", $refund->resource); - } - } -} diff --git a/tests/Mollie/API/Endpoints/SessionEndpointTest.php b/tests/Mollie/API/Endpoints/SessionEndpointTest.php deleted file mode 100644 index 648e72f24..000000000 --- a/tests/Mollie/API/Endpoints/SessionEndpointTest.php +++ /dev/null @@ -1,361 +0,0 @@ -mockApiCall( - new Request( - "POST", - "/v2/sessions", - [], - '{ - "paymentData": { - "amount": { - "value": "10.00", - "currency": "EUR" - }, - "description": "Order #12345" - }, - "method": "paypal", - "methodDetails": { - "checkoutFlow": "express" - }, - "returnUrl": "https://example.org/redirect", - "cancelUrl": "https://example.org/cancel" - }' - ), - new Response( - 201, - [], - $this->getSessionResponseFixture("sess_pbjz8x") - ) - ); - - $session = $this->apiClient->sessions->create([ - "paymentData" => [ - "amount" => [ - "value" => "10.00", - "currency" => "EUR", - ], - "description" => "Order #12345", - ], - "method" => "paypal", - "methodDetails" => [ - "checkoutFlow" => "express", - ], - "returnUrl" => "https://example.org/redirect", - "cancelUrl" => "https://example.org/cancel", - ]); - - $this->assertSession($session, 'sess_pbjz8x'); - } - - public function testGetSession() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/sessions/sess_pbjz8x" - ), - new Response( - 200, - [], - $this->getSessionResponseFixture("sess_pbjz8x") - ) - ); - - $session = $this->apiClient->sessions->get('sess_pbjz8x'); - - $this->assertSession($session, 'sess_pbjz8x'); - } - - public function testListSessions() - { - $this->mockApiCall( - new Request("GET", "/v2/sessions"), - new Response( - 200, - [], - '{ - "count": 3, - "_embedded": { - "sessions": [ - ' . $this->getSessionResponseFixture("sess_pbjz1x") . ', - ' . $this->getSessionResponseFixture("sess_pbjz2y") . ', - ' . $this->getSessionResponseFixture("sess_pbjz3z") . ' - ] - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/sessions", - "type": "application/hal+json" - }, - "previous": null, - "next": { - "href": "https://api.mollie.com/v2/sessions?from=sess_stTC2WHAuS", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/sessions-api/list-sessions", - "type": "text/html" - } - } - }' - ) - ); - - $sessions = $this->apiClient->sessions->page(); - - $this->assertInstanceOf(SessionCollection::class, $sessions); - $this->assertEquals(3, $sessions->count); - $this->assertEquals(3, count($sessions)); - - $this->assertNull($sessions->_links->previous); - $selfLink = $this->createLinkObject( - "https://api.mollie.com/v2/sessions", - "application/hal+json" - ); - $this->assertEquals($selfLink, $sessions->_links->self); - - $nextLink = $this->createLinkObject( - "https://api.mollie.com/v2/sessions?from=sess_stTC2WHAuS", - "application/hal+json" - ); - $this->assertEquals($nextLink, $sessions->_links->next); - - $documentationLink = $this->createLinkObject( - "https://docs.mollie.com/reference/v2/sessions-api/list-sessions", - "text/html" - ); - $this->assertEquals($documentationLink, $sessions->_links->documentation); - - $this->assertSession($sessions[0], 'sess_pbjz1x'); - $this->assertSession($sessions[1], 'sess_pbjz2y'); - $this->assertSession($sessions[2], 'sess_pbjz3z'); - } - - public function testIterateSessions() - { - $this->mockApiCall( - new Request("GET", "/v2/sessions"), - new Response( - 200, - [], - '{ - "count": 3, - "_embedded": { - "sessions": [ - ' . $this->getSessionResponseFixture("sess_pbjz1x") . ', - ' . $this->getSessionResponseFixture("sess_pbjz2y") . ', - ' . $this->getSessionResponseFixture("sess_pbjz3z") . ' - ] - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/sessions", - "type": "application/hal+json" - }, - "previous": null, - "next": null, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/sessions-api/list-sessions", - "type": "text/html" - } - } - }' - ) - ); - - foreach ($this->apiClient->sessions->iterator() as $session) { - $this->assertInstanceOf(Session::class, $session); - } - } - - public function testCancelSession() - { - $this->mockApiCall( - new Request("DELETE", "/v2/sessions/sess_pbjz1x"), - new Response( - 200, - [], - $this->getSessionResponseFixture( - 'sess_pbjz1x', - SessionStatus::STATUS_FAILED - ) - ) - ); - $session = $this->apiClient->sessions->cancel('sess_pbjz1x'); - $this->assertSession($session, 'sess_pbjz1x', SessionStatus::STATUS_FAILED); - } - - /** @test */ - public function testUpdateSession() - { - $this->mockApiCall( - new Request( - "PATCH", - "/v2/sessions/sess_pbjz8x", - [], - '{ - "billingAddress": { - "organizationName": "Organization Name LTD.", - "streetAndNumber": "Keizersgracht 313", - "postalCode": "1234AB", - "city": "Amsterdam", - "country": "NL", - "givenName": "Piet", - "familyName": "Mondriaan", - "email": "piet@mondriaan.com", - "region": "Noord-Holland", - "title": "Dhr", - "phone": "+31208202070" - }, - "shippingAddress": { - "organizationName": "Organization Name LTD.", - "streetAndNumber": "Keizersgracht 313", - "postalCode": "1016 EE", - "city": "Amsterdam", - "country": "nl", - "givenName": "Luke", - "familyName": "Skywalker", - "email": "luke@skywalker.com" - } - }' - ), - new Response( - 200, - [], - $this->getSessionResponseFixture( - "sess_pbjz8x", - SessionStatus::STATUS_CREATED - ) - ) - ); - - $sessionJSON = $this->getSessionResponseFixture('sess_pbjz8x'); - - /** @var Session $session */ - $session = $this->copy(json_decode($sessionJSON), new Session($this->apiClient)); - - $session->billingAddress->organizationName = "Organization Name LTD."; - $session->billingAddress->streetAndNumber = "Keizersgracht 313"; - $session->billingAddress->city = "Amsterdam"; - $session->billingAddress->region = "Noord-Holland"; - $session->billingAddress->postalCode = "1234AB"; - $session->billingAddress->country = "NL"; - $session->billingAddress->title = "Dhr"; - $session->billingAddress->givenName = "Piet"; - $session->billingAddress->familyName = "Mondriaan"; - $session->billingAddress->email = "piet@mondriaan.com"; - $session->billingAddress->phone = "+31208202070"; - $session = $session->update(); - - $this->assertSession($session, "sess_pbjz8x", SessionStatus::STATUS_CREATED); - } - - protected function assertSession($session, $session_id, $sessionStatus = SessionStatus::STATUS_CREATED) - { - $this->assertInstanceOf(Session::class, $session); - $this->assertEquals('session', $session->resource); - $this->assertEquals($session_id, $session->id); - $this->assertEquals('paypal', $session->method); - - $this->assertAmountObject('10.00', 'EUR', $session->amount); - - $this->assertEquals($sessionStatus, $session->status); - - $this->assertEquals("https://example.org/redirect", $session->getRedirectUrl()); - /** - * @todo check how the links will be returned - */ - // $this->assertEquals("https://example.org/cancel", $session->cancelUrl); - - $links = (object)[ - 'self' => $this->createLinkObject( - 'https://api.mollie.com/v2/sessions/' . $session_id, - 'application/hal+json' - ), - 'redirect' => $this->createLinkObject( - 'https://example.org/redirect', - 'application/hal+json' - ), - ]; - $this->assertEquals($links, $session->_links); - } - - protected function getSessionResponseFixture($session_id, $sessionStatus = SessionStatus::STATUS_CREATED) - { - return str_replace( - [ - "<>", - "<>", - ], - [ - $session_id, - $sessionStatus, - ], - '{ - "resource": "session", - "id": "<>", - "status": "<>", - "amount": { - "value": 10.00, - "currency": "EUR" - }, - "description": "Order #12345", - "method": "paypal", - "methodDetails": { - "checkoutFlow":"express" - }, - "billingAddress": { - "organizationName": "Organization Name LTD.", - "streetAndNumber": "Keizersgracht 313", - "postalCode": "1234AB", - "city": "Amsterdam", - "country": "NL", - "givenName": "Piet", - "familyName": "Mondriaan", - "email": "piet@mondriaan.com", - "region": "Noord-Holland", - "title": "Dhr", - "phone": "+31208202070" - }, - "shippingAddress": { - "organizationName": "Organization Name LTD.", - "streetAndNumber": "Keizersgracht 313", - "postalCode": "1016 EE", - "city": "Amsterdam", - "country": "nl", - "givenName": "Luke", - "familyName": "Skywalker", - "email": "luke@skywalker.com" - }, - "nextAction": "redirect", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/sessions/<>", - "type": "application/hal+json" - }, - "redirect": { - "href": "https://example.org/redirect", - "type": "application/hal+json" - } - } - }' - ); - } -} diff --git a/tests/Mollie/API/Endpoints/SettlementCaptureEndpointTest.php b/tests/Mollie/API/Endpoints/SettlementCaptureEndpointTest.php deleted file mode 100644 index 366a66a33..000000000 --- a/tests/Mollie/API/Endpoints/SettlementCaptureEndpointTest.php +++ /dev/null @@ -1,98 +0,0 @@ -mockApiCall( - new Request( - 'GET', - '/v2/settlements/stl_jDk30akdN/captures?limit=5&foo=bar' - ), - new Response( - 200, - [], - '{ - "_embedded": { - "captures": [ - { - "resource": "capture", - "id": "cpt_4qqhO89gsT", - "mode": "live", - "amount": { - "value": "1027.99", - "currency": "EUR" - }, - "settlementAmount": { - "value": "399.00", - "currency": "EUR" - }, - "paymentId": "tr_WDqYK6vllg", - "shipmentId": "shp_3wmsgCJN4U", - "settlementId": "stl_jDk30akdN", - "createdAt": "2018-08-02T09:29:56+00:00", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_WDqYK6vllg/captures/cpt_4qqhO89gsT", - "type": "application/hal+json" - }, - "payment": { - "href": "https://api.mollie.com/v2/payments/tr_WDqYK6vllg", - "type": "application/hal+json" - }, - "shipment": { - "href": "https://api.mollie.com/v2/orders/ord_8wmqcHMN4U/shipments/shp_3wmsgCJN4U", - "type": "application/hal+json" - }, - "settlement": { - "href": "https://api.mollie.com/v2/settlements/stl_jDk30akdN", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/captures-api/get-capture", - "type": "text/html" - } - } - } - ] - }, - "count": 1, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/settlements-api/list-settlement-captures", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.com/v2/settlements/stl_jDk30akdN/captures?limit=50", - "type": "application/hal+json" - }, - "previous": null, - "next": null - } - }' - ) - ); - - $settlement = new Settlement($this->apiClient); - $settlement->id = 'stl_jDk30akdN'; - - $captures = $settlement->captures(5, ['foo' => 'bar']); - - $this->assertInstanceOf(CaptureCollection::class, $captures); - $this->assertCount(1, $captures); - - $capture = $captures[0]; - $this->assertInstanceOf(Capture::class, $capture); - $this->assertEquals("cpt_4qqhO89gsT", $capture->id); - } -} diff --git a/tests/Mollie/API/Endpoints/SettlementChargebackEndpointTest.php b/tests/Mollie/API/Endpoints/SettlementChargebackEndpointTest.php deleted file mode 100644 index f76808490..000000000 --- a/tests/Mollie/API/Endpoints/SettlementChargebackEndpointTest.php +++ /dev/null @@ -1,88 +0,0 @@ -mockApiCall( - new Request( - 'GET', - '/v2/settlements/stl_jDk30akdN/chargebacks?limit=5&foo=bar' - ), - new Response( - 200, - [], - '{ - "count": 1, - "_embedded": { - "chargebacks": [ - { - "resource": "chargeback", - "id": "chb_n9z0tp", - "amount": { - "value": "43.38", - "currency": "USD" - }, - "settlementAmount": { - "value": "-37.14", - "currency": "EUR" - }, - "createdAt": "2018-03-14T17:00:52.0Z", - "reversedAt": null, - "paymentId": "tr_WDqYK6vllg", - "settlementId": "stl_jDk30akdN", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_WDqYK6vllg/chargebacks/chb_n9z0tp", - "type": "application/hal+json" - }, - "payment": { - "href": "https://api.mollie.com/v2/payments/tr_WDqYK6vllg", - "type": "application/hal+json" - }, - "settlement": { - "href": "https://api.mollie.com/v2/settlements/stl_jDk30akdN", - "type": "application/hal+json" - } - } - } - ] - }, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/settlements-api/list-settlement-chargebacks", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.com/v2/settlements/stl_jDk30akdN/chargebacks", - "type": "application/hal+json" - }, - "previous": null, - "next": null - } - }' - ) - ); - - $settlement = new Settlement($this->apiClient); - $settlement->id = 'stl_jDk30akdN'; - - $chargebacks = $settlement->chargebacks(5, ['foo' => 'bar']); - - $this->assertInstanceOf(ChargebackCollection::class, $chargebacks); - $this->assertCount(1, $chargebacks); - - $chargeback = $chargebacks[0]; - $this->assertInstanceOf(Chargeback::class, $chargeback); - $this->assertEquals("chb_n9z0tp", $chargeback->id); - } -} diff --git a/tests/Mollie/API/Endpoints/SettlementEndpointTest.php b/tests/Mollie/API/Endpoints/SettlementEndpointTest.php deleted file mode 100644 index a0e8ae314..000000000 --- a/tests/Mollie/API/Endpoints/SettlementEndpointTest.php +++ /dev/null @@ -1,654 +0,0 @@ -mockApiCall( - new Request( - "GET", - "/v2/settlements/stl_xcaSGAHuRt", - [], - '' - ), - new Response( - 200, - [], - '{ - "resource": "settlement", - "id": "stl_xcaSGAHuRt", - "reference": "1234567.1234.12", - "createdAt": "2018-04-30T04:00:02+00:00", - "settledAt": "2018-05-01T04:00:02+00:00", - "status": "pending", - "amount": { - "value": "1980.98", - "currency": "EUR" - }, - "periods": { - "2018": { - "04": { - "revenue": [ - { - "description": "Creditcard", - "method": "creditcard", - "count": 2, - "amountNet": { - "value": "790.00", - "currency": "EUR" - }, - "amountVat": null, - "amountGross": { - "value": "1000.00", - "currency": "EUR" - } - }, - { - "description": "iDEAL", - "method": "ideal", - "count": 2, - "amountNet": { - "value": "790.00", - "currency": "EUR" - }, - "amountVat": null, - "amountGross": { - "value": "1000.00", - "currency": "EUR" - } - } - ], - "costs": [ - { - "description": "Creditcard", - "method": "creditcard", - "count": 2, - "rate": { - "fixed": { - "value": "0.00", - "currency": "EUR" - }, - "percentage": "1.80" - }, - "amountNet": { - "value": "14.22", - "currency": "EUR" - }, - "amountVat": { - "value": "2.9862", - "currency": "EUR" - }, - "amountGross": { - "value": "17.2062", - "currency": "EUR" - } - }, - { - "description": "Fixed creditcard costs", - "method": "creditcard", - "count": 2, - "rate": { - "fixed": { - "value": "0.25", - "currency": "EUR" - }, - "percentage": "0" - }, - "amountNet": { - "value": "0.50", - "currency": "EUR" - }, - "amountVat": { - "value": "0.105", - "currency": "EUR" - }, - "amountGross": { - "value": "0.605", - "currency": "EUR" - } - }, - { - "description": "Fixed iDEAL costs", - "method": "ideal", - "count": 2, - "rate": { - "fixed": { - "value": "0.25", - "currency": "EUR" - }, - "percentage": "0" - }, - "amountNet": { - "value": "0.50", - "currency": "EUR" - }, - "amountVat": { - "value": "0.105", - "currency": "EUR" - }, - "amountGross": { - "value": "0.605", - "currency": "EUR" - } - }, - { - "description": "Refunds iDEAL", - "method": "refund", - "count": 2, - "rate": { - "fixed": { - "value": "0.25", - "currency": "EUR" - }, - "percentage": "0" - }, - "amountNet": { - "value": "0.50", - "currency": "EUR" - }, - "amountVat": { - "value": "0.105", - "currency": "EUR" - }, - "amountGross": { - "value": "0.605", - "currency": "EUR" - } - } - ] - } - } - }, - "invoiceId": "inv_VseyTUhJSy", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/settlements/stl_xcaSGAHuRt", - "type": "application/hal+json" - }, - "payments": { - "href": "https://api.mollie.com/v2/settlements/stl_xcaSGAHuRt/payments", - "type": "application/hal+json" - }, - "refunds": { - "href": "https://api.mollie.com/v2/settlements/stl_xcaSGAHuRt/refunds", - "type": "application/hal+json" - }, - "chargebacks": { - "href": "https://api.mollie.com/v2/settlements/stl_xcaSGAHuRt/chargebacks", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/settlements-api/get-settlement", - "type": "text/html" - } - } - }' - ) - ); - - /** @var Settlement $settlement */ - $settlement = $this->apiClient->settlements->get("stl_xcaSGAHuRt"); - - $this->assertInstanceOf(Settlement::class, $settlement); - $this->assertEquals("settlement", $settlement->resource); - $this->assertEquals("stl_xcaSGAHuRt", $settlement->id); - $this->assertEquals("1234567.1234.12", $settlement->reference); - $this->assertEquals("2018-04-30T04:00:02+00:00", $settlement->createdAt); - $this->assertEquals("2018-05-01T04:00:02+00:00", $settlement->settledAt); - $this->assertEquals(SettlementStatus::STATUS_PENDING, $settlement->status); - $this->assertEquals((object) ["value" => "1980.98", "currency" => "EUR"], $settlement->amount); - $this->assertNotEmpty($settlement->periods); - $this->assertEquals("inv_VseyTUhJSy", $settlement->invoiceId); - - $selfLink = (object)['href' => 'https://api.mollie.com/v2/settlements/stl_xcaSGAHuRt', 'type' => 'application/hal+json']; - $this->assertEquals($selfLink, $settlement->_links->self); - - $paymentLink = (object)['href' => 'https://api.mollie.com/v2/settlements/stl_xcaSGAHuRt/payments', 'type' => 'application/hal+json']; - $this->assertEquals($paymentLink, $settlement->_links->payments); - - $refundLink = (object)['href' => 'https://api.mollie.com/v2/settlements/stl_xcaSGAHuRt/refunds', 'type' => 'application/hal+json']; - $this->assertEquals($refundLink, $settlement->_links->refunds); - - $chargebackLink = (object)['href' => 'https://api.mollie.com/v2/settlements/stl_xcaSGAHuRt/chargebacks', 'type' => 'application/hal+json']; - $this->assertEquals($chargebackLink, $settlement->_links->chargebacks); - - $documentationLink = (object)['href' => 'https://docs.mollie.com/reference/v2/settlements-api/get-settlement', 'type' => 'text/html']; - $this->assertEquals($documentationLink, $settlement->_links->documentation); - } - - public function testListSettlement() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/settlements", - [], - '' - ), - new Response( - 200, - [], - '{ - "_embedded": { - "settlements": [ - { - "resource": "settlement", - "id": "stl_xcaSGAHuRt", - "reference": "1234567.1234.12", - "createdAt": "2018-04-30T04:00:02+00:00", - "settledAt": "2018-05-01T04:00:02+00:00", - "status": "pending", - "amount": { - "value": "1980.98", - "currency": "EUR" - }, - "periods": { - "2018": { - "04": { - "revenue": [ - { - "description": "Creditcard", - "method": "creditcard", - "count": 2, - "amountNet": { - "value": "790.00", - "currency": "EUR" - }, - "amountVat": null, - "amountGross": { - "value": "1000.00", - "currency": "EUR" - } - }, - { - "description": "iDEAL", - "method": "ideal", - "count": 2, - "amountNet": { - "value": "790.00", - "currency": "EUR" - }, - "amountVat": null, - "amountGross": { - "value": "1000.00", - "currency": "EUR" - } - } - ], - "costs": [ - { - "description": "Creditcard", - "method": "creditcard", - "count": 2, - "rate": { - "fixed": { - "value": "0.00", - "currency": "EUR" - }, - "percentage": "1.80" - }, - "amountNet": { - "value": "14.22", - "currency": "EUR" - }, - "amountVat": { - "value": "2.9862", - "currency": "EUR" - }, - "amountGross": { - "value": "17.2062", - "currency": "EUR" - } - }, - { - "description": "Fixed creditcard costs", - "method": "creditcard", - "count": 2, - "rate": { - "fixed": { - "value": "0.25", - "currency": "EUR" - }, - "percentage": "0" - }, - "amountNet": { - "value": "0.50", - "currency": "EUR" - }, - "amountVat": { - "value": "0.105", - "currency": "EUR" - }, - "amountGross": { - "value": "0.605", - "currency": "EUR" - } - }, - { - "description": "Fixed iDEAL costs", - "method": "ideal", - "count": 2, - "rate": { - "fixed": { - "value": "0.25", - "currency": "EUR" - }, - "percentage": "0" - }, - "amountNet": { - "value": "0.50", - "currency": "EUR" - }, - "amountVat": { - "value": "0.105", - "currency": "EUR" - }, - "amountGross": { - "value": "0.605", - "currency": "EUR" - } - }, - { - "description": "Refunds iDEAL", - "method": "refund", - "count": 2, - "rate": { - "fixed": { - "value": "0.25", - "currency": "EUR" - }, - "percentage": "0" - }, - "amountNet": { - "value": "0.50", - "currency": "EUR" - }, - "amountVat": { - "value": "0.105", - "currency": "EUR" - }, - "amountGross": { - "value": "0.605", - "currency": "EUR" - } - } - ] - } - } - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/settlements/stl_xcaSGAHuRt", - "type": "application/hal+json" - }, - "payments": { - "href": "https://api.mollie.com/v2/settlements/stl_xcaSGAHuRt/payments", - "type": "application/hal+json" - }, - "refunds": { - "href": "https://api.mollie.com/v2/settlements/stl_xcaSGAHuRt/refunds", - "type": "application/hal+json" - }, - "chargebacks": { - "href": "https://api.mollie.com/v2/settlements/stl_xcaSGAHuRt/chargebacks", - "type": "application/hal+json" - } - } - } - ] - }, - "count": 1, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/settlements-api/list-settlements", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.nl/v2/settlements", - "type": "application/hal+json" - }, - "previous": null, - "next": { - "href": "https://api.mollie.nl/v2/settlements?from=stl_xcaSGAHuRt&limit=1&previous=stl_xcaPACKpLs", - "type": "application/hal+json" - } - } - }' - ) - ); - - /** @var SettlementCollection $settlements */ - $settlements = $this->apiClient->settlements->page(); - $this->assertInstanceOf(SettlementCollection::class, $settlements); - - $documentationLink = (object)['href' => 'https://docs.mollie.com/reference/v2/settlements-api/list-settlements', 'type' => 'text/html']; - $this->assertEquals($documentationLink, $settlements->_links->documentation); - - $selfLink = (object)['href' => 'https://api.mollie.nl/v2/settlements', 'type' => 'application/hal+json']; - $this->assertEquals($selfLink, $settlements->_links->self); - - $this->assertEmpty($settlements->_links->previous); - - $nextLink = (object)['href' => 'https://api.mollie.nl/v2/settlements?from=stl_xcaSGAHuRt&limit=1&previous=stl_xcaPACKpLs', 'type' => 'application/hal+json']; - $this->assertEquals($nextLink, $settlements->_links->next); - - foreach ($settlements as $settlement) { - $this->assertInstanceOf(Settlement::class, $settlement); - $this->assertEquals("settlement", $settlement->resource); - $this->assertNotEmpty($settlement->periods); - } - } - - public function testIterateSettlement() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/settlements", - [], - '' - ), - new Response( - 200, - [], - '{ - "_embedded": { - "settlements": [ - { - "resource": "settlement", - "id": "stl_xcaSGAHuRt", - "reference": "1234567.1234.12", - "createdAt": "2018-04-30T04:00:02+00:00", - "settledAt": "2018-05-01T04:00:02+00:00", - "status": "pending", - "amount": { - "value": "1980.98", - "currency": "EUR" - }, - "periods": { - "2018": { - "04": { - "revenue": [ - { - "description": "Creditcard", - "method": "creditcard", - "count": 2, - "amountNet": { - "value": "790.00", - "currency": "EUR" - }, - "amountVat": null, - "amountGross": { - "value": "1000.00", - "currency": "EUR" - } - }, - { - "description": "iDEAL", - "method": "ideal", - "count": 2, - "amountNet": { - "value": "790.00", - "currency": "EUR" - }, - "amountVat": null, - "amountGross": { - "value": "1000.00", - "currency": "EUR" - } - } - ], - "costs": [ - { - "description": "Creditcard", - "method": "creditcard", - "count": 2, - "rate": { - "fixed": { - "value": "0.00", - "currency": "EUR" - }, - "percentage": "1.80" - }, - "amountNet": { - "value": "14.22", - "currency": "EUR" - }, - "amountVat": { - "value": "2.9862", - "currency": "EUR" - }, - "amountGross": { - "value": "17.2062", - "currency": "EUR" - } - }, - { - "description": "Fixed creditcard costs", - "method": "creditcard", - "count": 2, - "rate": { - "fixed": { - "value": "0.25", - "currency": "EUR" - }, - "percentage": "0" - }, - "amountNet": { - "value": "0.50", - "currency": "EUR" - }, - "amountVat": { - "value": "0.105", - "currency": "EUR" - }, - "amountGross": { - "value": "0.605", - "currency": "EUR" - } - }, - { - "description": "Fixed iDEAL costs", - "method": "ideal", - "count": 2, - "rate": { - "fixed": { - "value": "0.25", - "currency": "EUR" - }, - "percentage": "0" - }, - "amountNet": { - "value": "0.50", - "currency": "EUR" - }, - "amountVat": { - "value": "0.105", - "currency": "EUR" - }, - "amountGross": { - "value": "0.605", - "currency": "EUR" - } - }, - { - "description": "Refunds iDEAL", - "method": "refund", - "count": 2, - "rate": { - "fixed": { - "value": "0.25", - "currency": "EUR" - }, - "percentage": "0" - }, - "amountNet": { - "value": "0.50", - "currency": "EUR" - }, - "amountVat": { - "value": "0.105", - "currency": "EUR" - }, - "amountGross": { - "value": "0.605", - "currency": "EUR" - } - } - ] - } - } - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/settlements/stl_xcaSGAHuRt", - "type": "application/hal+json" - }, - "payments": { - "href": "https://api.mollie.com/v2/settlements/stl_xcaSGAHuRt/payments", - "type": "application/hal+json" - }, - "refunds": { - "href": "https://api.mollie.com/v2/settlements/stl_xcaSGAHuRt/refunds", - "type": "application/hal+json" - }, - "chargebacks": { - "href": "https://api.mollie.com/v2/settlements/stl_xcaSGAHuRt/chargebacks", - "type": "application/hal+json" - } - } - } - ] - }, - "count": 1, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/settlements-api/list-settlements", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.nl/v2/settlements", - "type": "application/hal+json" - }, - "previous": null, - "next": null - } - }' - ) - ); - - foreach ($this->apiClient->settlements->iterator() as $settlement) { - $this->assertInstanceOf(Settlement::class, $settlement); - $this->assertEquals("settlement", $settlement->resource); - $this->assertNotEmpty($settlement->periods); - } - } -} diff --git a/tests/Mollie/API/Endpoints/SettlementPaymentsEndpointTest.php b/tests/Mollie/API/Endpoints/SettlementPaymentsEndpointTest.php deleted file mode 100644 index 0a9f8d71e..000000000 --- a/tests/Mollie/API/Endpoints/SettlementPaymentsEndpointTest.php +++ /dev/null @@ -1,90 +0,0 @@ -mockApiCall( - new Request( - 'GET', - '/v2/settlements/stl_jDk30akdN/payments?limit=5&foo=bar' - ), - new Response( - 200, - [], - '{ - "count": 1, - "_embedded": { - "payments": [ - { - "resource": "payment", - "id": "tr_7UhSN1zuXS", - "mode": "test", - "createdAt": "2018-02-12T11:58:35.0Z", - "expiresAt": "2018-02-12T12:13:35.0Z", - "status": "open", - "isCancelable": false, - "amount": { - "value": "75.00", - "currency": "GBP" - }, - "description": "Order #12345", - "method": "ideal", - "metadata": null, - "details": null, - "profileId": "pfl_QkEhN94Ba", - "settlementId": "stl_jDk30akdN", - "redirectUrl": "https://webshop.example.org/order/12345/", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_7UhSN1zuXS", - "type": "application/hal+json" - }, - "settlement": { - "href": "https://api.mollie.com/v2/settlements/stl_jDk30akdN", - "type": "application/hal+json" - } - } - } - ] - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/settlements/stl_jDk30akdN/payments?limit=5", - "type": "application/hal+json" - }, - "previous": null, - "next": { - "href": "https://api.mollie.com/v2/settlements/stl_jDk30akdN/payments?from=tr_SDkzMggpvx&limit=5", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/settlements-api/list-settlement-payments", - "type": "text/html" - } - } - }' - ) - ); - - $settlement = new Settlement($this->apiClient); - $settlement->id = 'stl_jDk30akdN'; - - $payments = $settlement->payments(5, ['foo' => 'bar']); - - $this->assertInstanceOf(PaymentCollection::class, $payments); - $this->assertCount(1, $payments); - - $payment = $payments[0]; - $this->assertInstanceOf(Payment::class, $payment); - $this->assertEquals("tr_7UhSN1zuXS", $payment->id); - } -} diff --git a/tests/Mollie/API/Endpoints/SettlementRefundEndpointTest.php b/tests/Mollie/API/Endpoints/SettlementRefundEndpointTest.php deleted file mode 100644 index 261432c54..000000000 --- a/tests/Mollie/API/Endpoints/SettlementRefundEndpointTest.php +++ /dev/null @@ -1,92 +0,0 @@ -mockApiCall( - new Request( - 'GET', - '/v2/settlements/stl_jDk30akdN/refunds?limit=5&foo=bar' - ), - new Response( - 200, - [], - '{ - "_embedded": { - "refunds": [ - { - "resource": "refund", - "id": "re_3aKhkUNigy", - "amount": { - "value": "10.00", - "currency": "EUR" - }, - "status": "refunded", - "createdAt": "2018-08-30T07:59:02+00:00", - "description": "Order #33", - "paymentId": "tr_maJaG2j8OM", - "settlementAmount": { - "value": "-10.00", - "currency": "EUR" - }, - "settlementId": "stl_jDk30akdN", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/payments/tr_maJaG2j8OM/refunds/re_3aKhkUNigy", - "type": "application/hal+json" - }, - "payment": { - "href": "https://api.mollie.com/v2/payments/tr_maJaG2j8OM", - "type": "application/hal+json" - }, - "settlement": { - "href": "https://api.mollie.com/v2/settlements/stl_jDk30akdN", - "type": "application/hal+json" - } - } - }, - { } - ] - }, - "count": 1, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/settlements-api/list-settlement-refunds", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.com/v2/settlements/stl_jDk30akdN/refunds?limit=50", - "type": "application/hal+json" - }, - "previous": null, - "next": null - } - }' - ) - ); - - $settlement = new Settlement($this->apiClient); - $settlement->id = 'stl_jDk30akdN'; - - $refunds = $settlement->refunds(5, ['foo' => 'bar']); - - $this->assertInstanceOf(RefundCollection::class, $refunds); - $this->assertCount(2, $refunds); - - $refund = $refunds[0]; - $this->assertInstanceOf(Refund::class, $refund); - $this->assertEquals("re_3aKhkUNigy", $refund->id); - } -} diff --git a/tests/Mollie/API/Endpoints/ShipmentEndpointTest.php b/tests/Mollie/API/Endpoints/ShipmentEndpointTest.php deleted file mode 100644 index b9c4dcbd9..000000000 --- a/tests/Mollie/API/Endpoints/ShipmentEndpointTest.php +++ /dev/null @@ -1,564 +0,0 @@ -mockApiCall( - new Request( - "POST", - "/v2/orders/ord_pbjz8x/shipments", - [], - '{ - "lines": [ - { - "id": "odl_dgtxyl", - "quantity": 1 - }, - { - "id": "odl_jp31jz" - } - ] - }' - ), - new Response( - 201, - [], - $this->getShipmentResponseFixture("shp_3wmsgCJN4U", "ord_pbjz8x") - ) - ); - - $order = $this->getOrder('ord_pbjz8x'); - $shipment = $order->createShipment([ - 'lines' => [ - [ - 'id' => 'odl_dgtxyl', - 'quantity' => 1, - ], - [ - 'id' => 'odl_jp31jz', - ], - ], - ]); - - $this->assertShipment($shipment, 'shp_3wmsgCJN4U', 'ord_pbjz8x'); - } - - public function testCreateShipmentUsingShorthand() - { - $this->mockApiCall( - new Request( - "POST", - "/v2/orders/ord_pbjz8x/shipments", - [], - '{ - "lines": [] - }' - ), - new Response( - 201, - [], - $this->getShipmentResponseFixture("shp_3wmsgCJN4U", "ord_pbjz8x") - ) - ); - - $order = $this->getOrder('ord_pbjz8x'); - $shipment = $order->shipAll(); - - $this->assertShipment($shipment, 'shp_3wmsgCJN4U', 'ord_pbjz8x'); - } - - public function testGetShipment() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/orders/ord_pbjz8x/shipments/shp_3wmsgCJN4U" - ), - new Response( - 200, - [], - $this->getShipmentResponseFixture("shp_3wmsgCJN4U", "ord_pbjz8x") - ) - ); - - $order = $this->getOrder('ord_pbjz8x'); - $shipment = $this->apiClient->shipments->getFor($order, "shp_3wmsgCJN4U"); - - $this->assertShipment($shipment, 'shp_3wmsgCJN4U', 'ord_pbjz8x'); - } - - public function testGetShipmentOnOrderResource() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/orders/ord_pbjz8x/shipments/shp_3wmsgCJN4U" - ), - new Response( - 200, - [], - $this->getShipmentResponseFixture("shp_3wmsgCJN4U", "ord_pbjz8x") - ) - ); - - $order = $this->getOrder('ord_pbjz8x'); - $shipment = $order->getShipment('shp_3wmsgCJN4U'); - - $this->assertShipment($shipment, 'shp_3wmsgCJN4U', 'ord_pbjz8x'); - } - - public function testListShipmentsViaShipmentEndpoint() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/orders/ord_pbjz8x/shipments" - ), - new Response( - 200, - [], - '{ - "count": 2, - "_embedded": { - "shipments": [ - ' . $this->getShipmentResponseFixture("shp_3wmsgCJN4U", "ord_pbjz8x") . ', - ' . $this->getShipmentResponseFixture("shp_kjh234CASX", "ord_pbjz8x") . ' - ] - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/order/ord_pbjz8x/shipments", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/shipments-api/list-shipments", - "type": "text/html" - } - } - }' - ) - ); - - $order = $this->getOrder('ord_pbjz8x'); - $shipments = $this->apiClient->shipments->listFor($order); - - $this->assertInstanceOf(ShipmentCollection::class, $shipments); - $this->assertShipment($shipments[0], 'shp_3wmsgCJN4U', 'ord_pbjz8x'); - $this->assertShipment($shipments[1], 'shp_kjh234CASX', 'ord_pbjz8x'); - } - - public function testListShipmentsOnOrderResource() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/orders/ord_pbjz8x/shipments" - ), - new Response( - 200, - [], - '{ - "count": 2, - "_embedded": { - "shipments": [ - ' . $this->getShipmentResponseFixture("shp_3wmsgCJN4U", "ord_pbjz8x") . ', - ' . $this->getShipmentResponseFixture("shp_kjh234CASX", "ord_pbjz8x") . ' - ] - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/order/ord_pbjz8x/shipments", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/shipments-api/list-shipments", - "type": "text/html" - } - } - }' - ) - ); - - $order = $this->getOrder('ord_pbjz8x'); - - $shipments = $order->shipments(); - - $this->assertInstanceOf(ShipmentCollection::class, $shipments); - $this->assertShipment($shipments[0], 'shp_3wmsgCJN4U', 'ord_pbjz8x'); - $this->assertShipment($shipments[1], 'shp_kjh234CASX', 'ord_pbjz8x'); - } - - public function testUpdateShipmentTrackingInfo() - { - $this->mockApiCall( - new Request( - "PATCH", - "/v2/orders/ord_pbjz8x/shipments/shp_3wmsgCJN4U", - [], - '{ - "tracking": { - "carrier": "PostNL", - "code": "3SKABA000000000", - "url": "http://postnl.nl/tracktrace/?B=3SKABA000000000&P=1016EE&D=NL&T=C" - } - }' - ), - new Response( - 200, - [], - $this->getShipmentResponseFixture( - "shp_3wmsgCJN4U", - "ord_pbjz8x", - OrderLineStatus::STATUS_SHIPPING, - '"tracking": { - "carrier": "PostNL", - "code": "3SKABA000000000", - "url": "http://postnl.nl/tracktrace/?B=3SKABA000000000&P=1016EE&D=NL&T=C" - },' - ) - ) - ); - - $shipment = $this->getShipment('shp_3wmsgCJN4U', 'ord_pbjz8x', OrderLineStatus::STATUS_SHIPPING); - - $shipment->tracking = [ - 'carrier' => 'PostNL', - 'code' => '3SKABA000000000', - 'url' => 'http://postnl.nl/tracktrace/?B=3SKABA000000000&P=1016EE&D=NL&T=C', - ]; - $shipment = $shipment->update(); - - $this->assertShipment($shipment, 'shp_3wmsgCJN4U', 'ord_pbjz8x'); - - $this->assertEquals((object) [ - 'carrier' => 'PostNL', - 'code' => '3SKABA000000000', - 'url' => 'http://postnl.nl/tracktrace/?B=3SKABA000000000&P=1016EE&D=NL&T=C', - ], $shipment->tracking); - } - - protected function assertShipment($shipment, $shipment_id, $order_id) - { - $this->assertInstanceOf(Shipment::class, $shipment); - $this->assertEquals("shipment", $shipment->resource); - $this->assertEquals($shipment_id, $shipment->id); - $this->assertEquals($order_id, $shipment->orderId); - $this->assertEquals('2018-08-02T09:29:56+00:00', $shipment->createdAt); - $this->assertLinkObject( - "https://api.mollie.com/v2/orders/ord_pbjz8x/shipments/{$shipment_id}", - 'application/hal+json', - $shipment->_links->self - ); - $this->assertLinkObject( - 'https://api.mollie.com/v2/orders/ord_pbjz8x', - 'application/hal+json', - $shipment->_links->order - ); - $this->assertLinkObject( - 'https://docs.mollie.com/reference/v2/shipments-api/get-shipment', - 'text/html', - $shipment->_links->documentation - ); - - $line1 = $shipment->lines()[0]; - $this->assertEquals('orderline', $line1->resource); - $this->assertEquals('odl_dgtxyl', $line1->id); - $this->assertEquals('ord_pbjz8x', $line1->orderId); - $this->assertEquals('LEGO 42083 Bugatti Chiron', $line1->name); - $this->assertEquals('https://shop.lego.com/nl-NL/Bugatti-Chiron-42083', $line1->productUrl); - $this->assertEquals('https://sh-s7-live-s.legocdn.com/is/image//LEGO/42083_alt1?$main$', $line1->imageUrl); - $this->assertEquals('5702016116977', $line1->sku); - $this->assertEquals('physical', $line1->type); - $this->assertEquals(OrderLineStatus::STATUS_SHIPPING, $line1->status); - $this->assertEquals(2, $line1->quantity); - $this->assertEquals('2018-08-02T09:29:56+00:00', $line1->createdAt); - $this->assertEquals('21.00', $line1->vatRate); - $this->assertAmountObject('121.14', 'EUR', $line1->vatAmount); - $this->assertAmountObject('399.00', 'EUR', $line1->unitPrice); - $this->assertAmountObject('100.00', 'EUR', $line1->discountAmount); - $this->assertAmountObject('698.00', 'EUR', $line1->totalAmount); - - $line2 = $shipment->lines()[1]; - $this->assertEquals('orderline', $line2->resource); - $this->assertEquals('odl_jp31jz', $line2->id); - $this->assertEquals('ord_pbjz8x', $line2->orderId); - $this->assertEquals('LEGO 42056 Porsche 911 GT3 RS', $line2->name); - $this->assertEquals('https://shop.lego.com/nl-NL/Porsche-911-GT3-RS-42056', $line2->productUrl); - $this->assertEquals('https://sh-s7-live-s.legocdn.com/is/image/LEGO/42056?$PDPDefault$', $line2->imageUrl); - $this->assertEquals('5702015594028', $line2->sku); - $this->assertEquals('digital', $line2->type); - $this->assertEquals(OrderLineStatus::STATUS_SHIPPING, $line2->status); - $this->assertEquals(1, $line2->quantity); - $this->assertEquals('2018-08-02T09:29:56+00:00', $line2->createdAt); - $this->assertEquals('21.00', $line2->vatRate); - $this->assertAmountObject('57.27', 'EUR', $line2->vatAmount); - $this->assertAmountObject('329.99', 'EUR', $line2->unitPrice); - $this->assertAmountObject('329.99', 'EUR', $line2->totalAmount); - } - - protected function getOrder($id) - { - $orderJson = $this->getOrderResponseFixture($id); - - return $this->copy(json_decode($orderJson), new Order($this->apiClient)); - } - - protected function getShipment($shipment_id, $order_id, $orderLineStatus = OrderLineStatus::STATUS_SHIPPING) - { - $shipmentJson = $this->getShipmentResponseFixture($shipment_id, $order_id, $orderLineStatus); - - return $this->copy(json_decode($shipmentJson), new Shipment($this->apiClient)); - } - - protected function getOrderResponseFixture($order_id, $order_status = OrderStatus::STATUS_CREATED) - { - return str_replace( - "<>", - $order_id, - '{ - "resource": "order", - "id": "<>", - "amount": { - "value": "1027.99", - "currency": "EUR" - }, - "amountCaptured": { - "value": "0.00", - "currency": "EUR" - }, - "amountRefunded": { - "value": "0.00", - "currency": "EUR" - }, - "status": "' . $order_status . '", - "metadata": { - "order_id": "1337", - "description": "Lego cars" - }, - "consumerDateOfBirth": "1958-01-31", - "createdAt": "2018-08-02T09:29:56+00:00", - "mode": "live", - "billingAddress": { - "streetAndNumber": "Keizersgracht 313", - "postalCode": "1016 EE", - "city": "Amsterdam", - "country": "nl", - "givenName": "Luke", - "familyName": "Skywalker", - "email": "luke@skywalker.com" - }, - "shippingAddress": { - "streetAndNumber": "Keizersgracht 313", - "postalCode": "1016 EE", - "city": "Amsterdam", - "country": "nl", - "givenName": "Luke", - "familyName": "Skywalker", - "email": "luke@skywalker.com" - }, - "orderNumber": "1337", - "locale": "nl_NL", - "method" : "klarnapaylater", - "redirectUrl": "https://example.org/redirect", - "webhookUrl": "https://example.org/webhook", - "lines": [ - { - "resource": "orderline", - "id": "odl_dgtxyl", - "orderId": "<>", - "name": "LEGO 42083 Bugatti Chiron", - "productUrl": "https://shop.lego.com/nl-NL/Bugatti-Chiron-42083", - "imageUrl": "https://sh-s7-live-s.legocdn.com/is/image//LEGO/42083_alt1?$main$", - "sku": "5702016116977", - "type": "physical", - "status": "created", - "quantity": 2, - "unitPrice": { - "value": "399.00", - "currency": "EUR" - }, - "vatRate": "21.00", - "vatAmount": { - "value": "121.14", - "currency": "EUR" - }, - "discountAmount": { - "value": "100.00", - "currency": "EUR" - }, - "totalAmount": { - "value": "698.00", - "currency": "EUR" - }, - "createdAt": "2018-08-02T09:29:56+00:00", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/orders/<>/orderlines/odl_dgtxyl", - "type": "application/hal+json" - } - } - }, - { - "resource": "orderline", - "id": "odl_jp31jz", - "orderId": "<>", - "name": "LEGO 42056 Porsche 911 GT3 RS", - "productUrl": "https://shop.lego.com/nl-NL/Porsche-911-GT3-RS-42056", - "imageUrl": "https://sh-s7-live-s.legocdn.com/is/image/LEGO/42056?$PDPDefault$", - "sku": "5702015594028", - "type": "digital", - "status": "created", - "quantity": 1, - "unitPrice": { - "value": "329.99", - "currency": "EUR" - }, - "vatRate": "21.00", - "vatAmount": { - "value": "57.27", - "currency": "EUR" - }, - "totalAmount": { - "value": "329.99", - "currency": "EUR" - }, - "createdAt": "2018-08-02T09:29:56+00:00", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/orders/<>/orderlines/odl_jp31jz", - "type": "application/hal+json" - } - } - } - ], - "_links": { - "self": { - "href": "https://api.mollie.com/v2/orders/<>", - "type": "application/hal+json" - }, - "checkout": { - "href": "https://www.mollie.com/payscreen/select-method/7UhSN1zuXS", - "type": "text/html" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/orders-api/get-order", - "type": "text/html" - } - } - }' - ); - } - - protected function getShipmentResponseFixture($shipment_id, $order_id, $orderline_status = OrderLineStatus::STATUS_SHIPPING, $tracking_info = '') - { - return str_replace( - [ - "<>", - "<>", - "<>", - "<>", - ], - [ - $order_id, - $shipment_id, - $orderline_status, - $tracking_info, - ], - '{ - "resource": "shipment", - "id": "<>", - "orderId": "<>", - "createdAt": "2018-08-02T09:29:56+00:00", - <> - "lines": [ - { - "resource": "orderline", - "id": "odl_dgtxyl", - "orderId": "<>", - "name": "LEGO 42083 Bugatti Chiron", - "productUrl": "https://shop.lego.com/nl-NL/Bugatti-Chiron-42083", - "imageUrl": "https://sh-s7-live-s.legocdn.com/is/image//LEGO/42083_alt1?$main$", - "sku": "5702016116977", - "type": "physical", - "status": "<>", - "quantity": 2, - "unitPrice": { - "value": "399.00", - "currency": "EUR" - }, - "vatRate": "21.00", - "vatAmount": { - "value": "121.14", - "currency": "EUR" - }, - "discountAmount": { - "value": "100.00", - "currency": "EUR" - }, - "totalAmount": { - "value": "698.00", - "currency": "EUR" - }, - "createdAt": "2018-08-02T09:29:56+00:00" - }, - { - "resource": "orderline", - "id": "odl_jp31jz", - "orderId": "<>", - "name": "LEGO 42056 Porsche 911 GT3 RS", - "productUrl": "https://shop.lego.com/nl-NL/Porsche-911-GT3-RS-42056", - "imageUrl": "https://sh-s7-live-s.legocdn.com/is/image/LEGO/42056?$PDPDefault$", - "sku": "5702015594028", - "type": "digital", - "status": "<>", - "quantity": 1, - "unitPrice": { - "value": "329.99", - "currency": "EUR" - }, - "vatRate": "21.00", - "vatAmount": { - "value": "57.27", - "currency": "EUR" - }, - "totalAmount": { - "value": "329.99", - "currency": "EUR" - }, - "createdAt": "2018-08-02T09:29:56+00:00" - } - ], - "_links": { - "self": { - "href": "https://api.mollie.com/v2/orders/<>/shipments/<>", - "type": "application/hal+json" - }, - "order": { - "href": "https://api.mollie.com/v2/orders/<>", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/shipments-api/get-shipment", - "type": "text/html" - } - } - }' - ); - } -} diff --git a/tests/Mollie/API/Endpoints/SubscriptionEndpointTest.php b/tests/Mollie/API/Endpoints/SubscriptionEndpointTest.php deleted file mode 100644 index 66b2f4c75..000000000 --- a/tests/Mollie/API/Endpoints/SubscriptionEndpointTest.php +++ /dev/null @@ -1,556 +0,0 @@ -mockApiCall( - new Request('POST', '/v2/customers/cst_FhQJRw4s2n/subscriptions'), - new Response( - 200, - [], - '{ - "resource": "subscription", - "id": "sub_wByQa6efm6", - "mode": "test", - "createdAt": "2018-04-24T11:41:55+00:00", - "status": "active", - "amount": { - "value": "10.00", - "currency": "EUR" - }, - "description": "Order 1234", - "method": null, - "times": null, - "interval": "1 month", - "startDate": "2018-04-24", - "webhookUrl": null, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n/subscriptions/sub_wByQa6efm6", - "type": "application/hal+json" - }, - "customer": { - "href": "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/subscriptions-api/create-subscription", - "type": "text/html" - } - } - }' - ) - ); - - $customer = $this->getCustomer(); - - /** @var Subscription $subscription */ - $subscription = $customer->createSubscription([ - "amount" => [ - "value" => "10.00", - "currency" => "EUR", - ], - "interval" => "1 month", - "description" => "Order 1234", - ]); - - $this->assertInstanceOf(Subscription::class, $subscription); - $this->assertEquals("subscription", $subscription->resource); - $this->assertEquals("sub_wByQa6efm6", $subscription->id); - $this->assertEquals("test", $subscription->mode); - $this->assertEquals("2018-04-24T11:41:55+00:00", $subscription->createdAt); - $this->assertEquals(SubscriptionStatus::STATUS_ACTIVE, $subscription->status); - $this->assertEquals((object)["value" => "10.00", "currency" => "EUR"], $subscription->amount); - $this->assertEquals("Order 1234", $subscription->description); - $this->assertNull($subscription->method); - $this->assertNull($subscription->times); - $this->assertEquals("1 month", $subscription->interval); - $this->assertEquals("2018-04-24", $subscription->startDate); - - $selfLink = (object)["href" => "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n/subscriptions/sub_wByQa6efm6", "type" => "application/hal+json"]; - $this->assertEquals($selfLink, $subscription->_links->self); - - $customerLink = (object)["href" => "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n", "type" => "application/hal+json"]; - $this->assertEquals($customerLink, $subscription->_links->customer); - - $documentationLink = (object)["href" => "https://docs.mollie.com/reference/v2/subscriptions-api/create-subscription", "type" => "text/html"]; - $this->assertEquals($documentationLink, $subscription->_links->documentation); - } - - public function testGetWorks() - { - $this->mockApiCall( - new Request('GET', '/v2/customers/cst_FhQJRw4s2n/subscriptions/sub_wByQa6efm6'), - new Response( - 200, - [], - '{ - "resource": "subscription", - "id": "sub_wByQa6efm6", - "mode": "test", - "createdAt": "2018-04-24T11:41:55+00:00", - "status": "active", - "amount": { - "value": "10.00", - "currency": "EUR" - }, - "description": "Order 1234", - "method": null, - "times": null, - "interval": "1 month", - "startDate": "2018-04-24", - "webhookUrl": null, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n/subscriptions/sub_wByQa6efm6", - "type": "application/hal+json" - }, - "customer": { - "href": "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/subscriptions-api/get-subscription", - "type": "text/html" - } - } - }' - ) - ); - - $customer = $this->getCustomer(); - - /** @var Subscription $subscription */ - $subscription = $customer->getSubscription("sub_wByQa6efm6"); - - $this->assertInstanceOf(Subscription::class, $subscription); - $this->assertEquals("subscription", $subscription->resource); - $this->assertEquals("sub_wByQa6efm6", $subscription->id); - $this->assertEquals("test", $subscription->mode); - $this->assertEquals("2018-04-24T11:41:55+00:00", $subscription->createdAt); - $this->assertEquals(SubscriptionStatus::STATUS_ACTIVE, $subscription->status); - $this->assertEquals((object)["value" => "10.00", "currency" => "EUR"], $subscription->amount); - $this->assertEquals("Order 1234", $subscription->description); - $this->assertNull($subscription->method); - $this->assertNull($subscription->times); - $this->assertEquals("1 month", $subscription->interval); - $this->assertEquals("2018-04-24", $subscription->startDate); - - $selfLink = (object)["href" => "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n/subscriptions/sub_wByQa6efm6", "type" => "application/hal+json"]; - $this->assertEquals($selfLink, $subscription->_links->self); - - $customerLink = (object)["href" => "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n", "type" => "application/hal+json"]; - $this->assertEquals($customerLink, $subscription->_links->customer); - - $documentationLink = (object)["href" => "https://docs.mollie.com/reference/v2/subscriptions-api/get-subscription", "type" => "text/html"]; - $this->assertEquals($documentationLink, $subscription->_links->documentation); - } - - public function testListWorks() - { - $this->mockApiCall( - new Request('GET', '/v2/customers/cst_FhQJRw4s2n/subscriptions'), - new Response( - 200, - [], - '{ - "_embedded": { - "subscriptions": [{ - "resource": "subscription", - "id": "sub_wByQa6efm6", - "mode": "test", - "createdAt": "2018-04-24T11:41:55+00:00", - "status": "active", - "amount": { - "value": "10.00", - "currency": "EUR" - }, - "description": "Order 1234", - "method": null, - "times": null, - "interval": "1 month", - "startDate": "2018-04-24", - "webhookUrl": null, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n/subscriptions/sub_wByQa6efm6", - "type": "application/hal+json" - }, - "customer": { - "href": "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n", - "type": "application/hal+json" - } - } - }] - }, - "count": 1, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/subscriptions-api/list-subscriptions", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n/subscriptions?limit=50", - "type": "application/hal+json" - }, - "previous": null, - "next": null - } - }' - ) - ); - - $customer = $this->getCustomer(); - - $subscriptions = $customer->subscriptions(); - - $this->assertInstanceOf(SubscriptionCollection::class, $subscriptions); - - $this->assertEquals(count($subscriptions), $subscriptions->count); - - $documentationLink = (object)["href" => "https://docs.mollie.com/reference/v2/subscriptions-api/list-subscriptions", "type" => "text/html"]; - $this->assertEquals($documentationLink, $subscriptions->_links->documentation); - - $selfLink = (object)["href" => "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n/subscriptions?limit=50", "type" => "application/hal+json"]; - $this->assertEquals($selfLink, $subscriptions->_links->self); - - foreach ($subscriptions as $subscription) { - $this->assertInstanceOf(Subscription::class, $subscription); - $this->assertEquals("subscription", $subscription->resource); - $this->assertNotEmpty($subscription->createdAt); - } - } - - public function testCancelViaCustomerResourceWorks() - { - $this->mockApiCall( - new Request('DELETE', '/v2/customers/cst_FhQJRw4s2n/subscriptions/sub_wByQa6efm6'), - new Response( - 200, - [], - '{ - "resource": "subscription", - "id": "sub_wByQa6efm6", - "mode": "test", - "createdAt": "2018-04-24T11:41:55+00:00", - "status": "canceled", - "amount": { - "value": "10.00", - "currency": "EUR" - }, - "description": "Order 1234", - "method": null, - "times": null, - "interval": "1 month", - "startDate": "2018-04-24", - "webhookUrl": null, - "canceledAt": "2018-04-24T12:31:32+00:00", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n/subscriptions/sub_wByQa6efm6", - "type": "application/hal+json" - }, - "customer": { - "href": "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/subscriptions-api/cancel-subscription", - "type": "text/html" - } - } - }' - ) - ); - - $customer = $this->getCustomer(); - - /** @var Subscription $subscription */ - $subscription = $customer->cancelSubscription("sub_wByQa6efm6"); - - $this->assertInstanceOf(Subscription::class, $subscription); - $this->assertEquals("subscription", $subscription->resource); - $this->assertEquals("sub_wByQa6efm6", $subscription->id); - $this->assertEquals("test", $subscription->mode); - $this->assertEquals(SubscriptionStatus::STATUS_CANCELED, $subscription->status); - $this->assertEquals("2018-04-24T11:41:55+00:00", $subscription->createdAt); - $this->assertEquals("2018-04-24T12:31:32+00:00", $subscription->canceledAt); - - - $selfLink = (object)["href" => "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n/subscriptions/sub_wByQa6efm6", "type" => "application/hal+json"]; - $this->assertEquals($selfLink, $subscription->_links->self); - - $customerLink = (object)["href" => "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n", "type" => "application/hal+json"]; - $this->assertEquals($customerLink, $subscription->_links->customer); - - $documentationLink = (object)["href" => "https://docs.mollie.com/reference/v2/subscriptions-api/cancel-subscription", "type" => "text/html"]; - $this->assertEquals($documentationLink, $subscription->_links->documentation); - } - - public function testCancelOnSubscriptionResourceWorks($value = '') - { - $this->mockApiCall( - new Request('DELETE', '/v2/customers/cst_VhjQebNW5j/subscriptions/sub_DRjwaT5qHx'), - new Response( - 200, - [], - '{ - "resource": "subscription", - "id": "sub_DRjwaT5qHx", - "mode": "test", - "createdAt": "2018-04-24T11:41:55+00:00", - "status": "canceled", - "amount": { - "value": "10.00", - "currency": "EUR" - }, - "description": "Order 1234", - "method": null, - "times": null, - "interval": "1 month", - "startDate": "2018-04-24", - "webhookUrl": null, - "canceledAt": "2018-04-24T12:31:32+00:00", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/customers/cst_VhjQebNW5j/subscriptions/sub_DRjwaT5qHx", - "type": "application/hal+json" - }, - "customer": { - "href": "https://api.mollie.com/v2/customers/cst_VhjQebNW5j", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/subscriptions-api/cancel-subscription", - "type": "text/html" - } - } - }' - ) - ); - - $subscription = $this->getSubscription(); - - $subscription = $subscription->cancel(); - - $this->assertInstanceOf(Subscription::class, $subscription); - $this->assertEquals("subscription", $subscription->resource); - $this->assertEquals("sub_DRjwaT5qHx", $subscription->id); - $this->assertEquals("test", $subscription->mode); - $this->assertEquals(SubscriptionStatus::STATUS_CANCELED, $subscription->status); - $this->assertEquals("2018-04-24T11:41:55+00:00", $subscription->createdAt); - $this->assertEquals("2018-04-24T12:31:32+00:00", $subscription->canceledAt); - - - $selfLink = (object)["href" => "https://api.mollie.com/v2/customers/cst_VhjQebNW5j/subscriptions/sub_DRjwaT5qHx", "type" => "application/hal+json"]; - $this->assertEquals($selfLink, $subscription->_links->self); - - $customerLink = (object)["href" => "https://api.mollie.com/v2/customers/cst_VhjQebNW5j", "type" => "application/hal+json"]; - $this->assertEquals($customerLink, $subscription->_links->customer); - - $documentationLink = (object)["href" => "https://docs.mollie.com/reference/v2/subscriptions-api/cancel-subscription", "type" => "text/html"]; - $this->assertEquals($documentationLink, $subscription->_links->documentation); - } - - public function testThatUpdateSubscriptionWorks() - { - $expectedAmountValue = '12.00'; - $expectedAmountCurrency = 'EUR'; - $expectedStartDate = '2018-12-12'; - - $this->mockApiCall( - new Request('PATCH', '/v2/customers/cst_VhjQebNW5j/subscriptions/sub_DRjwaT5qHx'), - new Response( - 200, - [], - '{ - "resource": "subscription", - "id": "sub_DRjwaT5qHx", - "customerId": "cst_VhjQebNW5j", - "mode": "live", - "createdAt": "2018-07-17T07:45:52+00:00", - "status": "active", - "amount": { - "value": "' . $expectedAmountValue . '", - "currency": "' . $expectedAmountCurrency . '" - }, - "description": "Mollie Recurring subscription #1", - "method": null, - "times": 42, - "interval": "15 days", - "startDate": "' . $expectedStartDate . '", - "webhookUrl": "https://example.org/webhook", - "_links": { - "self": { - "href": "http://api.mollie.test/v2/customers/cst_VhjQebNW5j/subscriptions/sub_DRjwaT5qHx", - "type": "application/hal+json" - }, - "customer": { - "href": "http://api.mollie.test/v2/customers/cst_VhjQebNW5j", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/subscriptions-api/update-subscription", - "type": "text/html" - } - } - }' - ) - ); - - $subscription = $this->getSubscription(); - $expectedAmountObject = (object)[ - 'value' => $expectedAmountValue, - 'currency' => $expectedAmountCurrency, - ]; - $subscription->amount = $expectedAmountObject; - $subscription->startDate = $expectedStartDate; - - $updatedSubscription = $subscription->update(); - - $this->assertEquals($expectedStartDate, $updatedSubscription->startDate); - $this->assertEquals($expectedAmountObject, $updatedSubscription->amount); - } - - public function testListPageOfRootSubscriptionsWorks() - { - $this->mockApiCall( - new Request('GET', '/v2/subscriptions'), - new Response( - 200, - [], - '{ - "_embedded": { - "subscriptions": [{ - "resource": "subscription", - "id": "sub_wByQa6efm6", - "mode": "test", - "createdAt": "2018-04-24T11:41:55+00:00", - "status": "active", - "amount": { - "value": "10.00", - "currency": "EUR" - }, - "description": "Order 1234", - "method": null, - "times": null, - "interval": "1 month", - "startDate": "2018-04-24", - "webhookUrl": null, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n/subscriptions/sub_wByQa6efm6", - "type": "application/hal+json" - }, - "customer": { - "href": "https://api.mollie.com/v2/customers/cst_FhQJRw4s2n", - "type": "application/hal+json" - } - } - }] - }, - "count": 1, - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/subscriptions-api/list-subscriptions", - "type": "text/html" - }, - "self": { - "href": "https://api.mollie.com/v2/subscriptions?limit=50", - "type": "application/hal+json" - }, - "previous": null, - "next": null - } - }' - ) - ); - - $subscriptions = $this->apiClient->subscriptions->page(); - - $this->assertInstanceOf(SubscriptionCollection::class, $subscriptions); - $this->assertCount(1, $subscriptions); - $subscription = $subscriptions[0]; - - $this->assertEquals('subscription', $subscription->resource); - $this->assertEquals('sub_wByQa6efm6', $subscription->id); - // No need to test all attributes here ... - } - - /** - * @return Subscription - */ - private function getSubscription() - { - $subscriptionJson = '{ - "resource": "subscription", - "id": "sub_DRjwaT5qHx", - "customerId": "cst_VhjQebNW5j", - "mode": "live", - "createdAt": "2018-07-17T07:45:52+00:00", - "status": "active", - "amount": { - "value": "10.00", - "currency": "EUR" - }, - "description": "Mollie Recurring subscription #1", - "method": null, - "times": 42, - "interval": "15 days", - "startDate": "2018-12-12", - "webhookUrl": "https://example.org/webhook", - "_links": { - "self": { - "href": "http://api.mollie.test/v2/customers/cst_VhjQebNW5j/subscriptions/sub_DRjwaT5qHx", - "type": "application/hal+json" - }, - "customer": { - "href": "http://api.mollie.test/v2/customers/cst_VhjQebNW5j", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/subscriptions-api/update-subscription", - "type": "text/html" - } - } - }'; - - return $this->copy(json_decode($subscriptionJson), new Subscription($this->apiClient)); - } - - /** - * @return Customer - */ - private function getCustomer() - { - $customerJson = '{ - "resource": "customer", - "id": "cst_FhQJRw4s2n", - "mode": "test", - "name": "John Doe", - "email": "johndoe@example.org", - "locale": null, - "metadata": null, - "recentlyUsedMethods": [], - "createdAt": "2018-04-19T08:49:01+00:00", - "_links": { - "documentation": { - "href": "https://docs.mollie.com/reference/v2/customers-api/get-customer", - "type": "text/html" - } - } - }'; - - return $this->copy(json_decode($customerJson), new Customer($this->apiClient)); - } -} diff --git a/tests/Mollie/API/Endpoints/SubscriptionPaymentEndpointTest.php b/tests/Mollie/API/Endpoints/SubscriptionPaymentEndpointTest.php deleted file mode 100644 index 72991f1ae..000000000 --- a/tests/Mollie/API/Endpoints/SubscriptionPaymentEndpointTest.php +++ /dev/null @@ -1,86 +0,0 @@ -mockApiCall( - new Request( - 'GET', - '/v2/customers/cst_stTC2WHAuS/subscriptions/sub_8JfGzs6v3K/payments?limit=25' - ), - new Response( - 200, - [], - '{ - "count": 1, - "_embedded": { - "payments": [ - { - "resource": "payment", - "id": "tr_7UhSN1zuXS", - "mode": "live", - "amount": { - "currency": "EUR", - "value": "25.00" - }, - "description": "Quarterly payment", - "method": "creditcard", - "sequenceType": "recurring", - "status": "paid", - "isCancelable": false, - "webhookUrl": "https://webshop.example.org/payments/webhook", - "profileId": "pfl_QkEhN94Ba", - "customerId": "cst_stTC2WHAuS", - "mandateId": "mdt_38HS4fsS", - "createdAt": "2023-09-01T03:58:35.0Z", - "paidAt": "2023-09-01T04:02:01.0Z", - "_links": { - "self": { - "href": "...", - "type": "application/hal+json" - }, - "dashboard": { - "href": "https://www.mollie.com/dashboard/org_12345678/payments/tr_7UhSN1zuXS", - "type": "text/html" - } - } - } - ] - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/customers/cst_stTC2WHAuS/subscriptions/sub_8JfGzs6v3K/payments?limit=25", - "type": "application/hal+json" - }, - "previous": null, - "next": null, - "documentation": { - "href": "https://docs.mollie.com/reference/list-subscription-payments", - "type": "text/html" - } - } - }' - ) - ); - - $response = $this->apiClient->subscriptionPayments->pageForIds( - 'cst_stTC2WHAuS', - 'sub_8JfGzs6v3K', - null, - 25 - ); - - $this->assertInstanceOf(PaymentCollection::class, $response); - } -} diff --git a/tests/Mollie/API/Endpoints/TerminalEndpointTest.php b/tests/Mollie/API/Endpoints/TerminalEndpointTest.php deleted file mode 100644 index e3e0d146a..000000000 --- a/tests/Mollie/API/Endpoints/TerminalEndpointTest.php +++ /dev/null @@ -1,298 +0,0 @@ -mockApiCall( - new Request( - "GET", - "/v2/terminals/term_7MgL4wea46qkRcoTZjWEH?testmode=true", - [], - '' - ), - new Response( - 200, - [], - '{ - "id": "term_7MgL4wea46qkRcoTZjWEH", - "profileId": "pfl_QkEhN94Ba", - "status": "active", - "brand": "PAX", - "model": "A920", - "serialNumber": "1234567890", - "currency": "EUR", - "description": "Terminal #12345", - "timezone": "GMT +08:00", - "locale": "nl_NL", - "createdAt": "2022-02-12T11:58:35.0Z", - "updatedAt": "2022-11-15T13:32:11+00:00", - "activatedAt": "2022-02-12T12:13:35.0Z", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/terminals/term_7MgL4wea46qkRcoTZjWEH", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/terminals-api/get-terminal", - "type": "text/html" - } - } - }' - ) - ); - - $terminal = $this->apiClient->terminals->get("term_7MgL4wea46qkRcoTZjWEH", ["testmode" => true]); - - $this->assertInstanceOf(Terminal::class, $terminal); - $this->assertEquals('term_7MgL4wea46qkRcoTZjWEH', $terminal->id); - $this->assertEquals('pfl_QkEhN94Ba', $terminal->profileId); - $this->assertEquals(TerminalStatus::STATUS_ACTIVE, $terminal->status); - $this->assertEquals('PAX', $terminal->brand); - $this->assertEquals('A920', $terminal->model); - $this->assertEquals('1234567890', $terminal->serialNumber); - $this->assertEquals('EUR', $terminal->currency); - $this->assertEquals('Terminal #12345', $terminal->description); - $this->assertEquals('GMT +08:00', $terminal->timezone); - $this->assertEquals('nl_NL', $terminal->locale); - $this->assertEquals('2022-02-12T11:58:35.0Z', $terminal->createdAt); - $this->assertEquals('2022-11-15T13:32:11+00:00', $terminal->updatedAt); - $this->assertEquals('2022-02-12T12:13:35.0Z', $terminal->activatedAt); - - $this->assertLinkObject("https://api.mollie.com/v2/terminals/term_7MgL4wea46qkRcoTZjWEH", 'application/hal+json', $terminal->_links->self); - $this->assertLinkObject('https://docs.mollie.com/reference/v2/terminals-api/get-terminal', 'text/html', $terminal->_links->documentation); - } - - public function testListTerminal() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/terminals?limit=3", - [], - '' - ), - new Response( - 200, - [], - '{ - "count": 3, - "_embedded": { - "terminals": [ - { - "id": "term_7MgL4wea46qkRcoTZjWEH", - "resource": "terminal", - "profileId": "pfl_QkEhN94Ba", - "status": "active", - "brand": "PAX", - "model": "A920", - "serialNumber": "1234567890", - "currency": "EUR", - "description": "Terminal #12345", - "timezone": "GMT +08:00", - "locale": "nl_NL", - "createdAt": "2022-02-12T11:58:35.0Z", - "updatedAt": "2022-11-15T13:32:11+00:00", - "activatedAt": "2022-02-12T12:13:35.0Z", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/terminals/term_7MgL4wea46qkRcoTZjWEH", - "type": "application/hal+json" - } - } - }, - { - "id": "term_7MgL4wea46qkRcoTZjWEG", - "resource": "terminal", - "profileId": "pfl_QkEhN94Bb", - "status": "pending", - "brand": "PAX", - "model": "A920", - "serialNumber": "1234567891", - "currency": "EUR", - "description": "Terminal #12346", - "timezone": "GMT +08:00", - "locale": "nl_NL", - "createdAt": "2022-02-13T11:58:35.0Z", - "updatedAt": "2022-11-16T13:32:11+00:00", - "activatedAt": "2022-02-13T12:13:35.0Z", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/terminals/term_7MgL4wea46qkRcoTZjWEG", - "type": "application/hal+json" - } - } - }, - { - "id": "term_7MgL4wea46qkRcoTZjWEI", - "resource": "terminal", - "profileId": "pfl_QkEhN94Bc", - "status": "inactive", - "brand": "PAX", - "model": "A920", - "serialNumber": "1234567892", - "currency": "EUR", - "description": "Terminal #12347", - "timezone": "GMT +08:00", - "locale": "nl_NL", - "createdAt": "2022-02-14T11:58:35.0Z", - "updatedAt": "2022-11-17T13:32:11+00:00", - "activatedAt": "2022-02-14T12:13:35.0Z", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/terminals/term_7MgL4wea46qkRcoTZjWEI", - "type": "application/hal+json" - } - } - } - ] - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/terminals?limit=3", - "type": "application/hal+json" - }, - "previous": null, - "next": { - "href": "https://api.mollie.com/v2/terminals?from=term_7MgL4wea46qkRcoTZjWEH&limit=3", - "type": "application/hal+json" - }, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/terminals-api/list-terminals", - "type": "text/html" - } - } - }' - ) - ); - - $terminals = $this->apiClient->terminals->page(null, 3); - - $this->assertInstanceOf(TerminalCollection::class, $terminals); - $this->assertEquals(3, $terminals->count); - $this->assertEquals(3, count($terminals)); - - $this->assertLinkObject('https://docs.mollie.com/reference/v2/terminals-api/list-terminals', 'text/html', $terminals->_links->documentation); - $this->assertLinkObject('https://api.mollie.com/v2/terminals?limit=3', 'application/hal+json', $terminals->_links->self); - $this->assertLinkObject('https://api.mollie.com/v2/terminals?from=term_7MgL4wea46qkRcoTZjWEH&limit=3', 'application/hal+json', $terminals->_links->next); - - $this->assertNull($terminals->_links->previous); - } - - public function testIterateTerminal() - { - $this->mockApiCall( - new Request( - "GET", - "/v2/terminals", - [], - '' - ), - new Response( - 200, - [], - '{ - "count": 3, - "_embedded": { - "terminals": [ - { - "id": "term_7MgL4wea46qkRcoTZjWEH", - "resource": "terminal", - "profileId": "pfl_QkEhN94Ba", - "status": "active", - "brand": "PAX", - "model": "A920", - "serialNumber": "1234567890", - "currency": "EUR", - "description": "Terminal #12345", - "timezone": "GMT +08:00", - "locale": "nl_NL", - "createdAt": "2022-02-12T11:58:35.0Z", - "updatedAt": "2022-11-15T13:32:11+00:00", - "activatedAt": "2022-02-12T12:13:35.0Z", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/terminals/term_7MgL4wea46qkRcoTZjWEH", - "type": "application/hal+json" - } - } - }, - { - "id": "term_7MgL4wea46qkRcoTZjWEG", - "resource": "terminal", - "profileId": "pfl_QkEhN94Bb", - "status": "pending", - "brand": "PAX", - "model": "A920", - "serialNumber": "1234567891", - "currency": "EUR", - "description": "Terminal #12346", - "timezone": "GMT +08:00", - "locale": "nl_NL", - "createdAt": "2022-02-13T11:58:35.0Z", - "updatedAt": "2022-11-16T13:32:11+00:00", - "activatedAt": "2022-02-13T12:13:35.0Z", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/terminals/term_7MgL4wea46qkRcoTZjWEG", - "type": "application/hal+json" - } - } - }, - { - "id": "term_7MgL4wea46qkRcoTZjWEI", - "resource": "terminal", - "profileId": "pfl_QkEhN94Bc", - "status": "inactive", - "brand": "PAX", - "model": "A920", - "serialNumber": "1234567892", - "currency": "EUR", - "description": "Terminal #12347", - "timezone": "GMT +08:00", - "locale": "nl_NL", - "createdAt": "2022-02-14T11:58:35.0Z", - "updatedAt": "2022-11-17T13:32:11+00:00", - "activatedAt": "2022-02-14T12:13:35.0Z", - "_links": { - "self": { - "href": "https://api.mollie.com/v2/terminals/term_7MgL4wea46qkRcoTZjWEI", - "type": "application/hal+json" - } - } - } - ] - }, - "_links": { - "self": { - "href": "https://api.mollie.com/v2/terminals", - "type": "application/hal+json" - }, - "previous": null, - "next": null, - "documentation": { - "href": "https://docs.mollie.com/reference/v2/terminals-api/list-terminals", - "type": "text/html" - } - } - }' - ) - ); - - foreach ($this->apiClient->terminals->iterator() as $terminal) { - $this->assertInstanceOf(Terminal::class, $terminal); - $this->assertEquals("terminal", $terminal->resource); - } - } -} diff --git a/tests/Mollie/API/Endpoints/WalletEndpointTest.php b/tests/Mollie/API/Endpoints/WalletEndpointTest.php deleted file mode 100644 index ee52bab33..000000000 --- a/tests/Mollie/API/Endpoints/WalletEndpointTest.php +++ /dev/null @@ -1,55 +0,0 @@ -mockApiCall( - new Request( - "POST", - "/v2/wallets/applepay/sessions", - [], - '{ - "domain": "pay.mywebshop.com", - "validationUrl": "https://apple-pay-gateway-cert.apple.com/paymentservices/paymentSession", - "profileId": "pfl_xH2kP6Nc6X" - }' - ), - new Response( - 201, - [], - $responseBody - ) - ); - - $domain = 'pay.mywebshop.com'; - $validationUrl = 'https://apple-pay-gateway-cert.apple.com/paymentservices/paymentSession'; - - $response = $this->apiClient->wallets->requestApplePayPaymentSession( - $domain, - $validationUrl, - ['profileId' => 'pfl_xH2kP6Nc6X'] - ); - - $this->assertJsonStringEqualsJsonString( - $responseBody, - $response - ); - } -} diff --git a/tests/Mollie/API/Exceptions/ApiExceptionTest.php b/tests/Mollie/API/Exceptions/ApiExceptionTest.php deleted file mode 100644 index c9d8a4896..000000000 --- a/tests/Mollie/API/Exceptions/ApiExceptionTest.php +++ /dev/null @@ -1,52 +0,0 @@ -assertJsonStringEqualsJsonString(/** @lang JSON */'{ "foo": "bar" }', $exception->getRequest()->getBody()->__toString()); - $this->assertStringEndsWith('Error executing API call (422: Unprocessable Entity): Can not enable Credit card via the API. Please go to the dashboard to enable this payment method.. Documentation: https://docs.mollie.com/guides/handling-errors. Request body: { "foo": "bar" }', $exception->getMessage()); - $this->assertEquals('Error executing API call (422: Unprocessable Entity): Can not enable Credit card via the API. Please go to the dashboard to enable this payment method.', $exception->getPlainMessage()); - } -} diff --git a/tests/Mollie/API/HttpAdapter/CurlMollieHttpAdapterTest.php b/tests/Mollie/API/HttpAdapter/CurlMollieHttpAdapterTest.php deleted file mode 100644 index 114e09451..000000000 --- a/tests/Mollie/API/HttpAdapter/CurlMollieHttpAdapterTest.php +++ /dev/null @@ -1,16 +0,0 @@ -assertFalse($adapter->supportsDebugging()); - } -} diff --git a/tests/Mollie/API/HttpAdapter/Guzzle6And7MollieHttpAdapterTest.php b/tests/Mollie/API/HttpAdapter/Guzzle6And7MollieHttpAdapterTest.php deleted file mode 100644 index b789a74e1..000000000 --- a/tests/Mollie/API/HttpAdapter/Guzzle6And7MollieHttpAdapterTest.php +++ /dev/null @@ -1,93 +0,0 @@ -assertTrue($adapter->supportsDebugging()); - $this->assertFalse($adapter->debugging()); - - $adapter->enableDebugging(); - $this->assertTrue($adapter->debugging()); - - $adapter->disableDebugging(); - $this->assertFalse($adapter->debugging()); - } - - /** @test */ - public function whenDebuggingAnApiExceptionIncludesTheRequest() - { - $guzzleClient = $this->createMock(Client::class); - $guzzleClient - ->expects($this->once()) - ->method('send') - ->with($this->isInstanceOf(Request::class)) - ->willThrowException( - new ConnectException( - 'Mock exception', - new Request('POST', 'https://api.mollie.com') - ) - ); - - $adapter = new Guzzle6And7MollieHttpAdapter($guzzleClient); - $adapter->enableDebugging(); - - try { - $adapter->send( - 'POST', - 'https://api.mollie.com/v2/profiles/pfl_v9hTwCvYqw/methods/bancontact', - [], - /** @lang JSON */ - '{ "foo": "bar" }' - ); - } catch (ApiException $e) { - $exception = Liberator::liberate($e); - $this->assertInstanceOf(RequestInterface::class, $exception->request); - } - } - - /** @test */ - public function whenNotDebuggingAnApiExceptionIsExcludedFromTheRequest() - { - $guzzleClient = $this->createMock(Client::class); - $guzzleClient - ->expects($this->once()) - ->method('send') - ->with($this->isInstanceOf(Request::class)) - ->willThrowException( - new ConnectException( - 'Mock exception', - new Request('POST', 'https://api.mollie.com') - ) - ); - - $adapter = new Guzzle6And7MollieHttpAdapter($guzzleClient); - $this->assertFalse($adapter->debugging()); - - try { - $adapter->send( - 'POST', - 'https://api.mollie.com/v2/profiles/pfl_v9hTwCvYqw/methods/bancontact', - [], - /** @lang JSON */ - '{ "foo": "bar" }' - ); - } catch (ApiException $e) { - $exception = Liberator::liberate($e); - $this->assertNull($exception->request); - } - } -} diff --git a/tests/Mollie/API/HttpAdapter/MockMollieHttpAdapter.php b/tests/Mollie/API/HttpAdapter/MockMollieHttpAdapter.php deleted file mode 100644 index cf480b8b8..000000000 --- a/tests/Mollie/API/HttpAdapter/MockMollieHttpAdapter.php +++ /dev/null @@ -1,22 +0,0 @@ - 'bar']; - } - - /** - * @inheritDoc - */ - public function versionString() - { - return 'mock-client/1.0'; - } -} diff --git a/tests/Mollie/API/MollieApiClientTest.php b/tests/Mollie/API/MollieApiClientTest.php deleted file mode 100644 index bd1103a42..000000000 --- a/tests/Mollie/API/MollieApiClientTest.php +++ /dev/null @@ -1,322 +0,0 @@ -guzzleClient = $this->createMock(Client::class); - $this->mollieApiClient = new MollieApiClient($this->guzzleClient); - - $this->mollieApiClient->setApiKey('test_foobarfoobarfoobarfoobarfoobar'); - } - - public function testPerformHttpCallReturnsBodyAsObject() - { - $response = new Response(200, [], '{"resource": "payment"}'); - - $this->guzzleClient - ->expects($this->once()) - ->method('send') - ->willReturn($response); - - - $parsedResponse = $this->mollieApiClient->performHttpCall('GET', ''); - - $this->assertEquals( - (object)['resource' => 'payment'], - $parsedResponse - ); - } - - public function testPerformHttpCallCreatesApiExceptionCorrectly() - { - $this->expectException(ApiException::class); - $this->expectExceptionMessage('Error executing API call (422: Unprocessable Entity): Non-existent parameter "recurringType" for this API call. Did you mean: "sequenceType"?'); - $this->expectExceptionCode(422); - - $response = new Response(422, [], '{ - "status": 422, - "title": "Unprocessable Entity", - "detail": "Non-existent parameter \"recurringType\" for this API call. Did you mean: \"sequenceType\"?", - "field": "recurringType", - "_links": { - "documentation": { - "href": "https://docs.mollie.com/guides/handling-errors", - "type": "text/html" - } - } - }'); - - $this->guzzleClient - ->expects($this->once()) - ->method('send') - ->willReturn($response); - - try { - $parsedResponse = $this->mollieApiClient->performHttpCall('GET', ''); - } catch (ApiException $e) { - $this->assertEquals('recurringType', $e->getField()); - $this->assertEquals('https://docs.mollie.com/guides/handling-errors', $e->getDocumentationUrl()); - $this->assertEquals($response, $e->getResponse()); - - throw $e; - } - } - - public function testPerformHttpCallCreatesApiExceptionWithoutFieldAndDocumentationUrl() - { - $this->expectException(ApiException::class); - $this->expectExceptionMessage('Error executing API call (422: Unprocessable Entity): Non-existent parameter "recurringType" for this API call. Did you mean: "sequenceType"?'); - $this->expectExceptionCode(422); - - $response = new Response(422, [], '{ - "status": 422, - "title": "Unprocessable Entity", - "detail": "Non-existent parameter \"recurringType\" for this API call. Did you mean: \"sequenceType\"?" - }'); - - $this->guzzleClient - ->expects($this->once()) - ->method('send') - ->willReturn($response); - - try { - $parsedResponse = $this->mollieApiClient->performHttpCall('GET', ''); - } catch (ApiException $e) { - $this->assertNull($e->getField()); - $this->assertNull($e->getDocumentationUrl()); - $this->assertEquals($response, $e->getResponse()); - - throw $e; - } - } - - public function testCanBeSerializedAndUnserialized() - { - $this->mollieApiClient->setApiEndpoint("https://mymollieproxy.local"); - $serialized = \serialize($this->mollieApiClient); - - $this->assertStringNotContainsString('test_foobarfoobarfoobarfoobarfoobar', $serialized, "API key should not be in serialized data or it will end up in caches."); - - /** @var MollieApiClient $client_copy */ - $client_copy = Liberator::liberate(unserialize($serialized)); - - $this->assertEmpty($client_copy->apiKey, "API key should not have been remembered"); - $this->assertInstanceOf(Guzzle6And7MollieHttpAdapter::class, $client_copy->httpClient, "A Guzzle client should have been set."); - $this->assertNull($client_copy->usesOAuth()); - $this->assertEquals("https://mymollieproxy.local", $client_copy->getApiEndpoint(), "The API endpoint should be remembered"); - - $this->assertNotEmpty($client_copy->customerPayments); - $this->assertNotEmpty($client_copy->payments); - $this->assertNotEmpty($client_copy->methods); - // no need to assert them all. - } - - public function testResponseBodyCanBeReadMultipleTimesIfMiddlewareReadsItFirst() - { - $response = new Response(200, [], '{"resource": "payment"}'); - - // Before the MollieApiClient gets the response, some middleware reads the body first. - $bodyAsReadFromMiddleware = (string) $response->getBody(); - - $this->guzzleClient - ->expects($this->once()) - ->method('send') - ->willReturn($response); - - $parsedResponse = $this->mollieApiClient->performHttpCall('GET', ''); - - $this->assertEquals( - '{"resource": "payment"}', - $bodyAsReadFromMiddleware - ); - - $this->assertEquals( - (object)['resource' => 'payment'], - $parsedResponse - ); - } - - public function testEnablingDebuggingThrowsAnExceptionIfHttpAdapterDoesNotSupportIt() - { - $this->expectException(HttpAdapterDoesNotSupportDebuggingException::class); - $client = new MollieApiClient(new CurlMollieHttpAdapter); - - $client->enableDebugging(); - } - - public function testDisablingDebuggingThrowsAnExceptionIfHttpAdapterDoesNotSupportIt() - { - $this->expectException(HttpAdapterDoesNotSupportDebuggingException::class); - $client = new MollieApiClient(new CurlMollieHttpAdapter); - - $client->disableDebugging(); - } - - /** - * This test verifies that our request headers are correctly sent to Mollie. - * If these are broken, it could be that some payments do not work. - * - * @throws ApiException - */ - public function testCorrectRequestHeaders() - { - $response = new Response(200, [], '{"resource": "payment"}'); - $fakeAdapter = new FakeHttpAdapter($response); - - $mollieClient = new MollieApiClient($fakeAdapter); - $mollieClient->setApiKey('test_foobarfoobarfoobarfoobarfoobar'); - - $mollieClient->performHttpCallToFullUrl('GET', '', ''); - - $usedHeaders = $fakeAdapter->getUsedHeaders(); - - # these change through environments - # just make sure its existing - $this->assertArrayHasKey('User-Agent', $usedHeaders); - $this->assertArrayHasKey('X-Mollie-Client-Info', $usedHeaders); - - # these should be exactly the expected values - $this->assertEquals('Bearer test_foobarfoobarfoobarfoobarfoobar', $usedHeaders['Authorization']); - $this->assertEquals('application/json', $usedHeaders['Accept']); - $this->assertEquals('application/json', $usedHeaders['Content-Type']); - } - - /** - * This test verifies that we do not add a Content-Type request header - * if we do not send a BODY (skipping argument). - * In this case it has to be skipped. - * - * @throws ApiException - * @throws \Mollie\Api\Exceptions\IncompatiblePlatform - * @throws \Mollie\Api\Exceptions\UnrecognizedClientException - */ - public function testNoContentTypeWithoutProvidedBody() - { - $response = new Response(200, [], '{"resource": "payment"}'); - $fakeAdapter = new FakeHttpAdapter($response); - - $mollieClient = new MollieApiClient($fakeAdapter); - $mollieClient->setApiKey('test_foobarfoobarfoobarfoobarfoobar'); - - $mollieClient->performHttpCallToFullUrl('GET', ''); - - $this->assertEquals(false, isset($fakeAdapter->getUsedHeaders()['Content-Type'])); - } - - public function testIfNoIdempotencyKeyIsSetNoReferenceIsIncludedInTheRequestHeaders() - { - $response = new Response(200, [], '{"resource": "payment"}'); - $fakeAdapter = new FakeHttpAdapter($response); - - $mollieClient = new MollieApiClient($fakeAdapter); - $mollieClient->setApiKey('test_foobarfoobarfoobarfoobarfoobar'); - - // ... Not setting an idempotency key here - - $mollieClient->performHttpCallToFullUrl('GET', ''); - - $this->assertFalse(isset($fakeAdapter->getUsedHeaders()['Idempotency-Key'])); - } - - public function testIdempotencyKeyIsUsedOnMutatingRequests() - { - $this->assertIdempotencyKeyIsUsedForMethod('POST'); - $this->assertIdempotencyKeyIsUsedForMethod('PATCH'); - $this->assertIdempotencyKeyIsUsedForMethod('DELETE'); - } - - public function testIdempotencyKeyIsNotUsedOnGetRequests() - { - $response = new Response(200, [], '{"resource": "payment"}'); - $fakeAdapter = new FakeHttpAdapter($response); - - $mollieClient = new MollieApiClient($fakeAdapter); - $mollieClient->setApiKey('test_foobarfoobarfoobarfoobarfoobar'); - $mollieClient->setIdempotencyKey('idempotentFooBar'); - - $mollieClient->performHttpCallToFullUrl('GET', ''); - - $this->assertFalse(isset($fakeAdapter->getUsedHeaders()['Idempotency-Key'])); - } - - public function testIdempotencyKeyResetsAfterEachRequest() - { - $response = new Response(200, [], '{"resource": "payment"}'); - $fakeAdapter = new FakeHttpAdapter($response); - - $mollieClient = new MollieApiClient($fakeAdapter); - $mollieClient->setApiKey('test_foobarfoobarfoobarfoobarfoobar'); - $mollieClient->setIdempotencyKey('idempotentFooBar'); - $this->assertEquals('idempotentFooBar', $mollieClient->getIdempotencyKey()); - - $mollieClient->performHttpCallToFullUrl('POST', ''); - - $this->assertNull($mollieClient->getIdempotencyKey()); - } - - public function testItUsesTheIdempotencyKeyGenerator() - { - $response = new Response(200, [], '{"resource": "payment"}'); - $fakeAdapter = new FakeHttpAdapter($response); - $fakeIdempotencyKeyGenerator = new FakeIdempotencyKeyGenerator; - $fakeIdempotencyKeyGenerator->setFakeKey('fake-idempotency-key'); - - $mollieClient = new MollieApiClient($fakeAdapter, null, $fakeIdempotencyKeyGenerator); - $mollieClient->setApiKey('test_foobarfoobarfoobarfoobarfoobar'); - $this->assertNull($mollieClient->getIdempotencyKey()); - - $mollieClient->performHttpCallToFullUrl('POST', ''); - - $this->assertEquals('fake-idempotency-key', $fakeAdapter->getUsedHeaders()['Idempotency-Key']); - $this->assertNull($mollieClient->getIdempotencyKey()); - } - - /** - * @param $httpMethod - * @return void - * @throws \Mollie\Api\Exceptions\ApiException - * @throws \Mollie\Api\Exceptions\IncompatiblePlatform - * @throws \Mollie\Api\Exceptions\UnrecognizedClientException - */ - private function assertIdempotencyKeyIsUsedForMethod($httpMethod) - { - $response = new Response(200, [], '{"resource": "payment"}'); - $fakeAdapter = new FakeHttpAdapter($response); - - $mollieClient = new MollieApiClient($fakeAdapter); - $mollieClient->setApiKey('test_foobarfoobarfoobarfoobarfoobar'); - $mollieClient->setIdempotencyKey('idempotentFooBar'); - - $mollieClient->performHttpCallToFullUrl($httpMethod, ''); - - $this->assertTrue(isset($fakeAdapter->getUsedHeaders()['Idempotency-Key'])); - $this->assertEquals('idempotentFooBar', $fakeAdapter->getUsedHeaders()['Idempotency-Key']); - } -} diff --git a/tests/Mollie/API/Resources/CursorCollectionTest.php b/tests/Mollie/API/Resources/CursorCollectionTest.php deleted file mode 100644 index d521d4dce..000000000 --- a/tests/Mollie/API/Resources/CursorCollectionTest.php +++ /dev/null @@ -1,219 +0,0 @@ -createMock(MollieApiClient::class); - $mockedClient->expects($this->once()) - ->method('performHttpCallToFullUrl') - ->willReturn($this->arrayToObject([ - 'count' => 1, - '_links' => [ - 'self' => [ - 'href' => 'https://api.mollie.com/v2/orders?from=ord_stTC2WHAuS', - ], - ], - '_embedded' => [ - 'orders' => [ - ['id' => 'ord_stTC2WHAuS'], - ], - ], - ])); - - $collection = new OrderCollection( - $mockedClient, - 1, - $this->arrayToObject([ - 'next' => [ - 'href' => 'https://api.mollie.com/v2/orders?from=ord_stTC2WHAuS', - ], - ]) - ); - - $this->assertTrue($collection->hasNext()); - - $nextPage = $collection->next(); - - $this->assertEquals('ord_stTC2WHAuS', $nextPage[0]->id); - - $this->assertFalse($nextPage->hasNext()); - } - - public function testWillReturnNullIfNoNextResultIsAvailable() - { - $mockedClient = $this->createMock(MollieApiClient::class); - $collection = new OrderCollection( - $mockedClient, - 1, - (object) [] - ); - - $this->assertFalse($collection->hasNext()); - $this->assertNull($collection->next()); - } - - public function testCanGetPreviousCollectionResultWhenPreviousLinkIsAvailable() - { - $mockedClient = $this->createMock(MollieApiClient::class); - $mockedClient->expects($this->once()) - ->method('performHttpCallToFullUrl') - ->willReturn( - $this->arrayToObject([ - 'count' => 1, - '_links' => [ - 'self' => [ - 'href' => 'https://api.mollie.com/v2/orders?from=ord_stTC2WHAuS', - ], - ], - '_embedded' => [ - 'orders' => [ - ['id' => 'ord_stTC2WHAuS'], - ], - ], - ]) - ); - - $collection = new OrderCollection( - $mockedClient, - 1, - $this->arrayToObject([ - 'previous' => [ - 'href' => 'https://api.mollie.com/v2/orders?from=ord_stTC2WHAuS', - ], - ]) - ); - - $this->assertTrue($collection->hasPrevious()); - - $previousPage = $collection->previous(); - - $this->assertEquals('ord_stTC2WHAuS', $previousPage[0]->id); - - $this->assertFalse($previousPage->hasPrevious()); - } - - public function testWillReturnNullIfNoPreviousResultIsAvailable() - { - $mockedClient = $this->createMock(MollieApiClient::class); - $collection = new OrderCollection( - $mockedClient, - 1, - (object) [] - ); - - $this->assertFalse($collection->hasPrevious()); - $this->assertNull($collection->previous()); - } - - public function testAutoPaginatorReturnsLazyCollection() - { - $collection = new OrderCollection( - $this->createMock(MollieApiClient::class), - 1, - (object) [] - ); - - $this->assertInstanceOf(LazyCollection::class, $collection->getAutoIterator()); - } - - public function testAutoPaginatorCanHandleConsecutiveCalls() - { - $mockedClient = $this->createMock(MollieApiClient::class); - $mockedClient->expects($this->exactly(3)) - ->method('performHttpCallToFullUrl') - ->willReturnOnConsecutiveCalls( - $this->arrayToObject([ - 'count' => 1, - '_links' => [ - 'self' => [ - 'href' => 'https://api.mollie.com/v2/orders?from=ord_stTC2WHAuS', - ], - 'next' => [ - 'href' => 'https://api.mollie.com/v2/orders?from=ord_stTC2WHAuS', - ], - ], - '_embedded' => [ - 'orders' => [ - ['id' => 'ord_stTC2WHAuS'], - ], - ], - ]), - $this->arrayToObject([ - 'count' => 1, - '_links' => [ - 'self' => [ - 'href' => 'https://api.mollie.com/v2/orders?from=ord_stTC2WHAuF', - ], - 'next' => [ - 'href' => 'https://api.mollie.com/v2/orders?from=ord_stTC2WHAuF', - ], - ], - '_embedded' => [ - 'orders' => [ - ['id' => 'ord_stTC2WHAuF'], - ], - ], - ]), - $this->arrayToObject([ - 'count' => 1, - '_links' => [ - 'self' => [ - 'href' => 'https://api.mollie.com/v2/orders?from=ord_stTC2WHAuB', - ], - ], - '_embedded' => [ - 'orders' => [ - ['id' => 'ord_stTC2WHAuB'], - ], - ], - ]) - ); - - $collection = new OrderCollection( - $mockedClient, - 0, - $this->arrayToObject([ - 'next' => [ - 'href' => 'https://api.mollie.com/v2/orders?from=ord_stTC2WHAuS', - ], - ]) - ); - - $orderIds = []; - foreach ($collection->getAutoIterator() as $order) { - $orderIds[] = $order->id; - } - - $this->assertEquals(['ord_stTC2WHAuS', 'ord_stTC2WHAuF', 'ord_stTC2WHAuB'], $orderIds); - } - - /** - * Convert an array to an object recursively. - * - * @param mixed $data - * @return mixed - */ - private function arrayToObject($data) - { - if (! is_array($data)) { - return $data; - } - - $obj = new stdClass(); - - foreach ($data as $key => $value) { - $obj->$key = $this->arrayToObject($value); - } - - return $obj; - } -} diff --git a/tests/Mollie/API/Resources/InvoiceTest.php b/tests/Mollie/API/Resources/InvoiceTest.php deleted file mode 100644 index ad51cbca3..000000000 --- a/tests/Mollie/API/Resources/InvoiceTest.php +++ /dev/null @@ -1,43 +0,0 @@ -createMock(MollieApiClient::class)); - $invoice->status = $status; - - $this->assertEquals($expected_boolean, $invoice->{$function}()); - } - - public function dpTestInvoiceStatuses() - { - return [ - [InvoiceStatus::STATUS_PAID, "isPaid", true], - [InvoiceStatus::STATUS_PAID, "isOpen", false], - [InvoiceStatus::STATUS_PAID, "isOverdue", false], - - [InvoiceStatus::STATUS_OPEN, "isPaid", false], - [InvoiceStatus::STATUS_OPEN, "isOpen", true], - [InvoiceStatus::STATUS_OPEN, "isOverdue", false], - - [InvoiceStatus::STATUS_OVERDUE, "isPaid", false], - [InvoiceStatus::STATUS_OVERDUE, "isOpen", false], - [InvoiceStatus::STATUS_OVERDUE, "isOverdue", true], - ]; - } -} diff --git a/tests/Mollie/API/Resources/MandateCollectionTest.php b/tests/Mollie/API/Resources/MandateCollectionTest.php deleted file mode 100644 index cc971c934..000000000 --- a/tests/Mollie/API/Resources/MandateCollectionTest.php +++ /dev/null @@ -1,65 +0,0 @@ -client = $this->createMock(MollieApiClient::class); - } - - public function testWhereStatus() - { - $collection = new MandateCollection($this->client, 6, null); - $collection[] = $this->getMandateWithStatus(MandateStatus::STATUS_VALID); - $collection[] = $this->getMandateWithStatus(MandateStatus::STATUS_VALID); - $collection[] = $this->getMandateWithStatus(MandateStatus::STATUS_VALID); - $collection[] = $this->getMandateWithStatus(MandateStatus::STATUS_INVALID); - $collection[] = $this->getMandateWithStatus(MandateStatus::STATUS_INVALID); - $collection[] = $this->getMandateWithStatus(MandateStatus::STATUS_PENDING); - - $valid = $collection->whereStatus(MandateStatus::STATUS_VALID); - $invalid = $collection->whereStatus(MandateStatus::STATUS_INVALID); - $pending = $collection->whereStatus(MandateStatus::STATUS_PENDING); - - $this->assertInstanceOf(MandateCollection::class, $collection); - $this->assertInstanceOf(MandateCollection::class, $valid); - $this->assertInstanceOf(MandateCollection::class, $invalid); - $this->assertInstanceOf(MandateCollection::class, $pending); - - $this->assertCount(6, $collection); - $this->assertEquals(6, $collection->count); - $this->assertCount(3, $valid); - $this->assertEquals(3, $valid->count); - $this->assertCount(2, $invalid); - $this->assertEquals(2, $invalid->count); - $this->assertCount(1, $pending); - $this->assertEquals(1, $pending->count); - } - - /** - * @param string $status - * @return \Mollie\Api\Resources\Mandate - */ - protected function getMandateWithStatus($status) - { - $mandate = new Mandate($this->client); - $mandate->status = $status; - - return $mandate; - } -} diff --git a/tests/Mollie/API/Resources/OnboardingTest.php b/tests/Mollie/API/Resources/OnboardingTest.php deleted file mode 100644 index af9d9ddde..000000000 --- a/tests/Mollie/API/Resources/OnboardingTest.php +++ /dev/null @@ -1,42 +0,0 @@ -createMock(MollieApiClient::class)); - $orderLine->status = $status; - - $this->assertEquals($expected_boolean, $orderLine->{$function}()); - } - - public function dpTestOnboardingStatuses() - { - return [ - [OnboardingStatus::NEEDS_DATA, "needsData", true], - [OnboardingStatus::NEEDS_DATA, "isInReview", false], - [OnboardingStatus::NEEDS_DATA, "isCompleted", false], - - [OnboardingStatus::IN_REVIEW, "needsData", false], - [OnboardingStatus::IN_REVIEW, "isInReview", true], - [OnboardingStatus::IN_REVIEW, "isCompleted", false], - - [OnboardingStatus::COMPLETED, "needsData", false], - [OnboardingStatus::COMPLETED, "isInReview", false], - [OnboardingStatus::COMPLETED, "isCompleted", true], - ]; - } -} diff --git a/tests/Mollie/API/Resources/OrderLineCollectionTest.php b/tests/Mollie/API/Resources/OrderLineCollectionTest.php deleted file mode 100644 index c81460cd9..000000000 --- a/tests/Mollie/API/Resources/OrderLineCollectionTest.php +++ /dev/null @@ -1,36 +0,0 @@ -createMock(MollieApiClient::class); - $lines = new OrderLineCollection(3, null); - - $line1 = new OrderLine($mockApi); - $line1->id = 'odl_aaaaaaaaaaa1'; - - $line2 = new OrderLine($mockApi); - $line2->id = 'odl_aaaaaaaaaaa2'; - - $line3 = new OrderLine($mockApi); - $line3->id = 'odl_aaaaaaaaaaa3'; - - $lines[] = $line1; - $lines[] = $line2; - $lines[] = $line3; - - $this->assertNull($lines->get('odl_not_existent')); - - $line = $lines->get('odl_aaaaaaaaaaa2'); - - $this->assertInstanceOf(OrderLine::class, $line); - $this->assertEquals($line2, $line); - } -} diff --git a/tests/Mollie/API/Resources/OrderLineTest.php b/tests/Mollie/API/Resources/OrderLineTest.php deleted file mode 100644 index 8bdcff3dc..000000000 --- a/tests/Mollie/API/Resources/OrderLineTest.php +++ /dev/null @@ -1,172 +0,0 @@ -createMock(MollieApiClient::class)); - $orderLine->status = $status; - - $this->assertEquals($expected_boolean, $orderLine->{$function}()); - } - - /** - * @param string $type - * @param string $function - * @param bool $expected_boolean - * - * @dataProvider dpTestOrderLineTypes - */ - public function testOrderLineTypes($type, $function, $expected_boolean) - { - $orderLine = new OrderLine($this->createMock(MollieApiClient::class)); - $orderLine->type = $type; - - $this->assertEquals($expected_boolean, $orderLine->{$function}()); - } - - /** - * @param string $vatRate - * @param bool $expected_boolean - * - * @dataProvider dpTestUpdateVatRate - */ - public function testUpdateVatRate($vatRate, $expected_boolean) - { - $orderLine = new OrderLine($this->createMock(MollieApiClient::class)); - $orderLine->vatRate = $vatRate; - - $this->assertEquals(isset($orderLine->getUpdateData()['vatRate']), $expected_boolean); - } - - public function dpTestUpdateVatRate() - { - return [ - [0, true], - ['0', true], - [null, false], - ]; - } - - public function dpTestOrderLineTypes() - { - return [ - [OrderLineType::TYPE_PHYSICAL, "isPhysical", true], - [OrderLineType::TYPE_PHYSICAL, "isDiscount", false], - [OrderLineType::TYPE_PHYSICAL, "isDigital", false], - [OrderLineType::TYPE_PHYSICAL, "isShippingFee", false], - [OrderLineType::TYPE_PHYSICAL, "isStoreCredit", false], - [OrderLineType::TYPE_PHYSICAL, "isGiftCard", false], - [OrderLineType::TYPE_PHYSICAL, "isSurcharge", false], - - [OrderLineType::TYPE_DISCOUNT, "isPhysical", false], - [OrderLineType::TYPE_DISCOUNT, "isDiscount", true], - [OrderLineType::TYPE_DISCOUNT, "isDigital", false], - [OrderLineType::TYPE_DISCOUNT, "isShippingFee", false], - [OrderLineType::TYPE_DISCOUNT, "isStoreCredit", false], - [OrderLineType::TYPE_DISCOUNT, "isGiftCard", false], - [OrderLineType::TYPE_DISCOUNT, "isSurcharge", false], - - [OrderLineType::TYPE_DIGITAL, "isPhysical", false], - [OrderLineType::TYPE_DIGITAL, "isDiscount", false], - [OrderLineType::TYPE_DIGITAL, "isDigital", true], - [OrderLineType::TYPE_DIGITAL, "isShippingFee", false], - [OrderLineType::TYPE_DIGITAL, "isStoreCredit", false], - [OrderLineType::TYPE_DIGITAL, "isGiftCard", false], - [OrderLineType::TYPE_DIGITAL, "isSurcharge", false], - - [OrderLineType::TYPE_SHIPPING_FEE, "isPhysical", false], - [OrderLineType::TYPE_SHIPPING_FEE, "isDiscount", false], - [OrderLineType::TYPE_SHIPPING_FEE, "isDigital", false], - [OrderLineType::TYPE_SHIPPING_FEE, "isShippingFee", true], - [OrderLineType::TYPE_SHIPPING_FEE, "isStoreCredit", false], - [OrderLineType::TYPE_SHIPPING_FEE, "isGiftCard", false], - [OrderLineType::TYPE_SHIPPING_FEE, "isSurcharge", false], - - [OrderLineType::TYPE_STORE_CREDIT, "isPhysical", false], - [OrderLineType::TYPE_STORE_CREDIT, "isDiscount", false], - [OrderLineType::TYPE_STORE_CREDIT, "isDigital", false], - [OrderLineType::TYPE_STORE_CREDIT, "isShippingFee", false], - [OrderLineType::TYPE_STORE_CREDIT, "isStoreCredit", true], - [OrderLineType::TYPE_STORE_CREDIT, "isGiftCard", false], - [OrderLineType::TYPE_STORE_CREDIT, "isSurcharge", false], - - [OrderLineType::TYPE_GIFT_CARD, "isPhysical", false], - [OrderLineType::TYPE_GIFT_CARD, "isDiscount", false], - [OrderLineType::TYPE_GIFT_CARD, "isDigital", false], - [OrderLineType::TYPE_GIFT_CARD, "isShippingFee", false], - [OrderLineType::TYPE_GIFT_CARD, "isStoreCredit", false], - [OrderLineType::TYPE_GIFT_CARD, "isGiftCard", true], - [OrderLineType::TYPE_GIFT_CARD, "isSurcharge", false], - - [OrderLineType::TYPE_SURCHARGE, "isPhysical", false], - [OrderLineType::TYPE_SURCHARGE, "isDiscount", false], - [OrderLineType::TYPE_SURCHARGE, "isDigital", false], - [OrderLineType::TYPE_SURCHARGE, "isShippingFee", false], - [OrderLineType::TYPE_SURCHARGE, "isStoreCredit", false], - [OrderLineType::TYPE_SURCHARGE, "isGiftCard", false], - [OrderLineType::TYPE_SURCHARGE, "isSurcharge", true], - ]; - } - - public function dpTestOrderLineStatuses() - { - return [ - [OrderLineStatus::STATUS_CREATED, "isCreated", true], - [OrderLineStatus::STATUS_CREATED, "isPaid", false], - [OrderLineStatus::STATUS_CREATED, "isAuthorized", false], - [OrderLineStatus::STATUS_CREATED, "isCanceled", false], - [OrderLineStatus::STATUS_CREATED, "isShipping", false], - [OrderLineStatus::STATUS_CREATED, "isCompleted", false], - - [OrderLineStatus::STATUS_PAID, "isCreated", false], - [OrderLineStatus::STATUS_PAID, "isPaid", true], - [OrderLineStatus::STATUS_PAID, "isAuthorized", false], - [OrderLineStatus::STATUS_PAID, "isCanceled", false], - [OrderLineStatus::STATUS_PAID, "isShipping", false], - [OrderLineStatus::STATUS_PAID, "isCompleted", false], - - [OrderLineStatus::STATUS_AUTHORIZED, "isCreated", false], - [OrderLineStatus::STATUS_AUTHORIZED, "isPaid", false], - [OrderLineStatus::STATUS_AUTHORIZED, "isAuthorized", true], - [OrderLineStatus::STATUS_AUTHORIZED, "isCanceled", false], - [OrderLineStatus::STATUS_AUTHORIZED, "isShipping", false], - [OrderLineStatus::STATUS_AUTHORIZED, "isCompleted", false], - - [OrderLineStatus::STATUS_CANCELED, "isCreated", false], - [OrderLineStatus::STATUS_CANCELED, "isPaid", false], - [OrderLineStatus::STATUS_CANCELED, "isAuthorized", false], - [OrderLineStatus::STATUS_CANCELED, "isCanceled", true], - [OrderLineStatus::STATUS_CANCELED, "isShipping", false], - [OrderLineStatus::STATUS_CANCELED, "isCompleted", false], - - [OrderLineStatus::STATUS_SHIPPING, "isCreated", false], - [OrderLineStatus::STATUS_SHIPPING, "isPaid", false], - [OrderLineStatus::STATUS_SHIPPING, "isAuthorized", false], - [OrderLineStatus::STATUS_SHIPPING, "isCanceled", false], - [OrderLineStatus::STATUS_SHIPPING, "isShipping", true], - [OrderLineStatus::STATUS_SHIPPING, "isCompleted", false], - - [OrderLineStatus::STATUS_COMPLETED, "isCreated", false], - [OrderLineStatus::STATUS_COMPLETED, "isPaid", false], - [OrderLineStatus::STATUS_COMPLETED, "isAuthorized", false], - [OrderLineStatus::STATUS_COMPLETED, "isCanceled", false], - [OrderLineStatus::STATUS_COMPLETED, "isShipping", false], - [OrderLineStatus::STATUS_COMPLETED, "isCompleted", true], - ]; - } -} diff --git a/tests/Mollie/API/Resources/OrderTest.php b/tests/Mollie/API/Resources/OrderTest.php deleted file mode 100644 index f5050879c..000000000 --- a/tests/Mollie/API/Resources/OrderTest.php +++ /dev/null @@ -1,293 +0,0 @@ -createMock(MollieApiClient::class)); - $order->status = $status; - - $this->assertEquals($expected_boolean, $order->{$function}()); - } - - public function dpTestOrderStatuses() - { - return [ - [OrderStatus::STATUS_CREATED, "isCreated", true], - [OrderStatus::STATUS_CREATED, "isPaid", false], - [OrderStatus::STATUS_CREATED, "isAuthorized", false], - [OrderStatus::STATUS_CREATED, "isCanceled", false], - [OrderStatus::STATUS_CREATED, "isShipping", false], - [OrderStatus::STATUS_CREATED, "isCompleted", false], - [OrderStatus::STATUS_CREATED, "isExpired", false], - [OrderStatus::STATUS_CREATED, "isPending", false], - - [OrderStatus::STATUS_PAID, "isCreated", false], - [OrderStatus::STATUS_PAID, "isPaid", true], - [OrderStatus::STATUS_PAID, "isAuthorized", false], - [OrderStatus::STATUS_PAID, "isCanceled", false], - [OrderStatus::STATUS_PAID, "isShipping", false], - [OrderStatus::STATUS_PAID, "isCompleted", false], - [OrderStatus::STATUS_PAID, "isExpired", false], - [OrderStatus::STATUS_PAID, "isPending", false], - - [OrderStatus::STATUS_AUTHORIZED, "isCreated", false], - [OrderStatus::STATUS_AUTHORIZED, "isPaid", false], - [OrderStatus::STATUS_AUTHORIZED, "isAuthorized", true], - [OrderStatus::STATUS_AUTHORIZED, "isCanceled", false], - [OrderStatus::STATUS_AUTHORIZED, "isShipping", false], - [OrderStatus::STATUS_AUTHORIZED, "isCompleted", false], - [OrderStatus::STATUS_AUTHORIZED, "isExpired", false], - [OrderStatus::STATUS_AUTHORIZED, "isPending", false], - - [OrderStatus::STATUS_CANCELED, "isCreated", false], - [OrderStatus::STATUS_CANCELED, "isPaid", false], - [OrderStatus::STATUS_CANCELED, "isAuthorized", false], - [OrderStatus::STATUS_CANCELED, "isCanceled", true], - [OrderStatus::STATUS_CANCELED, "isShipping", false], - [OrderStatus::STATUS_CANCELED, "isCompleted", false], - [OrderStatus::STATUS_CANCELED, "isExpired", false], - [OrderStatus::STATUS_CANCELED, "isPending", false], - - [OrderStatus::STATUS_SHIPPING, "isCreated", false], - [OrderStatus::STATUS_SHIPPING, "isPaid", false], - [OrderStatus::STATUS_SHIPPING, "isAuthorized", false], - [OrderStatus::STATUS_SHIPPING, "isCanceled", false], - [OrderStatus::STATUS_SHIPPING, "isShipping", true], - [OrderStatus::STATUS_SHIPPING, "isCompleted", false], - [OrderStatus::STATUS_SHIPPING, "isExpired", false], - [OrderStatus::STATUS_SHIPPING, "isPending", false], - - [OrderStatus::STATUS_COMPLETED, "isCreated", false], - [OrderStatus::STATUS_COMPLETED, "isPaid", false], - [OrderStatus::STATUS_COMPLETED, "isAuthorized", false], - [OrderStatus::STATUS_COMPLETED, "isCanceled", false], - [OrderStatus::STATUS_COMPLETED, "isShipping", false], - [OrderStatus::STATUS_COMPLETED, "isCompleted", true], - [OrderStatus::STATUS_COMPLETED, "isExpired", false], - [OrderStatus::STATUS_COMPLETED, "isPending", false], - - [OrderStatus::STATUS_EXPIRED, "isCreated", false], - [OrderStatus::STATUS_EXPIRED, "isPaid", false], - [OrderStatus::STATUS_EXPIRED, "isAuthorized", false], - [OrderStatus::STATUS_EXPIRED, "isCanceled", false], - [OrderStatus::STATUS_EXPIRED, "isShipping", false], - [OrderStatus::STATUS_EXPIRED, "isCompleted", false], - [OrderStatus::STATUS_EXPIRED, "isExpired", true], - [OrderStatus::STATUS_EXPIRED, "isPending", false], - - [OrderStatus::STATUS_PENDING, "isCreated", false], - [OrderStatus::STATUS_PENDING, "isPaid", false], - [OrderStatus::STATUS_PENDING, "isAuthorized", false], - [OrderStatus::STATUS_PENDING, "isCanceled", false], - [OrderStatus::STATUS_PENDING, "isShipping", false], - [OrderStatus::STATUS_PENDING, "isCompleted", false], - [OrderStatus::STATUS_PENDING, "isExpired", false], - [OrderStatus::STATUS_PENDING, "isPending", true], - ]; - } - - public function testCanGetLinesAsResourcesOnOrderResource() - { - $order = new Order($this->createMock(MollieApiClient::class)); - $orderLine = new stdClass; - $lineArray = [ - 'resource' => 'orderline', - 'id' => 'odl_dgtxyl', - 'orderId' => 'ord_pbjz8x', - 'type' => 'physical', - 'name' => 'LEGO 42083 Bugatti Chiron', - 'productUrl' => 'https://shop.lego.com/nl-NL/Bugatti-Chiron-42083', - 'imageUrl' => 'https://sh-s7-live-s.legocdn.com/is/image//LEGO/42083_alt1?$main$', - 'sku' => '5702016116977', - 'status' => 'created', - 'quantity' => 2, - 'unitPrice' => (object) [ - 'value' => '399.00', - 'currency' => 'EUR', - ], - 'vatRate' => '21.00', - 'vatAmount' => (object) [ - 'value' => '121.14', - 'currency' => 'EUR', - ], - 'discountAmount' => (object) [ - 'value' => '100.00', - 'currency' => 'EUR', - ], - 'totalAmount' => (object) [ - 'value' => '698.00', - 'currency' => 'EUR', - ], - 'createdAt' => '2018-08-02T09:29:56+00:00', - ]; - - foreach ($lineArray as $key => $value) { - $orderLine->{$key} = $value; - } - - $order->lines = [$orderLine]; - - $lines = $order->lines(); - - $this->assertInstanceOf(OrderLineCollection::class, $lines); - $this->assertCount(1, $lines); - - $line = $lines[0]; - - $this->assertInstanceOf(OrderLine::class, $line); - - $this->assertEquals("orderline", $line->resource); - $this->assertEquals("odl_dgtxyl", $line->id); - $this->assertEquals('ord_pbjz8x', $line->orderId); - $this->assertEquals("LEGO 42083 Bugatti Chiron", $line->name); - $this->assertEquals("https://shop.lego.com/nl-NL/Bugatti-Chiron-42083", $line->productUrl); - $this->assertEquals('https://sh-s7-live-s.legocdn.com/is/image//LEGO/42083_alt1?$main$', $line->imageUrl); - $this->assertEquals("5702016116977", $line->sku); - $this->assertEquals(OrderLineType::TYPE_PHYSICAL, $line->type); - $this->assertEquals(OrderLineStatus::STATUS_CREATED, $line->status); - $this->assertEquals(2, $line->quantity); - $this->assertAmountObject("399.00", "EUR", $line->unitPrice); - $this->assertEquals("21.00", $line->vatRate); - $this->assertAmountObject("121.14", "EUR", $line->vatAmount); - $this->assertAmountObject("100.00", "EUR", $line->discountAmount); - $this->assertAmountObject("698.00", "EUR", $line->totalAmount); - $this->assertEquals("2018-08-02T09:29:56+00:00", $line->createdAt); - } - - public function testCanGetPaymentsAsResourcesOnOrderResource() - { - $order = new Order($this->createMock(MollieApiClient::class)); - $orderLine = new stdClass; - $lineArray = [ - 'resource' => 'orderline', - 'id' => 'odl_dgtxyl', - 'orderId' => 'ord_pbjz8x', - 'type' => 'physical', - 'name' => 'LEGO 42083 Bugatti Chiron', - 'productUrl' => 'https://shop.lego.com/nl-NL/Bugatti-Chiron-42083', - 'imageUrl' => 'https://sh-s7-live-s.legocdn.com/is/image//LEGO/42083_alt1?$main$', - 'sku' => '5702016116977', - 'status' => 'created', - 'quantity' => 2, - 'unitPrice' => (object) [ - 'value' => '399.00', - 'currency' => 'EUR', - ], - 'vatRate' => '21.00', - 'vatAmount' => (object) [ - 'value' => '121.14', - 'currency' => 'EUR', - ], - 'discountAmount' => (object) [ - 'value' => '100.00', - 'currency' => 'EUR', - ], - 'totalAmount' => (object) [ - 'value' => '698.00', - 'currency' => 'EUR', - ], - 'createdAt' => '2018-08-02T09:29:56+00:00', - ]; - - foreach ($lineArray as $key => $value) { - $orderLine->{$key} = $value; - } - - $order->lines = [$orderLine]; - - $lines = $order->lines(); - - $this->assertInstanceOf(OrderLineCollection::class, $lines); - $this->assertCount(1, $lines); - - $line = $lines[0]; - - $this->assertInstanceOf(OrderLine::class, $line); - - $this->assertEquals("orderline", $line->resource); - $this->assertEquals("odl_dgtxyl", $line->id); - $this->assertEquals('ord_pbjz8x', $line->orderId); - $this->assertEquals("LEGO 42083 Bugatti Chiron", $line->name); - $this->assertEquals("https://shop.lego.com/nl-NL/Bugatti-Chiron-42083", $line->productUrl); - $this->assertEquals('https://sh-s7-live-s.legocdn.com/is/image//LEGO/42083_alt1?$main$', $line->imageUrl); - $this->assertEquals("5702016116977", $line->sku); - $this->assertEquals(OrderLineType::TYPE_PHYSICAL, $line->type); - $this->assertEquals(OrderLineStatus::STATUS_CREATED, $line->status); - $this->assertEquals(2, $line->quantity); - $this->assertAmountObject("399.00", "EUR", $line->unitPrice); - $this->assertEquals("21.00", $line->vatRate); - $this->assertAmountObject("121.14", "EUR", $line->vatAmount); - $this->assertAmountObject("100.00", "EUR", $line->discountAmount); - $this->assertAmountObject("698.00", "EUR", $line->totalAmount); - $this->assertEquals("2018-08-02T09:29:56+00:00", $line->createdAt); - } - - public function testGetCheckoutUrlWorks() - { - $order = new Order($this->createMock(MollieApiClient::class)); - $order->_links = $this->getOrderLinksDummy([ - 'checkout' => (object) [ - 'href' => 'https://www.some-mollie-checkout-url.com/123', - 'type' => 'text/html', - ], - ]); - - $this->assertEquals( - 'https://www.some-mollie-checkout-url.com/123', - $order->getCheckoutUrl() - ); - } - - public function testGetCheckoutUrlReturnsNullIfNoCheckoutUrlAvailable() - { - $order = new Order($this->createMock(MollieApiClient::class)); - $order->_links = $this->getOrderLinksDummy(['checkout' => null]); - - $this->assertNull($order->getCheckoutUrl()); - } - - public function testPaymentsHelperReturnsIfNoEmbedAvailable() - { - $order = new Order($this->createMock(MollieApiClient::class)); - $this->assertNull($order->payments()); - } - - public function testPaymentsHelperReturnsIfNoPaymentsEmbedded() - { - $order = new Order($this->createMock(MollieApiClient::class)); - $order->_embedded = null; - $this->assertNull($order->payments()); - } - - protected function getOrderLinksDummy($overrides = []) - { - return (object) array_merge( - [], - $overrides - ); - } -} diff --git a/tests/Mollie/API/Resources/PaymentTest.php b/tests/Mollie/API/Resources/PaymentTest.php deleted file mode 100644 index 480e755a2..000000000 --- a/tests/Mollie/API/Resources/PaymentTest.php +++ /dev/null @@ -1,268 +0,0 @@ -createMock(MollieApiClient::class)); - $payment->status = $status; - - $this->assertEquals($expected_boolean, $payment->{$function}()); - } - - public function dpTestPaymentStatuses() - { - return [ - [PaymentStatus::STATUS_PENDING, "isPending", true], - [PaymentStatus::STATUS_PENDING, "isAuthorized", false], - [PaymentStatus::STATUS_PENDING, "isFailed", false], - [PaymentStatus::STATUS_PENDING, "isOpen", false], - [PaymentStatus::STATUS_PENDING, "isCanceled", false], - [PaymentStatus::STATUS_PENDING, "isPaid", false], - [PaymentStatus::STATUS_PENDING, "isExpired", false], - - [PaymentStatus::STATUS_AUTHORIZED, "isPending", false], - [PaymentStatus::STATUS_AUTHORIZED, "isAuthorized", true], - [PaymentStatus::STATUS_AUTHORIZED, "isFailed", false], - [PaymentStatus::STATUS_AUTHORIZED, "isOpen", false], - [PaymentStatus::STATUS_AUTHORIZED, "isCanceled", false], - [PaymentStatus::STATUS_AUTHORIZED, "isPaid", false], - [PaymentStatus::STATUS_AUTHORIZED, "isExpired", false], - - [PaymentStatus::STATUS_FAILED, "isPending", false], - [PaymentStatus::STATUS_FAILED, "isAuthorized", false], - [PaymentStatus::STATUS_FAILED, "isFailed", true], - [PaymentStatus::STATUS_FAILED, "isOpen", false], - [PaymentStatus::STATUS_FAILED, "isCanceled", false], - [PaymentStatus::STATUS_FAILED, "isPaid", false], - [PaymentStatus::STATUS_FAILED, "isExpired", false], - - [PaymentStatus::STATUS_OPEN, "isPending", false], - [PaymentStatus::STATUS_OPEN, "isAuthorized", false], - [PaymentStatus::STATUS_OPEN, "isFailed", false], - [PaymentStatus::STATUS_OPEN, "isOpen", true], - [PaymentStatus::STATUS_OPEN, "isCanceled", false], - [PaymentStatus::STATUS_OPEN, "isPaid", false], - [PaymentStatus::STATUS_OPEN, "isExpired", false], - - [PaymentStatus::STATUS_CANCELED, "isPending", false], - [PaymentStatus::STATUS_CANCELED, "isAuthorized", false], - [PaymentStatus::STATUS_CANCELED, "isFailed", false], - [PaymentStatus::STATUS_CANCELED, "isOpen", false], - [PaymentStatus::STATUS_CANCELED, "isCanceled", true], - [PaymentStatus::STATUS_CANCELED, "isPaid", false], - [PaymentStatus::STATUS_CANCELED, "isExpired", false], - - [PaymentStatus::STATUS_EXPIRED, "isPending", false], - [PaymentStatus::STATUS_EXPIRED, "isAuthorized", false], - [PaymentStatus::STATUS_EXPIRED, "isFailed", false], - [PaymentStatus::STATUS_EXPIRED, "isOpen", false], - [PaymentStatus::STATUS_EXPIRED, "isCanceled", false], - [PaymentStatus::STATUS_EXPIRED, "isPaid", false], - [PaymentStatus::STATUS_EXPIRED, "isExpired", true], - ]; - } - - public function testIsPaidReturnsTrueWhenPaidDatetimeIsSet() - { - $payment = new Payment($this->createMock(MollieApiClient::class)); - - $payment->paidAt = "2016-10-24"; - $this->assertTrue($payment->isPaid()); - } - - public function testHasRefundsReturnsTrueWhenPaymentHasRefunds() - { - $payment = new Payment($this->createMock(MollieApiClient::class)); - - $payment->_links = new stdClass(); - $payment->_links->refunds = (object) ["href" => "https://api.mollie.com/v2/payments/tr_44aKxzEbr8/refunds", "type" => "application/hal+json"]; - - $this->assertTrue($payment->hasRefunds()); - } - - public function testHasRefundsReturnsFalseWhenPaymentHasNoRefunds() - { - $payment = new Payment($this->createMock(MollieApiClient::class)); - - $payment->_links = new stdClass(); - $this->assertFalse($payment->hasRefunds()); - } - - public function testHasChargebacksReturnsTrueWhenPaymentHasChargebacks() - { - $payment = new Payment($this->createMock(MollieApiClient::class)); - - $payment->_links = new stdClass(); - $payment->_links->chargebacks = (object) ["href" => "https://api.mollie.com/v2/payments/tr_44aKxzEbr8/chargebacks", "type" => "application/hal+json"]; - - $this->assertTrue($payment->hasChargebacks()); - } - - public function testHasChargebacksReturnsFalseWhenPaymentHasNoChargebacks() - { - $payment = new Payment($this->createMock(MollieApiClient::class)); - - $payment->_links = new stdClass(); - $this->assertFalse($payment->hasChargebacks()); - } - - public function testHasRecurringTypeReturnsTrueWhenRecurringTypeIsFirst() - { - $payment = new Payment($this->createMock(MollieApiClient::class)); - - $payment->sequenceType = SequenceType::SEQUENCETYPE_FIRST; - $this->assertFalse($payment->hasSequenceTypeRecurring()); - $this->assertTrue($payment->hasSequenceTypeFirst()); - } - - public function testHasRecurringTypeReturnsTrueWhenRecurringTypeIsRecurring() - { - $payment = new Payment($this->createMock(MollieApiClient::class)); - - $payment->sequenceType = SequenceType::SEQUENCETYPE_RECURRING; - $this->assertTrue($payment->hasSequenceTypeRecurring()); - $this->assertFalse($payment->hasSequenceTypeFirst()); - } - - public function testHasRecurringTypeReturnsFalseWhenRecurringTypeIsNone() - { - $payment = new Payment($this->createMock(MollieApiClient::class)); - - $payment->sequenceType = SequenceType::SEQUENCETYPE_ONEOFF; - $this->assertFalse($payment->hasSequenceTypeFirst()); - $this->assertFalse($payment->hasSequenceTypeRecurring()); - } - - public function testGetCheckoutUrlReturnsPaymentUrlFromLinksObject() - { - $payment = new Payment($this->createMock(MollieApiClient::class)); - - $payment->_links = new stdClass(); - $payment->_links->checkout = new stdClass(); - $payment->_links->checkout->href = "https://example.com"; - - $this->assertSame($payment->getCheckoutUrl(), "https://example.com"); - } - - public function testGetMobileAppCheckoutUrlReturnsPaymentUrlFromLinksObject() - { - $payment = new Payment($this->createMock(MollieApiClient::class)); - - $payment->_links = new stdClass(); - $payment->_links->mobileAppCheckout = new stdClass(); - $payment->_links->mobileAppCheckout->href = "https://example-mobile-checkout.com"; - - - $this->assertSame($payment->getMobileAppCheckoutUrl(), "https://example-mobile-checkout.com"); - } - - public function testCanBeRefundedReturnsTrueWhenAmountRemainingIsSet() - { - $payment = new Payment($this->createMock(MollieApiClient::class)); - - $amountRemaining = new Stdclass(); - $amountRemaining->value = '15.00'; - $amountRemaining->currency = "EUR"; - - $payment->amountRemaining = $amountRemaining; - $this->assertTrue($payment->canBeRefunded()); - $this->assertTrue($payment->canBePartiallyRefunded()); - } - - public function testCanBeRefundedReturnsFalseWhenAmountRemainingIsNull() - { - $payment = new Payment($this->createMock(MollieApiClient::class)); - - $payment->amountRemaining = null; - $this->assertFalse($payment->canBeRefunded()); - $this->assertFalse($payment->canBePartiallyRefunded()); - } - - public function testGetAmountRefundedReturnsAmountRefundedAsFloat() - { - $payment = new Payment($this->createMock(MollieApiClient::class)); - - $payment->amountRefunded = (object)["value" => 22.0, "currency" => "EUR"]; - self::assertSame(22.0, $payment->getAmountRefunded()); - } - - public function testGetAmountRefundedReturns0WhenAmountRefundedIsSetToNull() - { - $payment = new Payment($this->createMock(MollieApiClient::class)); - - $payment->amountRefunded = null; - self::assertSame(0.0, $payment->getAmountRefunded()); - } - - public function testGetAmountRemainingReturnsAmountRemainingAsFloat() - { - $payment = new Payment($this->createMock(MollieApiClient::class)); - - $payment->amountRemaining = (object)["value" => 22.0, "currency" => "EUR"]; - self::assertSame(22.0, $payment->getAmountRemaining()); - } - - public function testGetAmountRemainingReturns0WhenAmountRemainingIsSetToNull() - { - $payment = new Payment($this->createMock(MollieApiClient::class)); - - $payment->amountRefunded = null; - self::assertSame(0.0, $payment->getAmountRemaining()); - } - - public function testGetAmountChargedBackReturnsAmountChargedBackAsFloat() - { - $payment = new Payment($this->createMock(MollieApiClient::class)); - - $payment->amountChargedBack = (object)["value" => 22.0, "currency" => "EUR"]; - self::assertSame(22.0, $payment->getAmountChargedBack()); - } - - public function testGetAmountChargedBackReturns0WhenAmountChargedBackIsSetToNull() - { - $payment = new Payment($this->createMock(MollieApiClient::class)); - - $payment->amountChargedBack = null; - self::assertSame(0.0, $payment->getAmountChargedBack()); - } - - public function testGetSettlementAmountReturns0WhenSettlementAmountIsSetToNull() - { - $payment = new Payment($this->createMock(MollieApiClient::class)); - - $payment->settlementAmount = null; - self::assertSame(0.0, $payment->getSettlementAmount()); - } - - public function testGetSettlementAmountReturnsSettlementAmountAsFloat() - { - $payment = new Payment($this->createMock(MollieApiClient::class)); - - $payment->settlementAmount = (object)["value" => 22.0, "currency" => "EUR"]; - self::assertSame(22.0, $payment->getSettlementAmount()); - } - - public function testHasSplitPaymentsReturnsFalseWhenPaymentHasNoSplit() - { - $payment = new Payment($this->createMock(MollieApiClient::class)); - - $payment->_links = new stdClass(); - $this->assertFalse($payment->hasSplitPayments()); - } -} diff --git a/tests/Mollie/API/Resources/ProfileTest.php b/tests/Mollie/API/Resources/ProfileTest.php deleted file mode 100644 index 1dbb9030c..000000000 --- a/tests/Mollie/API/Resources/ProfileTest.php +++ /dev/null @@ -1,42 +0,0 @@ -createMock(MollieApiClient::class)); - $profile->status = $status; - - $this->assertEquals($expected_boolean, $profile->{$function}()); - } - - public function dpTestProfileStatusses() - { - return [ - [ProfileStatus::STATUS_BLOCKED, "isBlocked", true], - [ProfileStatus::STATUS_BLOCKED, "isVerified", false], - [ProfileStatus::STATUS_BLOCKED, "isUnverified", false], - - [ProfileStatus::STATUS_VERIFIED, "isBlocked", false], - [ProfileStatus::STATUS_VERIFIED, "isVerified", true], - [ProfileStatus::STATUS_VERIFIED, "isUnverified", false], - - [ProfileStatus::STATUS_UNVERIFIED, "isBlocked", false], - [ProfileStatus::STATUS_UNVERIFIED, "isVerified", false], - [ProfileStatus::STATUS_UNVERIFIED, "isUnverified", true], - ]; - } -} diff --git a/tests/Mollie/API/Resources/RefundTest.php b/tests/Mollie/API/Resources/RefundTest.php deleted file mode 100644 index b8cdc706c..000000000 --- a/tests/Mollie/API/Resources/RefundTest.php +++ /dev/null @@ -1,169 +0,0 @@ -createMock(PaymentRefundEndpoint::class); - $endpoint->expects($this->once()) - ->method('cancelForId') - ->with( - $this->equalTo('tr_abc'), // paymentId - $this->equalTo('re_123'), // refundId - $this->equalTo(['testmode' => true]) - ); - - $apiClient = $this->createMock(MollieApiClient::class); - $apiClient->paymentRefunds = $endpoint; - $apiClient->expects($this->once()) - ->method('usesOAuth') - ->willReturn(true); - - $refund = new Refund($apiClient); - $refund->id = 're_123'; - $refund->paymentId = 'tr_abc'; - $refund->mode = 'test'; - - $response = $refund->cancel(); - - $this->assertNull($response); - } - - public function testCancelRefundUsingOauthLivemode() - { - $endpoint = $this->createMock(PaymentRefundEndpoint::class); - $endpoint->expects($this->once()) - ->method('cancelForId') - ->with( - $this->equalTo('tr_abc'), // paymentId - $this->equalTo('re_123'), // refundId - $this->equalTo(['testmode' => false]) - ); - - $apiClient = $this->createMock(MollieApiClient::class); - $apiClient->paymentRefunds = $endpoint; - $apiClient->expects($this->once()) - ->method('usesOAuth') - ->willReturn(true); - - $refund = new Refund($apiClient); - $refund->id = 're_123'; - $refund->paymentId = 'tr_abc'; - $refund->mode = 'live'; - - $response = $refund->cancel(); - - $this->assertNull($response); - } - - public function testCancelRefundWithoutOauth() - { - $endpoint = $this->createMock(PaymentRefundEndpoint::class); - $endpoint->expects($this->once()) - ->method('cancelForId') - ->with( - $this->equalTo('tr_abc'), // paymentId - $this->equalTo('re_123'), // refundId - $this->equalTo([]) - ); - - $apiClient = $this->createMock(MollieApiClient::class); - $apiClient->paymentRefunds = $endpoint; - $apiClient->expects($this->once()) - ->method('usesOAuth') - ->willReturn(false); - - $refund = new Refund($apiClient); - $refund->id = 're_123'; - $refund->paymentId = 'tr_abc'; - $refund->mode = 'test'; - - $response = $refund->cancel(); - - $this->assertNull($response); - } - - - /** - * @param string $status - * @param string $function - * @param bool $expected_boolean - * - * @dataProvider dpTestRefundStatuses - */ - public function testRefundStatuses($status, $function, $expected_boolean) - { - $refund = new Refund($this->createMock(MollieApiClient::class)); - $refund->status = $status; - - $this->assertEquals($expected_boolean, $refund->{$function}()); - } - - /** - * @param string $status - * @param bool $expected_boolean - * - * @dataProvider dpTestRefundCanBeCanceled - */ - public function testRefundCanBeCanceled($status, $expected_boolean) - { - $refund = new Refund($this->createMock(MollieApiClient::class)); - $refund->status = $status; - - $this->assertEquals($expected_boolean, $refund->canBeCanceled()); - } - - public function dpTestRefundStatuses() - { - return [ - [RefundStatus::STATUS_PENDING, "isPending", true], - [RefundStatus::STATUS_PENDING, "isProcessing", false], - [RefundStatus::STATUS_PENDING, "isQueued", false], - [RefundStatus::STATUS_PENDING, "isTransferred", false], - [RefundStatus::STATUS_PENDING, "isFailed", false], - - [RefundStatus::STATUS_PROCESSING, "isPending", false], - [RefundStatus::STATUS_PROCESSING, "isProcessing", true], - [RefundStatus::STATUS_PROCESSING, "isQueued", false], - [RefundStatus::STATUS_PROCESSING, "isTransferred", false], - [RefundStatus::STATUS_PROCESSING, "isFailed", false], - - [RefundStatus::STATUS_QUEUED, "isPending", false], - [RefundStatus::STATUS_QUEUED, "isProcessing", false], - [RefundStatus::STATUS_QUEUED, "isQueued", true], - [RefundStatus::STATUS_QUEUED, "isTransferred", false], - [RefundStatus::STATUS_QUEUED, "isFailed", false], - - [RefundStatus::STATUS_REFUNDED, "isPending", false], - [RefundStatus::STATUS_REFUNDED, "isProcessing", false], - [RefundStatus::STATUS_REFUNDED, "isQueued", false], - [RefundStatus::STATUS_REFUNDED, "isTransferred", true], - [RefundStatus::STATUS_REFUNDED, "isFailed", false], - - [RefundStatus::STATUS_FAILED, "isPending", false], - [RefundStatus::STATUS_FAILED, "isProcessing", false], - [RefundStatus::STATUS_FAILED, "isQueued", false], - [RefundStatus::STATUS_FAILED, "isTransferred", false], - [RefundStatus::STATUS_FAILED, "isFailed", true], - ]; - } - - public function dpTestRefundCanBeCanceled() - { - return [ - [RefundStatus::STATUS_PENDING, true], - [RefundStatus::STATUS_PROCESSING, false], - [RefundStatus::STATUS_QUEUED, true], - [RefundStatus::STATUS_REFUNDED, false], - [RefundStatus::STATUS_FAILED, false], - [RefundStatus::STATUS_CANCELED, false], - ]; - } -} diff --git a/tests/Mollie/API/Resources/ResourceFactoryTest.php b/tests/Mollie/API/Resources/ResourceFactoryTest.php deleted file mode 100644 index 5fcfc8950..000000000 --- a/tests/Mollie/API/Resources/ResourceFactoryTest.php +++ /dev/null @@ -1,33 +0,0 @@ -createMock(MollieApiClient::class))); - - $this->assertInstanceOf(Payment::class, $payment); - $this->assertEquals("payment", $payment->resource); - $this->assertEquals("tr_44aKxzEbr8", $payment->id); - $this->assertEquals("test", $payment->mode); - $this->assertEquals("2018-03-13T14:02:29+00:00", $payment->createdAt); - $this->assertEquals((object) ["value" => "20.00", "currency" => "EUR"], $payment->amount); - } -} diff --git a/tests/Mollie/API/Resources/SettlementTest.php b/tests/Mollie/API/Resources/SettlementTest.php deleted file mode 100644 index 85c0c5597..000000000 --- a/tests/Mollie/API/Resources/SettlementTest.php +++ /dev/null @@ -1,50 +0,0 @@ -createMock(MollieApiClient::class)); - $settlement->status = $status; - - $this->assertEquals($expected_boolean, $settlement->{$function}()); - } - - public function dpTestSettlementStatuses() - { - return [ - [SettlementStatus::STATUS_PENDING, "isPending", true], - [SettlementStatus::STATUS_PENDING, "isOpen", false], - [SettlementStatus::STATUS_PENDING, "isPaidout", false], - [SettlementStatus::STATUS_PENDING, "isFailed", false], - - [SettlementStatus::STATUS_OPEN, "isPending", false], - [SettlementStatus::STATUS_OPEN, "isOpen", true], - [SettlementStatus::STATUS_OPEN, "isPaidout", false], - [SettlementStatus::STATUS_OPEN, "isFailed", false], - - [SettlementStatus::STATUS_PAIDOUT, "isPending", false], - [SettlementStatus::STATUS_PAIDOUT, "isOpen", false], - [SettlementStatus::STATUS_PAIDOUT, "isPaidout", true], - [SettlementStatus::STATUS_PAIDOUT, "isFailed", false], - - [SettlementStatus::STATUS_FAILED, "isPending", false], - [SettlementStatus::STATUS_FAILED, "isOpen", false], - [SettlementStatus::STATUS_FAILED, "isPaidout", false], - [SettlementStatus::STATUS_FAILED, "isFailed", true], - ]; - } -} diff --git a/tests/Mollie/API/Resources/ShipmentTest.php b/tests/Mollie/API/Resources/ShipmentTest.php deleted file mode 100644 index 3ec2539e3..000000000 --- a/tests/Mollie/API/Resources/ShipmentTest.php +++ /dev/null @@ -1,84 +0,0 @@ -createMock(MollieApiClient::class)); - $shipment->tracking = $this->getTrackingDummy(); - $this->assertTrue($shipment->hasTracking()); - } - - public function testHasTrackingReturnsFalseIfObjectIsNull() - { - $shipment = new Shipment($this->createMock(MollieApiClient::class)); - $shipment->tracking = null; - $this->assertFalse($shipment->hasTracking()); - } - - public function testHasTrackingUrlReturnsFalseIfTrackingIsNotSet() - { - $shipment = new Shipment($this->createMock(MollieApiClient::class)); - $shipment->tracking = null; - $this->assertFalse($shipment->hasTrackingUrl()); - } - - public function testHasTrackingUrlReturnsTrueIfUrlIsSet() - { - $shipment = new Shipment($this->createMock(MollieApiClient::class)); - $shipment->tracking = $this->getTrackingDummy([ - 'url' => 'https://www.some-tracking-url.com/123', - ]); - $this->assertTrue($shipment->hasTrackingUrl()); - } - - public function testHasTrackingUrlReturnsFalseIfUrlIsNotSet() - { - $shipment = new Shipment($this->createMock(MollieApiClient::class)); - $shipment->tracking = $this->getTrackingDummy([ - 'url' => null, - ]); - $this->assertFalse($shipment->hasTrackingUrl()); - } - - public function testGetTrackingUrlReturnsNullIfNotAvailable() - { - $shipment = new Shipment($this->createMock(MollieApiClient::class)); - - $shipment->tracking = null; - $this->assertNull($shipment->getTrackingUrl()); - - $shipment->tracking = $this->getTrackingDummy([ - 'url' => null, - ]); - $this->assertNull($shipment->getTrackingUrl()); - } - - public function testGetTrackingUrlReturnsUrlIfAvailable() - { - $shipment = new Shipment($this->createMock(MollieApiClient::class)); - $shipment->tracking = $this->getTrackingDummy([ - 'url' => 'https://www.some-tracking-url.com/123', - ]); - - $this->assertEquals( - 'https://www.some-tracking-url.com/123', - $shipment->getTrackingUrl() - ); - } - - protected function getTrackingDummy($overrides = []) - { - return (object) array_merge([ - 'carrier' => 'DummyCarrier', - 'code' => '123456ABCD', - 'url' => 'https://www.example.org/tracktrace/1234', - ], $overrides); - } -} diff --git a/tests/Mollie/API/Resources/SubscriptionTest.php b/tests/Mollie/API/Resources/SubscriptionTest.php deleted file mode 100644 index c5e6bd518..000000000 --- a/tests/Mollie/API/Resources/SubscriptionTest.php +++ /dev/null @@ -1,60 +0,0 @@ -createMock(MollieApiClient::class)); - $subscription->status = $status; - - $this->assertEquals($expected_boolean, $subscription->{$function}()); - } - - public function dpTestSubscriptionStatuses() - { - return [ - [SubscriptionStatus::STATUS_PENDING, "isPending", true], - [SubscriptionStatus::STATUS_PENDING, "isCanceled", false], - [SubscriptionStatus::STATUS_PENDING, "isCompleted", false], - [SubscriptionStatus::STATUS_PENDING, "isSuspended", false], - [SubscriptionStatus::STATUS_PENDING, "isActive", false], - - [SubscriptionStatus::STATUS_CANCELED, "isPending", false], - [SubscriptionStatus::STATUS_CANCELED, "isCanceled", true], - [SubscriptionStatus::STATUS_CANCELED, "isCompleted", false], - [SubscriptionStatus::STATUS_CANCELED, "isSuspended", false], - [SubscriptionStatus::STATUS_CANCELED, "isActive", false], - - [SubscriptionStatus::STATUS_COMPLETED, "isPending", false], - [SubscriptionStatus::STATUS_COMPLETED, "isCanceled", false], - [SubscriptionStatus::STATUS_COMPLETED, "isCompleted", true], - [SubscriptionStatus::STATUS_COMPLETED, "isSuspended", false], - [SubscriptionStatus::STATUS_COMPLETED, "isActive", false], - - [SubscriptionStatus::STATUS_SUSPENDED, "isPending", false], - [SubscriptionStatus::STATUS_SUSPENDED, "isCanceled", false], - [SubscriptionStatus::STATUS_SUSPENDED, "isCompleted", false], - [SubscriptionStatus::STATUS_SUSPENDED, "isSuspended", true], - [SubscriptionStatus::STATUS_SUSPENDED, "isActive", false], - - [SubscriptionStatus::STATUS_ACTIVE, "isPending", false], - [SubscriptionStatus::STATUS_ACTIVE, "isCanceled", false], - [SubscriptionStatus::STATUS_ACTIVE, "isCompleted", false], - [SubscriptionStatus::STATUS_ACTIVE, "isSuspended", false], - [SubscriptionStatus::STATUS_ACTIVE, "isActive", true], - ]; - } -} diff --git a/tests/Mollie/TestHelpers/FakeHttpAdapter.php b/tests/Mollie/TestHelpers/FakeHttpAdapter.php deleted file mode 100644 index a7d525525..000000000 --- a/tests/Mollie/TestHelpers/FakeHttpAdapter.php +++ /dev/null @@ -1,100 +0,0 @@ -response = $response; - } - - /** - * @param string $httpMethod - * @param string $url - * @param string $headers - * @param string $httpBody - * @return \stdClass|void|null - */ - public function send($httpMethod, $url, $headers, $httpBody) - { - $this->usedMethod = $httpMethod; - $this->usedUrl = $url; - $this->usedHeaders = $headers; - $this->usedBody = $httpBody; - - return $this->response; - } - - /** - * @return string - */ - public function versionString() - { - return 'fake'; - } - - /** - * @return mixed - */ - public function getUsedMethod() - { - return $this->usedMethod; - } - - /** - * @return mixed - */ - public function getUsedUrl() - { - return $this->usedUrl; - } - - /** - * @return mixed - */ - public function getUsedHeaders() - { - return $this->usedHeaders; - } - - /** - * @return mixed - */ - public function getUsedBody() - { - return $this->usedBody; - } -} diff --git a/tests/MollieApiClientTest.php b/tests/MollieApiClientTest.php new file mode 100644 index 000000000..853fe7c63 --- /dev/null +++ b/tests/MollieApiClientTest.php @@ -0,0 +1,422 @@ + MockResponse::ok('{"resource": "payment"}'), + ]); + + $response = $client->send(new DynamicGetRequest('')); + + $this->assertEquals( + (object) ['resource' => 'payment'], + $response->json() + ); + } + + /** @test */ + public function send_creates_api_exception_correctly() + { + $this->expectException(ApiException::class); + $this->expectExceptionMessage('Error executing API call (422: Unprocessable Entity): Non-existent parameter "recurringType" for this API call. Did you mean: "sequenceType"?'); + $this->expectExceptionCode(422); + + $client = new MockMollieClient([ + DynamicGetRequest::class => MockResponse::unprocessableEntity('unprocessable-entity-with-field'), + ]); + + try { + $client->send(new DynamicGetRequest('')); + } catch (ApiException $e) { + $this->assertEquals('recurringType', $e->getField()); + $this->assertNotEmpty($e->getDocumentationUrl()); + + throw $e; + } + } + + /** @test */ + public function send_creates_api_exception_without_field_and_documentation_url() + { + $this->expectException(ApiException::class); + $this->expectExceptionMessage('Error executing API call (422: Unprocessable Entity): Non-existent parameter "recurringType" for this API call. Did you mean: "sequenceType"?'); + $this->expectExceptionCode(422); + + $client = new MockMollieClient([ + DynamicGetRequest::class => MockResponse::unprocessableEntity('unprocessable-entity'), + ]); + + try { + $client->send(new DynamicGetRequest('')); + } catch (ApiException $e) { + $this->assertNull($e->getField()); + $this->assertNull($e->getDocumentationUrl()); + + throw $e; + } + } + + /** @test */ + public function can_be_serialized_and_unserialized() + { + $client = new MollieApiClient($this->createMock(Client::class)); + + $client->setApiKey('test_foobarfoobarfoobarfoobarfoobar'); + $client->setApiEndpoint('https://mymollieproxy.local'); + $serialized = \serialize($client); + + $this->assertStringNotContainsString('test_foobarfoobarfoobarfoobarfoobar', $serialized, 'API key should not be in serialized data or it will end up in caches.'); + + /** @var MollieApiClient $client_copy */ + $client_copy = unserialize($serialized); + + $this->assertEmpty($client_copy->getAuthenticator(), 'Authenticator should not have been remembered'); + $this->assertInstanceOf(GuzzleMollieHttpAdapter::class, $client_copy->getHttpClient(), 'A Guzzle client should have been set.'); + $this->assertEquals('https://mymollieproxy.local', $client_copy->getApiEndpoint(), 'The API endpoint should be remembered'); + + $this->assertNotEmpty($client_copy->customerPayments); + $this->assertNotEmpty($client_copy->payments); + $this->assertNotEmpty($client_copy->methods); + } + + /** @test */ + public function enabling_debugging_throws_an_exception_if_http_adapter_does_not_support_it() + { + $this->expectException(HttpAdapterDoesNotSupportDebuggingException::class); + $client = new MollieApiClient(new CurlMollieHttpAdapter); + + $client->enableDebugging(); + } + + /** @test */ + public function disabling_debugging_throws_an_exception_if_http_adapter_does_not_support_it() + { + $this->expectException(HttpAdapterDoesNotSupportDebuggingException::class); + $client = new MollieApiClient(new CurlMollieHttpAdapter); + + $client->disableDebugging(); + } + + /** + * This test verifies that our request headers are correctly sent to Mollie. + * If these are broken, it could be that some payments do not work. + * + * @throws ApiException + */ + /** @test */ + public function correct_request_headers() + { + $client = new MockMollieClient([ + CreatePaymentRequest::class => MockResponse::ok('{"resource": "payment"}'), + ]); + + $client->setApiKey('test_foobarfoobarfoobarfoobarfoobar'); + + $response = $client->send(new CreatePaymentRequest(new CreatePaymentPayload( + 'test', + new Money('EUR', '100.00'), + ))); + + $usedHeaders = $response->getPendingRequest()->headers()->all(); + + // these change through environments + // just make sure its existing + $this->assertArrayHasKey('User-Agent', $usedHeaders); + $this->assertArrayHasKey('X-Mollie-Client-Info', $usedHeaders); + + // these should be exactly the expected values + $this->assertEquals('Bearer test_foobarfoobarfoobarfoobarfoobar', $usedHeaders['Authorization']); + $this->assertEquals('application/json', $usedHeaders['Accept']); + } + + /** + * This test verifies that we do not add a Content-Type request header + * if we do not send a BODY (skipping argument). + * In this case it has to be skipped. + * + * @throws ApiException + * @throws \Mollie\Api\Exceptions\IncompatiblePlatform + * @throws \Mollie\Api\Exceptions\UnrecognizedClientException + */ + /** @test */ + public function no_content_type_without_provided_body() + { + $client = new MockMollieClient([ + DynamicGetRequest::class => MockResponse::noContent(), + ]); + + /** @var Response $response */ + $response = $client->send(new DynamicGetRequest('')); + + $this->assertFalse($response->getPendingRequest()->headers()->has('Content-Type')); + } + + /** @test */ + public function no_idempotency_is_set_if_no_key_nor_generator_are_set() + { + $client = new MockMollieClient([ + DynamicDeleteRequest::class => MockResponse::noContent(), + ]); + + $client->clearIdempotencyKeyGenerator(); + + /** @var Response $response */ + $response = $client->send(new DynamicDeleteRequest('')); + + $this->assertFalse($response->getPendingRequest()->headers()->has(ApplyIdempotencyKey::IDEMPOTENCY_KEY_HEADER)); + } + + /** + * @dataProvider providesMutatingRequests + * + * @test + */ + public function idempotency_key_is_used_on_mutating_requests($request, $response) + { + $client = new MockMollieClient([ + get_class($request) => $response, + ]); + + $client->setIdempotencyKey('idempotentFooBar'); + + $response = $client->send($request); + + $this->assertTrue($response->getPendingRequest()->headers()->has(ApplyIdempotencyKey::IDEMPOTENCY_KEY_HEADER)); + $this->assertEquals('idempotentFooBar', $response->getPendingRequest()->headers()->get(ApplyIdempotencyKey::IDEMPOTENCY_KEY_HEADER)); + } + + public static function providesMutatingRequests(): array + { + return [ + 'delete' => [ + new DynamicDeleteRequest(''), + MockResponse::noContent(), + ], + 'post' => [ + new CreatePaymentRequest(new CreatePaymentPayload( + 'test', + new Money('EUR', '100.00'), + )), + MockResponse::ok('payment'), + ], + 'patch' => [ + new UpdatePaymentRequest('tr_payment-id', new UpdatePaymentPayload( + 'test', + )), + MockResponse::ok('payment'), + ], + ]; + } + + /** @test */ + public function idempotency_key_is_not_used_on_get_requests() + { + $client = new MockMollieClient([ + DynamicGetRequest::class => MockResponse::noContent(), + ]); + + $client->setIdempotencyKey('idempotentFooBar'); + + $response = $client->send(new DynamicGetRequest('')); + + $this->assertFalse($response->getPendingRequest()->headers()->has(ApplyIdempotencyKey::IDEMPOTENCY_KEY_HEADER)); + } + + /** @test */ + public function idempotency_key_resets_after_each_request() + { + $client = new MockMollieClient([ + DynamicDeleteRequest::class => MockResponse::noContent(), + ]); + + $client->setIdempotencyKey('idempotentFooBar'); + + $this->assertEquals('idempotentFooBar', $client->getIdempotencyKey()); + + $client->send(new DynamicDeleteRequest('')); + + $this->assertNull($client->getIdempotencyKey()); + } + + /** @test */ + public function it_uses_the_idempotency_key_generator() + { + $client = new MockMollieClient([ + DynamicDeleteRequest::class => MockResponse::noContent(), + ]); + + $fakeIdempotencyKeyGenerator = new FakeIdempotencyKeyGenerator; + $fakeIdempotencyKeyGenerator->setFakeKey('fake-idempotency-key'); + + $client->setIdempotencyKeyGenerator($fakeIdempotencyKeyGenerator); + + $this->assertNull($client->getIdempotencyKey()); + + $response = $client->send(new DynamicDeleteRequest('')); + + $this->assertEquals('fake-idempotency-key', $response->getPendingRequest()->headers()->get(ApplyIdempotencyKey::IDEMPOTENCY_KEY_HEADER)); + $this->assertNull($client->getIdempotencyKey()); + } + + /** @test */ + public function testmode_is_added_to_request_when_enabled() + { + $client = new MockMollieClient([ + DynamicGetRequest::class => MockResponse::ok('{"resource": "payment"}'), + ]); + + $client->test(true); + + $response = $client->send(new DynamicGetRequest('')); + + $this->assertTrue($response->getPendingRequest()->query()->has('testmode')); + $this->assertTrue($response->getPendingRequest()->query()->get('testmode')); + } + + /** @test */ + public function testmode_is_removed_when_using_api_key_authentication() + { + $client = new MockMollieClient([ + DynamicGetRequest::class => MockResponse::ok('{"resource": "payment"}'), + ]); + + $client->setApiKey('test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); + $client->test(true); + + $response = $client->send(new DynamicGetRequest('')); + + $this->assertFalse($response->getPendingRequest()->query()->has('testmode')); + } + + /** @test */ + public function testmode_is_not_removed_when_not_using_api_key_authentication() + { + $client = new MockMollieClient([ + DynamicGetRequest::class => MockResponse::ok('{"resource": "payment"}'), + ]); + + // Not setting an API key, so using default authentication + // by default we use access token authentication in tests + $client->test(true); + + $response = $client->send(new DynamicGetRequest('')); + + $this->assertTrue($response->getPendingRequest()->query()->has('testmode')); + $this->assertTrue($response->getPendingRequest()->query()->get('testmode')); + } + + /** @test */ + public function can_hydrate_response_into_custom_resource_wrapper_class() + { + $client = new MockMollieClient([ + DynamicGetRequest::class => MockResponse::ok('{"resource": "payment"}'), + ]); + + /** @var DummyResourceWrapper $response */ + $response = $client->send( + (new DynamicGetRequest('')) + ->setHydratableResource(new WrapperResource(DummyResourceWrapper::class)) + ); + + $this->assertInstanceOf(DummyResourceWrapper::class, $response); + } + + /** @test */ + public function empty_or_null_query_parameters_are_not_added_to_the_request() + { + $client = new MockMollieClient([ + DynamicGetRequest::class => function (PendingRequest $pendingRequest) { + $this->assertEquals([ + 'filled' => 'bar', + ], $pendingRequest->query()->all()); + $this->assertEquals('filled=bar', $pendingRequest->getUri()->getQuery()); + + return MockResponse::noContent(); + }, + ]); + + $client->send(new DynamicGetRequest('', [ + 'filled' => 'bar', + 'empty' => '', + 'null' => null, + 'empty_array' => [], + ])); + } + + /** @test */ + public function empty_or_null_payload_parameters_are_not_added_to_the_request() + { + $client = new MockMollieClient([ + DummyPostRequest::class => function (PendingRequest $pendingRequest) { + $this->assertEquals([ + 'filled' => 'bar', + ], $pendingRequest->payload()->all()); + + return MockResponse::noContent(); + }, + ]); + + $request = new DummyPostRequest; + + $request->payload()->set([ + 'filled' => 'bar', + 'empty' => '', + 'null' => null, + 'empty_array' => [], + ]); + + $client->send($request); + } +} + +class DummyResourceWrapper extends ResourceWrapper +{ + public static function fromResource($resource): self + { + return (new self)->wrap($resource); + } +} + +class DummyPostRequest extends Request implements HasPayload +{ + use HasJsonPayload; + + protected static string $method = Method::POST; + + public function resolveResourcePath(): string + { + return 'dummy'; + } +} diff --git a/tests/Resources/BaseCollectionTest.php b/tests/Resources/BaseCollectionTest.php new file mode 100644 index 000000000..7aeaa827c --- /dev/null +++ b/tests/Resources/BaseCollectionTest.php @@ -0,0 +1,126 @@ +connectorMock = $this->createMock(Connector::class); + } + + /** @test */ + public function constructor_initializes_collection_properly() + { + $items = ['item1', 'item2']; + $links = new stdClass; + $links->self = 'https://api.mollie.com/v2/test'; + + $collection = new TestCollection($this->connectorMock, $items, $links); + + $this->assertCount(2, $collection); + $this->assertSame($items, $collection->getArrayCopy()); + $this->assertSame($links, $collection->_links); + } + + /** @test */ + public function contains_returns_true_when_item_exists() + { + $items = [ + 'apple', + 'banana', + 'orange', + ]; + + $collection = new TestCollection($this->connectorMock, $items); + + $this->assertTrue($collection->contains(fn ($item) => $item === 'banana')); + } + + /** @test */ + public function contains_returns_false_when_item_does_not_exist() + { + $items = [ + 'apple', + 'banana', + 'orange', + ]; + + $collection = new TestCollection($this->connectorMock, $items); + + $this->assertFalse($collection->contains(fn ($item) => $item === 'grape')); + } + + /** @test */ + public function filter_returns_filtered_collection() + { + $items = [ + 'apple', + 'banana', + 'orange', + ]; + + $collection = new TestCollection($this->connectorMock, $items); + $filtered = $collection->filter(fn ($item) => $item !== 'banana'); + + $this->assertCount(2, $filtered); + $this->assertContains('apple', $filtered); + $this->assertContains('orange', $filtered); + $this->assertNotContains('banana', $filtered); + + // Verify it returns a new collection instance + $this->assertInstanceOf(TestCollection::class, $filtered); + $this->assertNotSame($collection, $filtered); + } + + /** @test */ + public function first_returns_first_item() + { + $collection = new TestCollection($this->connectorMock, ['item1', 'item2']); + $this->assertEquals('item1', $collection->first()); + } + + /** @test */ + public function first_where_returns_first_item_where_condition_is_true() + { + $collection = new TestCollection($this->connectorMock, [ + ['id' => 'item1'], + ['id' => 'item2'], + ]); + + $this->assertEquals(['id' => 'item2'], $collection->firstWhere('id', 'item2')); + $this->assertEquals(['id' => 'item1'], $collection->firstWhere(fn ($item) => $item['id'] === 'item1')); + } + + /** @test */ + public function get_collection_resource_name_returns_name() + { + $this->assertEquals('test_collection', TestCollection::getCollectionResourceName()); + } + + /** @test */ + public function get_collection_resource_name_throws_exception_when_empty() + { + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Collection name not set'); + + EmptyCollection::getCollectionResourceName(); + } +} + +class TestCollection extends BaseCollection +{ + public static string $collectionName = 'test_collection'; +} + +class EmptyCollection extends BaseCollection +{ + // Intentionally empty collection name +} diff --git a/tests/Resources/CursorCollectionTest.php b/tests/Resources/CursorCollectionTest.php new file mode 100644 index 000000000..4c7b2f9cb --- /dev/null +++ b/tests/Resources/CursorCollectionTest.php @@ -0,0 +1,152 @@ + MockResponse::ok('cursor-collection'), + ]); + + $collection = new PaymentCollection( + $client, + [], + $this->arrayToObject([ + 'next' => [ + 'href' => 'https://api.mollie.com/v2/payments?from=tr_*', + ], + ]) + ); + + $this->assertTrue($collection->hasNext()); + + $nextPage = $collection->next(); + + $this->assertFalse($nextPage->hasNext()); + } + + public function test_will_return_null_if_no_next_result_is_available() + { + $client = new MockMollieClient; + + $collection = new PaymentCollection( + $client, + [], + (object) [] + ); + + $this->assertFalse($collection->hasNext()); + $this->assertNull($collection->next()); + } + + public function test_can_get_previous_collection_result_when_previous_link_is_available() + { + $client = new MockMollieClient([ + DynamicGetRequest::class => MockResponse::ok('cursor-collection'), + ]); + + $collection = new PaymentCollection( + $client, + [], + $this->arrayToObject([ + 'previous' => [ + 'href' => 'https://api.mollie.com/v2/payments?from=tr_*', + ], + ]) + ); + + $this->assertTrue($collection->hasPrevious()); + + $previousPage = $collection->previous(); + + $this->assertFalse($previousPage->hasPrevious()); + } + + public function test_will_return_null_if_no_previous_result_is_available() + { + $client = new MockMollieClient; + + $collection = new PaymentCollection( + $client, + [], + (object) [] + ); + + $this->assertFalse($collection->hasPrevious()); + $this->assertNull($collection->previous()); + } + + public function test_auto_paginator_returns_lazy_collection() + { + $client = new MockMollieClient; + + $collection = new PaymentCollection( + $client, + [], + (object) [] + ); + + $this->assertInstanceOf(LazyCollection::class, $collection->getAutoIterator()); + } + + public function test_auto_paginator_can_handle_consecutive_calls() + { + $client = new MockMollieClient([ + DynamicGetRequest::class => new SequenceMockResponse( + MockResponse::ok('cursor-collection-next', 'tr_stTC2WHAuF'), + MockResponse::ok('cursor-collection-next', 'tr_stTC2WHAuS'), + MockResponse::ok('cursor-collection', 'tr_stTC2WHAuB') + ), + ]); + + $collection = new PaymentCollection( + $client, + [], + $this->arrayToObject([ + 'next' => [ + 'href' => 'https://api.mollie.com/v2/payments?from=tr_stTC2WHAuS', + ], + ]) + ); + + $paymentIds = []; + foreach ($collection->getAutoIterator() as $payment) { + $paymentIds[] = $payment->id; + } + + $this->assertEquals(['tr_stTC2WHAuF', 'tr_stTC2WHAuS', 'tr_stTC2WHAuB'], $paymentIds); + } + + /** + * Convert an array to an object recursively. + * + * @param mixed $data + * @return mixed + */ + private function arrayToObject($data) + { + if (! is_array($data)) { + return $data; + } + + $obj = new stdClass; + + foreach ($data as $key => $value) { + $obj->$key = $this->arrayToObject($value); + } + + return $obj; + } +} diff --git a/tests/Resources/InvoiceTest.php b/tests/Resources/InvoiceTest.php new file mode 100644 index 000000000..f5620e856 --- /dev/null +++ b/tests/Resources/InvoiceTest.php @@ -0,0 +1,45 @@ +createMock(MollieApiClient::class), + ); + $invoice->status = $status; + + $this->assertEquals($expected_boolean, $invoice->{$function}()); + } + + public function dpTestInvoiceStatuses() + { + return [ + [InvoiceStatus::PAID, 'isPaid', true], + [InvoiceStatus::PAID, 'isOpen', false], + [InvoiceStatus::PAID, 'isOverdue', false], + + [InvoiceStatus::OPEN, 'isPaid', false], + [InvoiceStatus::OPEN, 'isOpen', true], + [InvoiceStatus::OPEN, 'isOverdue', false], + + [InvoiceStatus::OVERDUE, 'isPaid', false], + [InvoiceStatus::OVERDUE, 'isOpen', false], + [InvoiceStatus::OVERDUE, 'isOverdue', true], + ]; + } +} diff --git a/tests/Mollie/API/Resources/LazyCollectionTest.php b/tests/Resources/LazyCollectionTest.php similarity index 57% rename from tests/Mollie/API/Resources/LazyCollectionTest.php rename to tests/Resources/LazyCollectionTest.php index 726c76bc5..d7bf9c168 100644 --- a/tests/Mollie/API/Resources/LazyCollectionTest.php +++ b/tests/Resources/LazyCollectionTest.php @@ -1,6 +1,6 @@ assertEquals(3, $this->collection->count()); $this->assertEquals(1, $this->collection->get(0)); @@ -31,50 +32,58 @@ public function testCanCreateACollectionFromGeneratorFunction() $this->assertEquals(3, $this->collection->get(2)); } - public function testFilter() + /** @test */ + public function can_filter_collection() { $filtered = $this->collection->filter(function ($value) { return $value > 1; }); $this->assertEquals(2, $filtered->count()); + $this->assertEquals([2, 3], array_values($filtered->all())); } - public function testAll() + /** @test */ + public function can_get_all_items() { $this->assertEquals([1, 2, 3], $this->collection->all()); } - public function testFirst() + /** @test */ + public function can_get_first_item() { $this->assertEquals(1, $this->collection->first()); + } + + /** @test */ + public function can_get_first_item_with_callback() + { $this->assertEquals(3, $this->collection->first(function ($value) { return $value === 3; })); } - public function testMap() + /** @test */ + public function can_map_collection() { $mapped = $this->collection->map(function ($value) { return $value * 2; }); - - $mapped->every(function ($value, $key) { - $this->assertEquals($value, $this->collection->get($key) * 2); - - return true; - }); + $this->assertEquals([2, 4, 6], $mapped->all()); } - public function testTake() + /** @test */ + public function can_take_items() { $taken = $this->collection->take(2); $this->assertEquals(2, $taken->count()); + $this->assertEquals([1, 2], $taken->all()); } - public function testEvery() + /** @test */ + public function can_check_every_item() { $this->assertTrue($this->collection->every(function ($value) { return $value > 0; @@ -85,16 +94,37 @@ public function testEvery() })); } - public function testChainedUsage() + /** @test */ + public function can_chain_methods() { $result = $this->collection ->filter(function ($value) { return $value > 1; - })->map(function ($value) { + }) + ->map(function ($value) { return $value * 2; - })->take(1); + }) + ->take(1); $this->assertEquals(1, $result->count()); $this->assertEquals(4, $result->first()); } + + /** @test */ + public function can_iterate_over_collection() + { + $items = []; + foreach ($this->collection as $item) { + $items[] = $item; + } + + $this->assertEquals([1, 2, 3], $items); + } + + /** @test */ + public function can_get_item_by_key() + { + $this->assertEquals(2, $this->collection->get(1)); + $this->assertNull($this->collection->get(99)); + } } diff --git a/tests/Resources/MandateCollectionTest.php b/tests/Resources/MandateCollectionTest.php new file mode 100644 index 000000000..824478ad0 --- /dev/null +++ b/tests/Resources/MandateCollectionTest.php @@ -0,0 +1,68 @@ +client = $this->createMock(MollieApiClient::class); + } + + public function test_where_status() + { + $collection = new MandateCollection($this->client, [ + $this->getMandateWithStatus(MandateStatus::VALID), + $this->getMandateWithStatus(MandateStatus::VALID), + $this->getMandateWithStatus(MandateStatus::VALID), + $this->getMandateWithStatus(MandateStatus::INVALID), + $this->getMandateWithStatus(MandateStatus::INVALID), + $this->getMandateWithStatus(MandateStatus::PENDING), + ]); + + $valid = $collection->whereStatus(MandateStatus::VALID); + $invalid = $collection->whereStatus(MandateStatus::INVALID); + $pending = $collection->whereStatus(MandateStatus::PENDING); + + $this->assertInstanceOf(MandateCollection::class, $collection); + $this->assertInstanceOf(MandateCollection::class, $valid); + $this->assertInstanceOf(MandateCollection::class, $invalid); + $this->assertInstanceOf(MandateCollection::class, $pending); + + $this->assertCount(6, $collection); + $this->assertEquals(6, $collection->count()); + $this->assertCount(3, $valid); + $this->assertEquals(3, $valid->count()); + $this->assertCount(2, $invalid); + $this->assertEquals(2, $invalid->count()); + $this->assertCount(1, $pending); + $this->assertEquals(1, $pending->count()); + } + + /** + * @param string $status + * @return \Mollie\Api\Resources\Mandate + */ + protected function getMandateWithStatus($status) + { + $mandate = new Mandate( + $this->createMock(MollieApiClient::class), + ); + $mandate->status = $status; + + return $mandate; + } +} diff --git a/tests/Mollie/API/Resources/MethodTest.php b/tests/Resources/MethodTest.php similarity index 58% rename from tests/Mollie/API/Resources/MethodTest.php rename to tests/Resources/MethodTest.php index 2af382a1f..2bc7471fc 100644 --- a/tests/Mollie/API/Resources/MethodTest.php +++ b/tests/Resources/MethodTest.php @@ -1,17 +1,19 @@ createMock(MollieApiClient::class)); + $method = new Method(new MockMollieClient); + $method->setResponse($this->createMock(Response::class)); $this->assertNull($method->issuers); $issuers = $method->issuers(); diff --git a/tests/Resources/OnboardingTest.php b/tests/Resources/OnboardingTest.php new file mode 100644 index 000000000..db0451ec1 --- /dev/null +++ b/tests/Resources/OnboardingTest.php @@ -0,0 +1,44 @@ +createMock(MollieApiClient::class), + ); + $onboarding->status = $status; + + $this->assertEquals($expected_boolean, $onboarding->{$function}()); + } + + public function dpTestOnboardingStatuses() + { + return [ + [OnboardingStatus::NEEDS_DATA, 'needsData', true], + [OnboardingStatus::NEEDS_DATA, 'inReview', false], + [OnboardingStatus::NEEDS_DATA, 'isCompleted', false], + + [OnboardingStatus::IN_REVIEW, 'needsData', false], + [OnboardingStatus::IN_REVIEW, 'inReview', true], + [OnboardingStatus::IN_REVIEW, 'isCompleted', false], + + [OnboardingStatus::COMPLETED, 'needsData', false], + [OnboardingStatus::COMPLETED, 'inReview', false], + [OnboardingStatus::COMPLETED, 'isCompleted', true], + ]; + } +} diff --git a/tests/Resources/PaymentTest.php b/tests/Resources/PaymentTest.php new file mode 100644 index 000000000..d8a78a00d --- /dev/null +++ b/tests/Resources/PaymentTest.php @@ -0,0 +1,311 @@ +createMock(MollieApiClient::class), + ); + $payment->status = $status; + + $this->assertEquals($expected_boolean, $payment->{$function}()); + } + + public function dpTestPaymentStatuses() + { + return [ + [PaymentStatus::PENDING, 'isPending', true], + [PaymentStatus::PENDING, 'isAuthorized', false], + [PaymentStatus::PENDING, 'isFailed', false], + [PaymentStatus::PENDING, 'isOpen', false], + [PaymentStatus::PENDING, 'isCanceled', false], + [PaymentStatus::PENDING, 'isPaid', false], + [PaymentStatus::PENDING, 'isExpired', false], + + [PaymentStatus::AUTHORIZED, 'isPending', false], + [PaymentStatus::AUTHORIZED, 'isAuthorized', true], + [PaymentStatus::AUTHORIZED, 'isFailed', false], + [PaymentStatus::AUTHORIZED, 'isOpen', false], + [PaymentStatus::AUTHORIZED, 'isCanceled', false], + [PaymentStatus::AUTHORIZED, 'isPaid', false], + [PaymentStatus::AUTHORIZED, 'isExpired', false], + + [PaymentStatus::FAILED, 'isPending', false], + [PaymentStatus::FAILED, 'isAuthorized', false], + [PaymentStatus::FAILED, 'isFailed', true], + [PaymentStatus::FAILED, 'isOpen', false], + [PaymentStatus::FAILED, 'isCanceled', false], + [PaymentStatus::FAILED, 'isPaid', false], + [PaymentStatus::FAILED, 'isExpired', false], + + [PaymentStatus::OPEN, 'isPending', false], + [PaymentStatus::OPEN, 'isAuthorized', false], + [PaymentStatus::OPEN, 'isFailed', false], + [PaymentStatus::OPEN, 'isOpen', true], + [PaymentStatus::OPEN, 'isCanceled', false], + [PaymentStatus::OPEN, 'isPaid', false], + [PaymentStatus::OPEN, 'isExpired', false], + + [PaymentStatus::CANCELED, 'isPending', false], + [PaymentStatus::CANCELED, 'isAuthorized', false], + [PaymentStatus::CANCELED, 'isFailed', false], + [PaymentStatus::CANCELED, 'isOpen', false], + [PaymentStatus::CANCELED, 'isCanceled', true], + [PaymentStatus::CANCELED, 'isPaid', false], + [PaymentStatus::CANCELED, 'isExpired', false], + + [PaymentStatus::EXPIRED, 'isPending', false], + [PaymentStatus::EXPIRED, 'isAuthorized', false], + [PaymentStatus::EXPIRED, 'isFailed', false], + [PaymentStatus::EXPIRED, 'isOpen', false], + [PaymentStatus::EXPIRED, 'isCanceled', false], + [PaymentStatus::EXPIRED, 'isPaid', false], + [PaymentStatus::EXPIRED, 'isExpired', true], + ]; + } + + public function test_is_paid_returns_true_when_paid_datetime_is_set() + { + $payment = new Payment( + $this->createMock(MollieApiClient::class), + ); + + $payment->paidAt = '2016-10-24'; + $this->assertTrue($payment->isPaid()); + } + + public function test_has_refunds_returns_true_when_payment_has_refunds() + { + $payment = new Payment( + $this->createMock(MollieApiClient::class), + ); + + $payment->_links = new stdClass; + $payment->_links->refunds = (object) ['href' => 'https://api.mollie.com/v2/payments/tr_44aKxzEbr8/refunds', 'type' => 'application/hal+json']; + + $this->assertTrue($payment->hasRefunds()); + } + + public function test_has_refunds_returns_false_when_payment_has_no_refunds() + { + $payment = new Payment( + $this->createMock(MollieApiClient::class), + ); + + $payment->_links = new stdClass; + $this->assertFalse($payment->hasRefunds()); + } + + public function test_has_chargebacks_returns_true_when_payment_has_chargebacks() + { + $payment = new Payment( + $this->createMock(MollieApiClient::class), + ); + + $payment->_links = new stdClass; + $payment->_links->chargebacks = (object) ['href' => 'https://api.mollie.com/v2/payments/tr_44aKxzEbr8/chargebacks', 'type' => 'application/hal+json']; + + $this->assertTrue($payment->hasChargebacks()); + } + + public function test_has_chargebacks_returns_false_when_payment_has_no_chargebacks() + { + $payment = new Payment( + $this->createMock(MollieApiClient::class), + ); + + $payment->_links = new stdClass; + $this->assertFalse($payment->hasChargebacks()); + } + + public function test_has_recurring_type_returns_true_when_recurring_type_is_first() + { + $payment = new Payment( + $this->createMock(MollieApiClient::class), + ); + + $payment->sequenceType = SequenceType::FIRST; + $this->assertFalse($payment->hasSequenceTypeRecurring()); + $this->assertTrue($payment->hasSequenceTypeFirst()); + } + + public function test_has_recurring_type_returns_true_when_recurring_type_is_recurring() + { + $payment = new Payment( + $this->createMock(MollieApiClient::class), + ); + + $payment->sequenceType = SequenceType::RECURRING; + $this->assertTrue($payment->hasSequenceTypeRecurring()); + $this->assertFalse($payment->hasSequenceTypeFirst()); + } + + public function test_has_recurring_type_returns_false_when_recurring_type_is_none() + { + $payment = new Payment( + $this->createMock(MollieApiClient::class), + ); + + $payment->sequenceType = SequenceType::ONEOFF; + $this->assertFalse($payment->hasSequenceTypeFirst()); + $this->assertFalse($payment->hasSequenceTypeRecurring()); + } + + public function test_get_checkout_url_returns_payment_url_from_links_object() + { + $payment = new Payment( + $this->createMock(MollieApiClient::class), + ); + + $payment->_links = new stdClass; + $payment->_links->checkout = new stdClass; + $payment->_links->checkout->href = 'https://example.com'; + + $this->assertSame($payment->getCheckoutUrl(), 'https://example.com'); + } + + public function test_get_mobile_app_checkout_url_returns_payment_url_from_links_object() + { + $payment = new Payment( + $this->createMock(MollieApiClient::class), + ); + + $payment->_links = new stdClass; + $payment->_links->mobileAppCheckout = new stdClass; + $payment->_links->mobileAppCheckout->href = 'https://example-mobile-checkout.com'; + + $this->assertSame($payment->getMobileAppCheckoutUrl(), 'https://example-mobile-checkout.com'); + } + + public function test_can_be_refunded_returns_true_when_amount_remaining_is_set() + { + $payment = new Payment( + $this->createMock(MollieApiClient::class), + ); + + $amountRemaining = new Stdclass; + $amountRemaining->value = '15.00'; + $amountRemaining->currency = 'EUR'; + + $payment->amountRemaining = $amountRemaining; + $this->assertTrue($payment->canBeRefunded()); + $this->assertTrue($payment->canBePartiallyRefunded()); + } + + public function test_can_be_refunded_returns_false_when_amount_remaining_is_null() + { + $payment = new Payment( + $this->createMock(MollieApiClient::class), + ); + + $payment->amountRemaining = null; + $this->assertFalse($payment->canBeRefunded()); + $this->assertFalse($payment->canBePartiallyRefunded()); + } + + public function test_get_amount_refunded_returns_amount_refunded_as_float() + { + $payment = new Payment( + $this->createMock(MollieApiClient::class), + ); + + $payment->amountRefunded = (object) ['value' => 22.0, 'currency' => 'EUR']; + self::assertSame(22.0, $payment->getAmountRefunded()); + } + + public function test_get_amount_refunded_returns0_when_amount_refunded_is_set_to_null() + { + $payment = new Payment( + $this->createMock(MollieApiClient::class), + ); + + $payment->amountRefunded = null; + self::assertSame(0.0, $payment->getAmountRefunded()); + } + + public function test_get_amount_remaining_returns_amount_remaining_as_float() + { + $payment = new Payment( + $this->createMock(MollieApiClient::class), + ); + + $payment->amountRemaining = (object) ['value' => 22.0, 'currency' => 'EUR']; + self::assertSame(22.0, $payment->getAmountRemaining()); + } + + public function test_get_amount_remaining_returns0_when_amount_remaining_is_set_to_null() + { + $payment = new Payment( + $this->createMock(MollieApiClient::class), + ); + + $payment->amountRefunded = null; + self::assertSame(0.0, $payment->getAmountRemaining()); + } + + public function test_get_amount_charged_back_returns_amount_charged_back_as_float() + { + $payment = new Payment( + $this->createMock(MollieApiClient::class), + ); + + $payment->amountChargedBack = (object) ['value' => 22.0, 'currency' => 'EUR']; + self::assertSame(22.0, $payment->getAmountChargedBack()); + } + + public function test_get_amount_charged_back_returns0_when_amount_charged_back_is_set_to_null() + { + $payment = new Payment( + $this->createMock(MollieApiClient::class), + ); + + $payment->amountChargedBack = null; + self::assertSame(0.0, $payment->getAmountChargedBack()); + } + + public function test_get_settlement_amount_returns0_when_settlement_amount_is_set_to_null() + { + $payment = new Payment( + $this->createMock(MollieApiClient::class), + ); + + $payment->settlementAmount = null; + self::assertSame(0.0, $payment->getSettlementAmount()); + } + + public function test_get_settlement_amount_returns_settlement_amount_as_float() + { + $payment = new Payment( + $this->createMock(MollieApiClient::class), + ); + + $payment->settlementAmount = (object) ['value' => 22.0, 'currency' => 'EUR']; + self::assertSame(22.0, $payment->getSettlementAmount()); + } + + public function test_has_split_payments_returns_false_when_payment_has_no_split() + { + $payment = new Payment( + $this->createMock(MollieApiClient::class), + ); + + $payment->_links = new stdClass; + $this->assertFalse($payment->hasSplitPayments()); + } +} diff --git a/tests/Resources/ProfileTest.php b/tests/Resources/ProfileTest.php new file mode 100644 index 000000000..8b02fea5c --- /dev/null +++ b/tests/Resources/ProfileTest.php @@ -0,0 +1,44 @@ +createMock(MollieApiClient::class), + ); + $profile->status = $status; + + $this->assertEquals($expected_boolean, $profile->{$function}()); + } + + public function dpTestProfileStatusses() + { + return [ + [ProfileStatus::BLOCKED, 'isBlocked', true], + [ProfileStatus::BLOCKED, 'isVerified', false], + [ProfileStatus::BLOCKED, 'isUnverified', false], + + [ProfileStatus::VERIFIED, 'isBlocked', false], + [ProfileStatus::VERIFIED, 'isVerified', true], + [ProfileStatus::VERIFIED, 'isUnverified', false], + + [ProfileStatus::UNVERIFIED, 'isBlocked', false], + [ProfileStatus::UNVERIFIED, 'isVerified', false], + [ProfileStatus::UNVERIFIED, 'isUnverified', true], + ]; + } +} diff --git a/tests/Resources/RefundTest.php b/tests/Resources/RefundTest.php new file mode 100644 index 000000000..c8be569e0 --- /dev/null +++ b/tests/Resources/RefundTest.php @@ -0,0 +1,90 @@ +createMock(MollieApiClient::class), + ); + $refund->status = $status; + + $this->assertEquals($expected_boolean, $refund->{$function}()); + } + + /** + * @param string $status + * @param bool $expected_boolean + * + * @dataProvider dpTestRefundCanBeCanceled + */ + public function test_refund_can_be_canceled($status, $expected_boolean) + { + $refund = new Refund( + $this->createMock(MollieApiClient::class), + ); + $refund->status = $status; + + $this->assertEquals($expected_boolean, $refund->canBeCanceled()); + } + + public function dpTestRefundStatuses() + { + return [ + [RefundStatus::PENDING, 'isPending', true], + [RefundStatus::PENDING, 'isProcessing', false], + [RefundStatus::PENDING, 'isQueued', false], + [RefundStatus::PENDING, 'isTransferred', false], + [RefundStatus::PENDING, 'isFailed', false], + + [RefundStatus::PROCESSING, 'isPending', false], + [RefundStatus::PROCESSING, 'isProcessing', true], + [RefundStatus::PROCESSING, 'isQueued', false], + [RefundStatus::PROCESSING, 'isTransferred', false], + [RefundStatus::PROCESSING, 'isFailed', false], + + [RefundStatus::QUEUED, 'isPending', false], + [RefundStatus::QUEUED, 'isProcessing', false], + [RefundStatus::QUEUED, 'isQueued', true], + [RefundStatus::QUEUED, 'isTransferred', false], + [RefundStatus::QUEUED, 'isFailed', false], + + [RefundStatus::REFUNDED, 'isPending', false], + [RefundStatus::REFUNDED, 'isProcessing', false], + [RefundStatus::REFUNDED, 'isQueued', false], + [RefundStatus::REFUNDED, 'isTransferred', true], + [RefundStatus::REFUNDED, 'isFailed', false], + + [RefundStatus::FAILED, 'isPending', false], + [RefundStatus::FAILED, 'isProcessing', false], + [RefundStatus::FAILED, 'isQueued', false], + [RefundStatus::FAILED, 'isTransferred', false], + [RefundStatus::FAILED, 'isFailed', true], + ]; + } + + public function dpTestRefundCanBeCanceled() + { + return [ + [RefundStatus::PENDING, true], + [RefundStatus::PROCESSING, false], + [RefundStatus::QUEUED, true], + [RefundStatus::REFUNDED, false], + [RefundStatus::FAILED, false], + [RefundStatus::CANCELED, false], + ]; + } +} diff --git a/tests/Resources/ResourceFactoryTest.php b/tests/Resources/ResourceFactoryTest.php new file mode 100644 index 000000000..972799748 --- /dev/null +++ b/tests/Resources/ResourceFactoryTest.php @@ -0,0 +1,321 @@ +createMock(MollieApiClient::class), + $apiResult, + Payment::class, + $this->createMock(Response::class) + ); + + $this->assertInstanceOf(Payment::class, $payment); + $this->assertEquals('payment', $payment->resource); + $this->assertEquals('tr_44aKxzEbr8', $payment->id); + $this->assertEquals('test', $payment->mode); + $this->assertEquals('2018-03-13T14:02:29+00:00', $payment->createdAt); + $this->assertEquals((object) ['value' => '20.00', 'currency' => 'EUR'], $payment->amount); + } + + /** @test */ + public function embedded_collections_are_type_casted() + { + $apiResult = json_decode('{ + "resource":"payment", + "id":"tr_44aKxzEbr8", + "mode":"test", + "createdAt":"2018-03-13T14:02:29+00:00", + "amount":{ + "value":"20.00", + "currency":"EUR" + }, + "_embedded": { + "refunds": [ + { + "resource": "refund", + "id": "re_4qqhO89gsT", + "amount": { + "value": "20.00", + "currency": "EUR" + } + } + ] + } + }'); + + /** @var Payment $payment */ + $payment = ResourceFactory::createFromApiResult( + $this->createMock(MollieApiClient::class), + $apiResult, + Payment::class, + $this->createMock(Response::class) + ); + + $this->assertInstanceOf(Payment::class, $payment); + /** @phpstan-ignore-next-line */ + $this->assertInstanceOf(RefundCollection::class, $payment->_embedded->refunds); + } + + /** @test */ + /** @test */ + public function embedded_resources_are_type_casted() + { + $apiResult = json_decode('{ + "resource": "client", + "id": "org_1337", + "organizationCreatedAt": "2018-03-21T13:13:37+00:00", + "commission": { + "count": 200, + "totalAmount": { + "currency": "EUR", + "value": "10.00" + } + }, + "_embedded": { + "onboarding": { + "resource": "onboarding", + "name": "Mollie B.V.", + "signedUpAt": "2018-12-20T10:49:08+00:00", + "status": "completed", + "canReceivePayments": true, + "canReceiveSettlements": true + } + } + }'); + + /** @var Client $client */ + $client = ResourceFactory::createFromApiResult( + $this->createMock(MollieApiClient::class), + $apiResult, + Client::class, + $this->createMock(Response::class) + ); + + $this->assertInstanceOf(Client::class, $client); + /** @phpstan-ignore-next-line */ + $this->assertInstanceOf(Onboarding::class, $client->_embedded->onboarding); + } + + /** @test */ + public function it_throws_exception_when_response_is_missing() + { + $apiResult = new \stdClass; + + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('Response is required'); + + ResourceFactory::createFromApiResult( + $this->createMock(MollieApiClient::class), + $apiResult, + Payment::class + ); + } + + /** @test */ + public function response_param_is_optional_when_data_is_a_response() + { + $jsonData = '{ + "resource":"payment", + "id":"tr_44aKxzEbr8" + }'; + + $response = $this->createMock(Response::class); + $response->method('json')->willReturn(json_decode($jsonData)); + + $payment = ResourceFactory::createFromApiResult( + $this->createMock(MollieApiClient::class), + $response, + Payment::class + ); + + $this->assertInstanceOf(Payment::class, $payment); + $this->assertEquals('tr_44aKxzEbr8', $payment->id); + } + + /** @test */ + public function it_throws_exception_for_unmapped_embedded_resources() + { + $apiResult = json_decode('{ + "resource":"payment", + "id":"tr_44aKxzEbr8", + "_embedded": { + "unknown_resource": { + "id": "test" + } + } + }'); + + $this->expectException(\Mollie\Api\Exceptions\EmbeddedResourcesNotParseableException::class); + + ResourceFactory::createFromApiResult( + $this->createMock(MollieApiClient::class), + $apiResult, + Payment::class, + $this->createMock(Response::class) + ); + } + + /** @test */ + public function it_creates_base_resource_collection() + { + $response = $this->createMock(Response::class); + $data = [ + ['id' => 'payment-1', 'resource' => 'payment'], + ['id' => 'payment-2', 'resource' => 'payment'], + ]; + + $collection = ResourceFactory::createBaseResourceCollection( + $this->createMock(MollieApiClient::class), + Payment::class, + $response, + $data + ); + + $this->assertInstanceOf(PaymentCollection::class, $collection); + $this->assertCount(2, $collection); + $this->assertInstanceOf(Payment::class, $collection[0]); + $this->assertEquals('payment-1', $collection[0]->id); + } + + /** @test */ + public function it_creates_base_resource_collection_with_custom_collection_class() + { + $response = $this->createMock(Response::class); + $data = [ + ['id' => 'payment-1', 'resource' => 'payment'], + ]; + + $collection = ResourceFactory::createBaseResourceCollection( + $this->createMock(MollieApiClient::class), + Payment::class, + $response, + $data, + null, + CustomPaymentCollection::class + ); + + $this->assertInstanceOf(CustomPaymentCollection::class, $collection); + $this->assertCount(1, $collection); + } + + /** @test */ + public function it_handles_any_resource_type() + { + $apiResult = json_decode('{ + "resource":"custom", + "id":"custom_123", + "customField":"test" + }'); + + $resource = ResourceFactory::createFromApiResult( + $this->createMock(MollieApiClient::class), + $apiResult, + AnyResource::class, + $this->createMock(Response::class) + ); + + $this->assertInstanceOf(AnyResource::class, $resource); + $this->assertEquals('custom_123', $resource->id); + $this->assertEquals('test', $resource->customField); + } + + /** @test */ + public function it_creates_decorated_resource() + { + $apiResult = json_decode('{ + "resource":"onboarding", + "status":"pending", + "canReceivePayments":true, + "canReceiveSettlements":true, + "_links": { + "dashboard": { + "href": "https://my.mollie.com/dashboard/org_123" + } + } + }'); + + $resource = ResourceFactory::createFromApiResult( + $this->createMock(MollieApiClient::class), + $apiResult, + Onboarding::class, + $this->createMock(Response::class) + ); + + $decoratedResource = ResourceFactory::createDecoratedResource( + $resource, + CustomResourceDecorator::class + ); + + $this->assertInstanceOf(CustomResourceDecorator::class, $decoratedResource); + $this->assertEquals('pending', $decoratedResource->status); + $this->assertEquals('https://my.mollie.com/dashboard/org_123', $decoratedResource->dashboardUrl); + } +} + +class CustomPaymentCollection extends BaseCollection +{ + // +} + +class CustomResourceDecorator implements IsWrapper +{ + public string $status; + + public bool $canReceivePayments; + + public bool $canReceiveSettlements; + + public string $dashboardUrl; + + public function __construct( + string $status, + bool $canReceivePayments, + bool $canReceiveSettlements, + string $dashboardUrl + ) { + $this->status = $status; + $this->canReceivePayments = $canReceivePayments; + $this->canReceiveSettlements = $canReceiveSettlements; + $this->dashboardUrl = $dashboardUrl; + } + + public static function fromResource($onboarding): IsWrapper + { + /** @var Onboarding $onboarding */ + return new self( + $onboarding->status, + $onboarding->canReceivePayments, + $onboarding->canReceiveSettlements, + $onboarding->_links->dashboard->href + ); + } +} diff --git a/tests/Resources/ResourceHydratorTest.php b/tests/Resources/ResourceHydratorTest.php new file mode 100644 index 000000000..8a127ca64 --- /dev/null +++ b/tests/Resources/ResourceHydratorTest.php @@ -0,0 +1,193 @@ +hydrator = new ResourceHydrator; + $this->client = $this->createMock(MollieApiClient::class); + } + + /** @test */ + public function hydrate_simple_resource(): void + { + $request = $this->createMock(ResourceHydratableRequest::class); + $response = $this->createMock(Response::class); + + $mockResource = new class($this->client) extends BaseResource {}; + + $request->expects($this->once()) + ->method('getHydratableResource') + ->willReturn(get_class($mockResource)); + + $response->expects($this->once()) + ->method('getConnector') + ->willReturn($this->client); + + $result = $this->hydrator->hydrate($request, $response); + + $this->assertInstanceOf(BaseResource::class, $result); + } + + /** @test */ + public function hydrate_collection(): void + { + $request = $this->createMock(ResourceHydratableRequest::class); + $response = $this->createMock(Response::class); + + $mockCollection = new class($this->client) extends ResourceCollection + { + public static string $resource = AnyResource::class; + + public static string $collectionName = 'items'; + }; + + $request->expects($this->once()) + ->method('getHydratableResource') + ->willReturn(get_class($mockCollection)); + + $response->expects($this->once()) + ->method('getConnector') + ->willReturn($this->client); + + $response->expects($this->once()) + ->method('json') + ->willReturn((object) [ + '_embedded' => (object) ['items' => []], + '_links' => (object) [], + ]); + + $result = $this->hydrator->hydrate($request, $response); + + $this->assertInstanceOf(ResourceCollection::class, $result); + } + + /** @test */ + public function hydrate_iteratable_collection(): void + { + $request = $this->createMock(IteratableRequest::class); + $request->method('getHydratableResource') + ->willReturn(CustomCollection::class); + + $request->expects($this->once()) + ->method('iteratorEnabled') + ->willReturn(true); + + $request->expects($this->once()) + ->method('iteratesBackwards') + ->willReturn(false); + + $this->assertInstanceOf(IsIteratable::class, $request); + + $response = $this->createMock(Response::class); + $response->method('getConnector') + ->willReturn($this->client); + + $response->expects($this->once()) + ->method('json') + ->willReturn((object) [ + '_embedded' => (object) ['items' => [ + (object) [ + 'id' => 'id', + 'foo' => 'bar', + ], + ]], + '_links' => (object) [], + ]); + + $result = $this->hydrator->hydrate($request, $response); + + $this->assertInstanceOf(LazyCollection::class, $result); + $this->assertInstanceOf(AnyResource::class, $result->first()); + } + + /** @test */ + public function hydrate_decorated_resource(): void + { + $request = $this->createMock(ResourceHydratableRequest::class); + $response = $this->createMock(Response::class); + + $decoratedResource = new WrapperResource(CustomDecorator::class); + + $request->expects($this->exactly(2)) + ->method('getHydratableResource') + ->willReturnOnConsecutiveCalls($decoratedResource, AnyResource::class); + + $request->expects($this->once()) + ->method('resetHydratableResource') + ->willReturnSelf(); + + $response->expects($this->once()) + ->method('getConnector') + ->willReturn($this->client); + + $result = $this->hydrator->hydrate($request, $response); + + $this->assertInstanceOf(CustomDecorator::class, $result); + } + + /** @test */ + public function hydrate_returns_response_when_no_resource_target(): void + { + $request = $this->createMock(ResourceHydratableRequest::class); + $response = $this->createMock(Response::class); + + $request->expects($this->once()) + ->method('getHydratableResource') + ->willReturn('InvalidClass'); + + $result = $this->hydrator->hydrate($request, $response); + + $this->assertSame($response, $result); + } +} + +class IteratableRequest extends ResourceHydratableRequest implements IsIteratable +{ + use IsIteratableRequest; + + protected $hydratableResource = CustomCollection::class; + + public function resolveResourcePath(): string + { + return 'items'; + } +} + +class CustomCollection extends CursorCollection +{ + public static string $resource = AnyResource::class; + + public static string $collectionName = 'items'; +} + +class CustomDecorator implements IsWrapper +{ + public static function fromResource($resource): self + { + return new self; + } +} diff --git a/tests/Resources/SettlementTest.php b/tests/Resources/SettlementTest.php new file mode 100644 index 000000000..59c45a5b0 --- /dev/null +++ b/tests/Resources/SettlementTest.php @@ -0,0 +1,52 @@ +createMock(MollieApiClient::class), + ); + $settlement->status = $status; + + $this->assertEquals($expected_boolean, $settlement->{$function}()); + } + + public function dpTestSettlementStatuses() + { + return [ + [SettlementStatus::PENDING, 'isPending', true], + [SettlementStatus::PENDING, 'isOpen', false], + [SettlementStatus::PENDING, 'isPaidout', false], + [SettlementStatus::PENDING, 'isFailed', false], + + [SettlementStatus::OPEN, 'isPending', false], + [SettlementStatus::OPEN, 'isOpen', true], + [SettlementStatus::OPEN, 'isPaidout', false], + [SettlementStatus::OPEN, 'isFailed', false], + + [SettlementStatus::PAIDOUT, 'isPending', false], + [SettlementStatus::PAIDOUT, 'isOpen', false], + [SettlementStatus::PAIDOUT, 'isPaidout', true], + [SettlementStatus::PAIDOUT, 'isFailed', false], + + [SettlementStatus::FAILED, 'isPending', false], + [SettlementStatus::FAILED, 'isOpen', false], + [SettlementStatus::FAILED, 'isPaidout', false], + [SettlementStatus::FAILED, 'isFailed', true], + ]; + } +} diff --git a/tests/Resources/SubscriptionTest.php b/tests/Resources/SubscriptionTest.php new file mode 100644 index 000000000..7d67e8e2c --- /dev/null +++ b/tests/Resources/SubscriptionTest.php @@ -0,0 +1,62 @@ +createMock(MollieApiClient::class), + ); + $subscription->status = $status; + + $this->assertEquals($expected_boolean, $subscription->{$function}()); + } + + public function dpTestSubscriptionStatuses() + { + return [ + [SubscriptionStatus::PENDING, 'isPending', true], + [SubscriptionStatus::PENDING, 'isCanceled', false], + [SubscriptionStatus::PENDING, 'isCompleted', false], + [SubscriptionStatus::PENDING, 'isSuspended', false], + [SubscriptionStatus::PENDING, 'isActive', false], + + [SubscriptionStatus::CANCELED, 'isPending', false], + [SubscriptionStatus::CANCELED, 'isCanceled', true], + [SubscriptionStatus::CANCELED, 'isCompleted', false], + [SubscriptionStatus::CANCELED, 'isSuspended', false], + [SubscriptionStatus::CANCELED, 'isActive', false], + + [SubscriptionStatus::COMPLETED, 'isPending', false], + [SubscriptionStatus::COMPLETED, 'isCanceled', false], + [SubscriptionStatus::COMPLETED, 'isCompleted', true], + [SubscriptionStatus::COMPLETED, 'isSuspended', false], + [SubscriptionStatus::COMPLETED, 'isActive', false], + + [SubscriptionStatus::SUSPENDED, 'isPending', false], + [SubscriptionStatus::SUSPENDED, 'isCanceled', false], + [SubscriptionStatus::SUSPENDED, 'isCompleted', false], + [SubscriptionStatus::SUSPENDED, 'isSuspended', true], + [SubscriptionStatus::SUSPENDED, 'isActive', false], + + [SubscriptionStatus::ACTIVE, 'isPending', false], + [SubscriptionStatus::ACTIVE, 'isCanceled', false], + [SubscriptionStatus::ACTIVE, 'isCompleted', false], + [SubscriptionStatus::ACTIVE, 'isSuspended', false], + [SubscriptionStatus::ACTIVE, 'isActive', true], + ]; + } +} diff --git a/tests/Mollie/API/Types/MandateMethodTest.php b/tests/Types/MandateMethodTest.php similarity index 85% rename from tests/Mollie/API/Types/MandateMethodTest.php rename to tests/Types/MandateMethodTest.php index 02b6f6cea..16dd53f46 100644 --- a/tests/Mollie/API/Types/MandateMethodTest.php +++ b/tests/Types/MandateMethodTest.php @@ -1,6 +1,6 @@ assertEquals($expectedMethod, $actualMethod); diff --git a/tests/Utils/ArrTest.php b/tests/Utils/ArrTest.php new file mode 100644 index 000000000..6d8af09c8 --- /dev/null +++ b/tests/Utils/ArrTest.php @@ -0,0 +1,164 @@ + ['bar' => 'baz']]; + + $this->assertEquals('baz', Arr::get($array, 'foo.bar')); + $this->assertEquals(null, Arr::get($array, 'foo.baz')); + $this->assertEquals('default', Arr::get($array, 'foo.baz', 'default')); + } + + /** @test */ + public function pull(): void + { + $array = ['foo' => ['bar' => 'baz']]; + + $this->assertEquals('baz', Arr::pull($array, 'foo.bar')); + $this->assertEquals(['foo' => []], $array); + } + + /** @test */ + public function forget(): void + { + $array = ['foo' => ['bar' => 'baz']]; + + Arr::forget($array, 'foo.bar'); + + $this->assertEquals(['foo' => []], $array); + } + + /** @test */ + public function has(): void + { + $array = ['foo' => ['bar' => 'baz']]; + + $this->assertTrue(Arr::has($array, 'foo')); + $this->assertTrue(Arr::has($array, 'foo.bar')); + $this->assertFalse(Arr::has($array, 'foo.baz')); + $this->assertFalse(Arr::has($array, 'baz')); + } + + /** @test */ + public function exists(): void + { + $array = ['foo' => 'bar']; + + $this->assertTrue(Arr::exists($array, 'foo')); + $this->assertFalse(Arr::exists($array, 'bar')); + } + + /** @test */ + public function join(): void + { + $array = ['foo', 'bar', 'baz']; + + $this->assertEquals('foo, bar, baz', Arr::join($array)); + $this->assertEquals('foo-bar-baz', Arr::join($array, '-')); + } + + /** @test */ + public function wrap(): void + { + $value = 'foo'; + + $this->assertEquals(['foo'], Arr::wrap($value)); + + $array = ['foo', 'bar']; + + $this->assertEquals($array, Arr::wrap($array)); + } + + /** @test */ + public function includes(): void + { + $array = ['includes' => ['payment']]; + + $this->assertTrue(Arr::includes($array, 'includes', 'payment')); + $this->assertFalse(Arr::includes($array, 'includes', 'refund')); + } + + /** @test */ + public function resolve(): void + { + $foo = new Foo('bar', new Bar('baz')); + $anyData = new AnyData(['foo' => $foo]); + + $this->assertEquals(['foo' => ['foo' => 'bar', 'bar' => 'baz']], Arr::resolve($anyData)); + + $nullResult = Arr::resolve(null); + $this->assertEquals([], $nullResult); + + $resolvesDateTime = Arr::resolve(['dateTime' => DateTimeImmutable::createFromFormat('Y-m-d', '2024-01-01')]); + $this->assertEquals(['dateTime' => '2024-01-01'], $resolvesDateTime); + + $filtersResult = Arr::resolve(['some' => null, 'bar' => 'baz']); + $this->assertEquals(['bar' => 'baz'], $filtersResult); + + $dataCollectionResult = Arr::resolve(new DataCollection([ + new PaymentRoute( + new Money('EUR', '10.00'), + 'org_1234567890', + null + ), + ])); + + $this->assertEquals([ + [ + 'amount' => ['currency' => 'EUR', 'value' => '10.00'], + 'destination' => ['type' => 'organization', 'organizationId' => 'org_1234567890'], + ], + ], $dataCollectionResult); + } +} + +class Foo implements Resolvable +{ + public string $foo; + + public Bar $bar; + + public function __construct(string $foo, Bar $bar) + { + $this->foo = $foo; + $this->bar = $bar; + } + + public function toArray(): array + { + return [ + 'foo' => $this->foo, + 'bar' => $this->bar, + ]; + } +} + +class Bar implements Stringable +{ + public string $bar; + + public function __construct(string $bar) + { + $this->bar = $bar; + } + + public function __toString(): string + { + return $this->bar; + } +} diff --git a/tests/Utils/UrlTest.php b/tests/Utils/UrlTest.php new file mode 100644 index 000000000..a4944c308 --- /dev/null +++ b/tests/Utils/UrlTest.php @@ -0,0 +1,42 @@ +assertEquals($expected, $result); + } + + public function test_is_valid() + { + $validUrl = 'https://example.com'; + $invalidUrl = 'example.com'; + + $this->assertTrue(Url::isValid($validUrl)); + $this->assertFalse(Url::isValid($invalidUrl)); + } + + public function test_parse_query() + { + $query = 'param1=value1¶m2=value2'; + + $expected = [ + 'param1' => 'value1', + 'param2' => 'value2', + ]; + $result = Url::parseQuery($query); + + $this->assertEquals($expected, $result); + } +} diff --git a/tests/Utils/UtilityTest.php b/tests/Utils/UtilityTest.php new file mode 100644 index 000000000..1c8beda44 --- /dev/null +++ b/tests/Utils/UtilityTest.php @@ -0,0 +1,149 @@ +assertContains(TestTrait1::class, $result); + $this->assertContains(TestTrait2::class, $result); + $this->assertContains(TestTrait3::class, $result); + } + + /** @test */ + public function trait_uses_recursive() + { + $result = Utility::traitUsesRecursive(TestTraitMain::class); + + $this->assertContains(TestTraitBase::class, $result); + $this->assertContains(TestTraitNested::class, $result); + } + + /** @test */ + public function get_properties() + { + // Test getting all properties + $allProps = Utility::getProperties(TestPropertiesClass::class); + $this->assertCount(3, $allProps); + $this->assertContainsOnlyInstancesOf(ReflectionProperty::class, $allProps); + + // Test getting only public properties + $publicProps = Utility::getProperties(TestPropertiesClass::class, ReflectionProperty::IS_PUBLIC); + $this->assertCount(1, $publicProps); + $this->assertEquals('publicProp', $publicProps[0]->getName()); + } + + /** @test */ + public function filter_by_properties() + { + $array = [ + 'prop1' => 'value1', + 'prop2' => 'value2', + 'extraProp' => 'extraValue', + ]; + + $filtered = Utility::filterByProperties(TestFilterClass::class, $array); + + $this->assertArrayHasKey('extraProp', $filtered); + $this->assertArrayNotHasKey('prop1', $filtered); + $this->assertArrayNotHasKey('prop2', $filtered); + } + + /** @test */ + public function compose() + { + // Test with callable + $composedWithCallable = Utility::compose(5, fn ($x) => $x * 2); + $this->assertEquals(10, $composedWithCallable); + + $composedWithClass = Utility::compose('test', TestComposable::class); + $this->assertInstanceOf(TestComposable::class, $composedWithClass); + $this->assertEquals('test', $composedWithClass->value); + + // Test with falsy value + $composedWithDefault = Utility::compose(false, fn ($x) => $x * 2, 'default'); + $this->assertEquals('default', $composedWithDefault); + + $existingValueIsNotOverriden = Utility::compose(new Metadata(['key' => 'value']), Metadata::class); + $this->assertInstanceOf(Metadata::class, $existingValueIsNotOverriden); + $this->assertEquals(['key' => 'value'], $existingValueIsNotOverriden->data); + } + + /** @test */ + public function extract_bool() + { + // Test with direct boolean + $this->assertTrue(Utility::extractBool(true, 'key')); + $this->assertFalse(Utility::extractBool(false, 'key')); + + // Test with array + $array = ['enabled' => true]; + $this->assertTrue(Utility::extractBool($array, 'enabled')); + $this->assertFalse(Utility::extractBool($array, 'nonexistent')); + + // Test with default value + $this->assertTrue(Utility::extractBool([], 'key', true)); + } +} + +trait TestTrait1 {} +trait TestTrait2 {} +trait TestTrait3 +{ + use TestTrait1; +} + +class TestParentClass +{ + use TestTrait1; +} + +class TestChildClass extends TestParentClass +{ + use TestTrait2, TestTrait3; +} + +trait TestTraitBase {} +trait TestTraitNested +{ + use TestTraitBase; +} +trait TestTraitMain +{ + use TestTraitNested; +} + +class TestPropertiesClass +{ + public $publicProp; + + protected $protectedProp; + + private $privateProp; +} + +class TestFilterClass +{ + public $prop1; + + public $prop2; +} + +class TestComposable +{ + public $value; + + public function __construct($value) + { + $this->value = $value; + } +}