Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Naoray committed Dec 6, 2024
1 parent 02ca3a2 commit 8aefdb1
Show file tree
Hide file tree
Showing 21 changed files with 1,379 additions and 270 deletions.
237 changes: 36 additions & 201 deletions README.md

Large diffs are not rendered by default.

718 changes: 718 additions & 0 deletions docs/endpoint-collections.md

Large diffs are not rendered by default.

74 changes: 74 additions & 0 deletions docs/http-adapters.md
Original file line number Diff line number Diff line change
@@ -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();
```
57 changes: 57 additions & 0 deletions docs/idempotency.md
Original file line number Diff line number Diff line change
@@ -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.
93 changes: 93 additions & 0 deletions docs/payments.md
Original file line number Diff line number Diff line change
@@ -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).
47 changes: 47 additions & 0 deletions docs/requests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# 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\Payload\Money;
use Mollie\Api\Http\Payload\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();
```
43 changes: 43 additions & 0 deletions docs/responses.md
Original file line number Diff line number Diff line change
@@ -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()`.
55 changes: 55 additions & 0 deletions docs/testing.md
Original file line number Diff line number Diff line change
@@ -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\Payload\Money;
use Mollie\Api\Http\Payload\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);
```
Loading

0 comments on commit 8aefdb1

Please sign in to comment.