Skip to content

Commit

Permalink
Merge pull request #13 from logeecom/master
Browse files Browse the repository at this point in the history
PISYL-3 & PISYL-173 & PISYL-158 & PISYL-177:  Enable single click payment with mollie components. Fix some cases where `$order->getPayments()->last()` can return false, Fix issue with TAB not switching between mollie components
  • Loading branch information
sebastian-mollie authored Jan 29, 2024
2 parents a3ad196 + 8fa46f9 commit 9613892
Show file tree
Hide file tree
Showing 59 changed files with 870 additions and 51 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"php": "^7.4 || ^8.0",
"sylius/sylius": "~1.9.0 || ~1.10.0 || ~1.11.0 || ~1.12.0",
"symfony/messenger": "^4.4 || ^5.2 || ^6.0",
"mollie/mollie-api-php": "^2.0",
"mollie/mollie-api-php": "^2.64.0",
"sylius/refund-plugin": "^1.0",
"sylius/admin-order-creation-plugin": "^0.12 || ^0.13 || v0.14",
"ext-json": "*",
Expand Down
13 changes: 12 additions & 1 deletion doc/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,18 @@ sylius_mollie_plugin:

#### 12. Update your database

Apply migration to your database:
Apply migration to your database: (this is for the plugin fresh installation only)
```
bin/console doctrine:migrations:migrate
```

In case if you are updating from older version of plugin (versions < 5.0), you will need to run the following commands before running migrate command.
```
bin/console doctrine:migrations:version --add --range-from='SyliusMolliePlugin\Migrations\Version20200513092722' --range-to='SyliusMolliePlugin\Migrations\Version20220211040328'
bin/console doctrine:migrations:execute --up 'SyliusMolliePlugin\Migrations\Version20231225151033'
```
After running all the above-mentioned commands, run migrate command
```
bin/console doctrine:migrations:migrate
```
Expand Down
18 changes: 18 additions & 0 deletions src/Action/Api/BaseApiAwareAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,22 @@ public function setApi($mollieApiClient): void

$this->mollieApiClient = $mollieApiClient;
}

/**
* Checks if payment should be refunded. As long as there are order items to be refunded, payment will be refunded.
*
* @param \ArrayObject $details
*
* @return bool
*/
public function shouldBeRefunded(\ArrayObject $details): bool
{
if (isset($details['metadata']['refund']) && array_key_exists('items', $details['metadata']['refund'])) {
$items = $details['metadata']['refund']['items'];

return count($items) > 0 && !empty($items[0]);
}

return false;
}
}
29 changes: 28 additions & 1 deletion src/Action/Api/CreatePaymentAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@

namespace SyliusMolliePlugin\Action\Api;

use Sylius\Bundle\ResourceBundle\Doctrine\ORM\EntityRepository;
use SyliusMolliePlugin\Logger\MollieLoggerActionInterface;
use SyliusMolliePlugin\Parser\Response\GuzzleNegativeResponseParserInterface;
use SyliusMolliePlugin\Repository\CustomerRepository;
use SyliusMolliePlugin\Request\Api\CreatePayment;
use Mollie\Api\Exceptions\ApiException;
use Mollie\Api\Resources\Payment;
Expand All @@ -29,14 +31,21 @@ final class CreatePaymentAction extends BaseApiAwareAction
/** @var RequestStack */
private $requestStack;

/**
* @var CustomerRepository
*/
private $customerRepository;

public function __construct(
MollieLoggerActionInterface $loggerAction,
GuzzleNegativeResponseParserInterface $guzzleNegativeResponseParser,
RequestStack $requestStack
RequestStack $requestStack,
EntityRepository $customerRepository
) {
$this->loggerAction = $loggerAction;
$this->guzzleNegativeResponseParser = $guzzleNegativeResponseParser;
$this->requestStack = $requestStack;
$this->customerRepository = $customerRepository;
}

public function execute($request): void
Expand All @@ -63,8 +72,26 @@ public function execute($request): void
$paymentDetails['locale'] = $details['locale'];
}

if (isset($details['metadata']['saveCardInfo']) && $details['metadata']['saveCardInfo'] === "0") {
unset($paymentDetails['customerId']);
}

if (isset($details['metadata']['useSavedCards']) && $details['metadata']['useSavedCards'] === "1") {
unset($paymentDetails['cardToken']);
}

/** @var Payment $payment */
$payment = $this->mollieApiClient->payments->create($paymentDetails);

if (isset($details['metadata']['saveCardInfo'])) {
$valueToUpdate = $details['metadata']['saveCardInfo'] === '1' ? '1' : null;
$existingCustomer = $this->customerRepository->findOneBy(['profileId' => $details['customerId']]);

if ($existingCustomer) {
$existingCustomer->setIsCreditCardSaved($valueToUpdate);
$this->customerRepository->add($existingCustomer);
}
}
} catch (ApiException $e) {
$message = $this->guzzleNegativeResponseParser->parse($e);
$this->loggerAction->addNegativeLog(sprintf('Error with create payment with: %s', $e->getMessage()));
Expand Down
6 changes: 6 additions & 0 deletions src/Action/ConvertMolliePaymentAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,14 @@ public function execute($request): void
if (isset($paymentOptions['metadata'])) {
$paymentMethod = $paymentOptions['metadata']['molliePaymentMethods'] ?? null;
$cartToken = $paymentOptions['metadata']['cartToken'];
$saveCardInfo = $paymentOptions['metadata']['saveCardInfo'];
$useSavedCards = $paymentOptions['metadata']['useSavedCards'];
$selectedIssuer = PaymentMethod::IDEAL === $paymentMethod ? $paymentOptions['metadata']['selected_issuer'] : null;
} else {
$paymentMethod = $paymentOptions['molliePaymentMethods'] ?? null;
$cartToken = $paymentOptions['cartToken'];
$saveCardInfo = $paymentOptions['saveCardInfo'];
$useSavedCards = $paymentOptions['useSavedCards'];
$selectedIssuer = PaymentMethod::IDEAL === $paymentMethod ? $paymentOptions['issuers']['id'] : null;
}

Expand All @@ -125,6 +129,8 @@ public function execute($request): void
'customer_id' => $customer->getId() ?? null,
'molliePaymentMethods' => $paymentMethod ?? null,
'cartToken' => $cartToken ?? null,
'saveCardInfo' => $saveCardInfo ?? null,
'useSavedCards' => $useSavedCards ?? null,
'selected_issuer' => $selectedIssuer ?? null,
],
'full_name' => $customer->getFullName() ?? null,
Expand Down
2 changes: 1 addition & 1 deletion src/Action/RefundAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public function execute($request): void
throw new \Exception(sprintf('API call failed: %s', htmlspecialchars($e->getMessage())));
}

if ($molliePayment->hasRefunds()) {
if (!$this->shouldBeRefunded($details)) {
return;
}

Expand Down
6 changes: 1 addition & 5 deletions src/Action/RefundOrderAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public function execute($request): void

$details = ArrayObject::ensureArrayObject($request->getModel());

if (!array_key_exists('refund', $details['metadata'])) {
if (!array_key_exists('refund', $details['metadata']) || !$this->shouldBeRefunded($details)) {
return;
}

Expand Down Expand Up @@ -76,10 +76,6 @@ public function execute($request): void

Assert::notNull($molliePayment);

if ($molliePayment->hasRefunds()) {
return;
}

/** @var PaymentInterface $payment */
$payment = $request->getFirstModel();

Expand Down
10 changes: 9 additions & 1 deletion src/Creator/ApiKeysTestCreator.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ private function testApiKey(ApiKeyTest $apiKeyTest, string $apiKey): ApiKeyTest
$client = $this->mollieApiClient->setApiKey($apiKey);

/** @var MethodCollection $methods */
$methods = $client->methods->allActive(MollieMethodsResolverInterface::PARAMETERS);
$methods = $client->methods->allAvailable(MollieMethodsResolverInterface::PARAMETERS_AVAILABLE);
$filteredMethods = array_filter($methods->getArrayCopy(), array($this, 'filterActiveMethods'));
$methods->exchangeArray($filteredMethods);

$apiKeyTest->setMethods($methods);

return $apiKeyTest;
Expand All @@ -85,4 +88,9 @@ private function testApiKey(ApiKeyTest $apiKeyTest, string $apiKey): ApiKeyTest
return $apiKeyTest;
}
}

private function filterActiveMethods($method): bool
{
return $method->status === 'activated';
}
}
4 changes: 2 additions & 2 deletions src/EmailSender/PaymentLinkEmailSender.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ public function __construct(

public function sendConfirmationEmail(OrderInterface $order, TemplateMollieEmailTranslationInterface $template): void
{
/** @var PaymentInterface $payment */
/** @var PaymentInterface|null $payment */
$payment = $order->getPayments()->last();

if (0 === count($payment->getDetails())) {
if (false === $payment || 0 === count($payment->getDetails())) {
return;
}

Expand Down
13 changes: 13 additions & 0 deletions src/Entity/MollieCustomer.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ class MollieCustomer implements ResourceInterface, MollieCustomerInterface
/** @var string */
protected $email;

/** @var string|null */
protected $isCreditCardSaved;

public function getId(): int
{
return $this->id;
Expand All @@ -42,4 +45,14 @@ public function setEmail(string $email): void
{
$this->email = $email;
}

public function isCreditCardSaved(): ?string
{
return $this->isCreditCardSaved;
}

public function setIsCreditCardSaved(?string $isCreditCardSaved): void
{
$this->isCreditCardSaved = $isCreditCardSaved;
}
}
4 changes: 4 additions & 0 deletions src/Entity/MollieCustomerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,8 @@ public function setProfileId(string $profileId): void;
public function getEmail(): string;

public function setEmail(string $email): void;

public function isCreditCardSaved(): ?string;

public function setIsCreditCardSaved(?string $isCreditCardSaved): void;
}
13 changes: 13 additions & 0 deletions src/Entity/MollieGatewayConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ class MollieGatewayConfig extends AbstractMethod implements ResourceInterface, M
/** @var PaymentSurchargeFeeInterface|null */
protected $paymentSurchargeFee;

/** @var MollieMinMaxInterface|null */
protected $amountLimits;

/** @var MollieMethodImageInterface|null */
protected $customizeMethodImage;

Expand Down Expand Up @@ -205,6 +208,16 @@ public function setPosition(?int $position): void
$this->position = $position;
}

public function getAmountLimits(): ?MollieMinMaxInterface
{
return $this->amountLimits;
}

public function setAmountLimits(?MollieMinMaxInterface $amountLimits): void
{
$this->amountLimits = $amountLimits;
}

protected function createTranslation(): TranslationInterface
{
return new MollieGatewayConfigTranslation();
Expand Down
4 changes: 4 additions & 0 deletions src/Entity/MollieGatewayConfigInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,9 @@ public function getPosition(): ?int;

public function setPosition(?int $position): void;

public function getAmountLimits(): ?MollieMinMaxInterface;

public function setAmountLimits(?MollieMinMaxInterface $amountLimits): void;

public function hasTranslationLocale(string $localeCode): bool;
}
58 changes: 58 additions & 0 deletions src/Entity/MollieMinMax.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

declare(strict_types=1);

namespace SyliusMolliePlugin\Entity;

use Sylius\Component\Resource\Model\ResourceInterface;

class MollieMinMax implements ResourceInterface, MollieMinMaxInterface
{
/** @var int|null */
protected $id;

/** @var float|null */
protected $minimumAmount;

/** @var float|null */
protected $maximumAmount;

/** @var MollieGatewayConfigInterface|null */
protected $mollieGatewayConfig;

public function getId(): ?int
{
return $this->id;
}

public function getMinimumAmount(): ?float
{
return $this->minimumAmount;
}

public function setMinimumAmount(?float $minimumAmount): void
{
$this->minimumAmount = $minimumAmount;
}

public function getMaximumAmount(): ?float
{
return $this->maximumAmount;
}

public function setMaximumAmount(?float $maximumAmount): void
{
$this->maximumAmount = $maximumAmount;
}

public function getMollieGatewayConfig(): ?MollieGatewayConfigInterface
{
return $this->mollieGatewayConfig;
}

public function setMollieGatewayConfig(?MollieGatewayConfigInterface $mollieGatewayConfig): void
{
$this->mollieGatewayConfig = $mollieGatewayConfig;
}

}
22 changes: 22 additions & 0 deletions src/Entity/MollieMinMaxInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace SyliusMolliePlugin\Entity;

interface MollieMinMaxInterface
{
public function getId(): ?int;

public function getMinimumAmount(): ?float;

public function setMinimumAmount(?float $minimumAmount): void;

public function getMaximumAmount(): ?float;

public function setMaximumAmount(?float $maximumAmount): void;

public function getMollieGatewayConfig(): ?MollieGatewayConfigInterface;

public function setMollieGatewayConfig(?MollieGatewayConfigInterface $mollieGatewayConfig): void;
}
2 changes: 1 addition & 1 deletion src/Factory/MollieGatewayConfigFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public function create(
$mollieGatewayConfig->setMethodId($method->getMethodId());
$mollieGatewayConfig->setName($method->getName());
$mollieGatewayConfig->setMinimumAmount($method->getMinimumAmount());
$mollieGatewayConfig->setMaximumAmount($method->getMinimumAmount());
$mollieGatewayConfig->setMaximumAmount($method->getMaximumAmount());
$mollieGatewayConfig->setImage($method->getImage());
$mollieGatewayConfig->setGateway($gateway);
$mollieGatewayConfig->setIssuers($method->getIssuers());
Expand Down
2 changes: 2 additions & 0 deletions src/Form/Extension/GatewayConfigTypeExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

use SyliusMolliePlugin\Form\Type\MollieGatewayConfigType;
use Sylius\Bundle\PayumBundle\Form\Type\GatewayConfigType;
use SyliusMolliePlugin\Validator\Constraints\MollieGatewayConfigValidatorType;
use Symfony\Component\Form\AbstractTypeExtension;
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
use Symfony\Component\Form\FormBuilderInterface;
Expand All @@ -24,6 +25,7 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
'validation_groups' => ['sylius'],
'constraints' => [
new Valid(),
new MollieGatewayConfigValidatorType(['groups' => 'sylius'])
],
]
);
Expand Down
5 changes: 5 additions & 0 deletions src/Form/Type/MollieGatewayConfigType.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use SyliusMolliePlugin\Options\Country\Options as CountryOptions;
use SyliusMolliePlugin\Payments\Methods\AbstractMethod;
use SyliusMolliePlugin\Payments\PaymentTerms\Options;
use SyliusMolliePlugin\Validator\Constraints\MollieMinMaxValidatorType;
use SyliusMolliePlugin\Validator\Constraints\PaymentSurchargeType;
use Sylius\Bundle\ProductBundle\Form\Type\ProductType as ProductFormType;
use Sylius\Bundle\ResourceBundle\Form\Type\AbstractResourceType;
Expand Down Expand Up @@ -85,6 +86,10 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
'label' => false,
'constraints' => [new PaymentSurchargeType(['groups' => 'sylius'])],
])
->add('amountLimits', MollieMinMaxType::class, [
'label' => false,
'required' => false,
])
->add('customizeMethodImage', CustomizeMethodImageType::class, [
'label' => false,
])
Expand Down
Loading

0 comments on commit 9613892

Please sign in to comment.