diff --git a/Entity/PaymentMethodSettings.php b/Entity/PaymentMethodSettings.php index d46ef49..b7f6c30 100644 --- a/Entity/PaymentMethodSettings.php +++ b/Entity/PaymentMethodSettings.php @@ -127,7 +127,45 @@ class PaymentMethodSettings * @ORM\Column(name="mollie_method_description", type="string", length=255, nullable=false) */ protected $mollieMethodDescription; + /** + * @var Collection|LocalizedFallbackValue[] + * + * @ORM\ManyToMany( + * targetEntity="Oro\Bundle\LocaleBundle\Entity\LocalizedFallbackValue", + * cascade={"ALL"}, + * orphanRemoval=true + * ) + * @ORM\JoinTable( + * name="mollie_single_click_appr_text", + * joinColumns={ + * @ORM\JoinColumn(name="payment_setting_id", referencedColumnName="id", onDelete="CASCADE") + * }, + * inverseJoinColumns={ + * @ORM\JoinColumn(name="localized_value_id", referencedColumnName="id", onDelete="CASCADE", unique=true) + * } + * ) + */ + protected $singleClickPaymentApprovalText; + /** + * @var Collection|LocalizedFallbackValue[] + * + * @ORM\ManyToMany( + * targetEntity="Oro\Bundle\LocaleBundle\Entity\LocalizedFallbackValue", + * cascade={"ALL"}, + * orphanRemoval=true + * ) + * @ORM\JoinTable( + * name="mollie_single_click_desc", + * joinColumns={ + * @ORM\JoinColumn(name="payment_setting_id", referencedColumnName="id", onDelete="CASCADE") + * }, + * inverseJoinColumns={ + * @ORM\JoinColumn(name="localized_value_id", referencedColumnName="id", onDelete="CASCADE", unique=true) + * } + * ) + */ + protected $singleClickPaymentDescription; /** * @var \Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\PaymentMethod\Model\PaymentMethodConfig */ @@ -156,18 +194,35 @@ class PaymentMethodSettings /** * @var string */ - private $method; + private $surchargeType; + + /** + * @var string + */ + private $surchargeFixedAmount; /** * @var string */ - private $surcharge; + private $surchargePercentage; + /** + * @var string + */ + private $surchargeLimit; + /** + * @var string + */ + private $method; /** * @var boolean */ private $mollieComponents; + /** + * @var boolean + */ + private $singleClickPayment; /** * @var string */ @@ -202,6 +257,8 @@ public function __construct() $this->descriptions = new ArrayCollection(); $this->paymentDescriptions = new ArrayCollection(); $this->transactionDescriptions = new ArrayCollection(); + $this->singleClickPaymentApprovalText = new ArrayCollection(); + $this->singleClickPaymentDescription = new ArrayCollection(); } /** @@ -447,6 +504,70 @@ public function setEnabled($enabled) $this->enabled = $enabled; } + /** + * @return string + */ + public function getSurchargeType() + { + return $this->surchargeType; + } + + /** + * @param string $surchargeType + */ + public function setSurchargeType($surchargeType) + { + $this->surchargeType = $surchargeType; + } + + /** + * @return string + */ + public function getSurchargeFixedAmount() + { + return $this->surchargeFixedAmount; + } + + /** + * @param string $surchargeFixedAmount + */ + public function setSurchargeFixedAmount($surchargeFixedAmount) + { + $this->surchargeFixedAmount = $surchargeFixedAmount; + } + + /** + * @return string + */ + public function getSurchargePercentage() + { + return $this->surchargePercentage; + } + + /** + * @param string $surchargePercentage + */ + public function setSurchargePercentage($surchargePercentage) + { + $this->surchargePercentage = $surchargePercentage; + } + + /** + * @return string + */ + public function getSurchargeLimit() + { + return $this->surchargeLimit; + } + + /** + * @param string $surchargeLimit + */ + public function setSurchargeLimit($surchargeLimit) + { + $this->surchargeLimit = $surchargeLimit; + } + /** * @return string */ @@ -496,35 +617,123 @@ public function setOriginalImagePath($originalImagePath) } /** - * @return string + * @return mixed */ - public function getSurcharge() + public function getMollieComponents() { - return $this->surcharge; + return $this->mollieComponents; } /** - * @param string $surcharge + * @param bool $mollieComponents */ - public function setSurcharge($surcharge) + public function setMollieComponents($mollieComponents) { - $this->surcharge = $surcharge; + $this->mollieComponents = $mollieComponents; } /** * @return mixed */ - public function getMollieComponents() + public function getSingleClickPayment() { - return $this->mollieComponents; + return $this->singleClickPayment; } /** - * @param bool $mollieComponents + * @param bool $singleClickPayment */ - public function setMollieComponents($mollieComponents) + public function setSingleClickPayment($singleClickPayment) { - $this->mollieComponents = $mollieComponents; + $this->singleClickPayment = $singleClickPayment; + } + + /** + * @return Collection|LocalizedFallbackValue[] + */ + public function getSingleClickPaymentApprovalText() + { + return $this->singleClickPaymentApprovalText; + } + + /** + * @param Collection|LocalizedFallbackValue[] $singleClickPaymentApprovalText + */ + public function setSingleClickPaymentApprovalText($singleClickPaymentApprovalText) + { + $this->singleClickPaymentApprovalText = $singleClickPaymentApprovalText; + } + + /** + * @param LocalizedFallbackValue $singleClickPaymentApprovalText + * + * @return $this + */ + public function addSingleClickPaymentApprovalText(LocalizedFallbackValue $singleClickPaymentApprovalText) + { + if (!$this->singleClickPaymentApprovalText->contains($singleClickPaymentApprovalText)) { + $this->singleClickPaymentApprovalText->add($singleClickPaymentApprovalText); + } + + return $this; + } + + /** + * @param LocalizedFallbackValue $singleClickPaymentApprovalText + * + * @return $this + */ + public function removeSingleClickPaymentApprovalText(LocalizedFallbackValue $singleClickPaymentApprovalText) + { + if ($this->singleClickPaymentApprovalText->contains($singleClickPaymentApprovalText)) { + $this->singleClickPaymentApprovalText->removeElement($singleClickPaymentApprovalText); + } + + return $this; + } + + /** + * @return Collection|LocalizedFallbackValue[] + */ + public function getSingleClickPaymentDescription() + { + return $this->singleClickPaymentDescription; + } + + /** + * @param Collection|LocalizedFallbackValue[] $singleClickPaymentDescription + */ + public function setSingleClickPaymentDescription($singleClickPaymentDescription) + { + $this->singleClickPaymentDescription = $singleClickPaymentDescription; + } + + /** + * @param LocalizedFallbackValue $singleClickPaymentDescription + * + * @return $this + */ + public function addSingleClickPaymentDescription(LocalizedFallbackValue $singleClickPaymentDescription) + { + if (!$this->singleClickPaymentDescription->contains($singleClickPaymentDescription)) { + $this->singleClickPaymentDescription->add($singleClickPaymentDescription); + } + + return $this; + } + + /** + * @param LocalizedFallbackValue $singleClickPaymentDescription + * + * @return $this + */ + public function removeSingleClickPaymentDescription(LocalizedFallbackValue $singleClickPaymentDescription) + { + if ($this->singleClickPaymentDescription->contains($singleClickPaymentDescription)) { + $this->singleClickPaymentDescription->removeElement($singleClickPaymentDescription); + } + + return $this; } /** diff --git a/EventListener/ChannelSettingsListener.php b/EventListener/ChannelSettingsListener.php index 48f9518..e15920b 100644 --- a/EventListener/ChannelSettingsListener.php +++ b/EventListener/ChannelSettingsListener.php @@ -227,9 +227,13 @@ protected function updatePaymentMethodConfigurations(ChannelSettings $channelSet ); } - $paymentMethodConfig->setSurcharge($paymentMethodSetting->getSurcharge()); + $paymentMethodConfig->setSurchargeType($paymentMethodSetting->getSurchargeType()); + $paymentMethodConfig->setSurchargeFixedAmount($paymentMethodSetting->getSurchargeFixedAmount()); + $paymentMethodConfig->setSurchargePercentage($paymentMethodSetting->getSurchargePercentage()); + $paymentMethodConfig->setSurchargeLimit($paymentMethodSetting->getSurchargeLimit()); $paymentMethodConfig->setApiMethod($paymentMethodSetting->getMethod()); $paymentMethodConfig->setUseMollieComponents($paymentMethodSetting->getMollieComponents()); + $paymentMethodConfig->setUseSingleClickPayment($paymentMethodSetting->getSingleClickPayment()); $paymentMethodConfig->setIssuerListStyle($paymentMethodSetting->getIssuerListStyle()); $paymentMethodConfig->setDaysToOrderExpire($paymentMethodSetting->getOrderExpiryDays()); $paymentMethodConfig->setDaysToPaymentExpire($paymentMethodSetting->getPaymentExpiryDays()); diff --git a/EventListener/CheckoutEntityListener.php b/EventListener/CheckoutEntityListener.php index bc04ed9..fc72e49 100644 --- a/EventListener/CheckoutEntityListener.php +++ b/EventListener/CheckoutEntityListener.php @@ -3,6 +3,8 @@ namespace Mollie\Bundle\PaymentBundle\EventListener; use Mollie\Bundle\PaymentBundle\Entity\MollieSurchargeAwareInterface; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Surcharge\SurchargeService; +use Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\ServiceRegister; use Mollie\Bundle\PaymentBundle\PaymentMethod\Config\Provider\MolliePaymentConfigProviderInterface; use Oro\Bundle\CheckoutBundle\Entity\Checkout; @@ -49,10 +51,45 @@ protected function setSurcharge(Checkout $checkout) } $paymentMethodConfig = $this->paymentConfigProvider->getPaymentConfig($checkout->getPaymentMethod()); - if ($paymentMethodConfig && $paymentMethodConfig->getSurchargeAmount() > 0) { - $checkout->setMollieSurchargeAmount($paymentMethodConfig->getSurchargeAmount()); + + if ($paymentMethodConfig) { + $surcharge = $this->getSurchargeService()->calculateSurchargeAmount( + $paymentMethodConfig->getSurchargeType(), + $paymentMethodConfig->getSurchargeFixedAmount(), + $paymentMethodConfig->getSurchargePercentage(), + $paymentMethodConfig->getSurchargeLimit(), + $this->calculateSubtotal($checkout) + ); + + $checkout->setMollieSurchargeAmount($surcharge); } else { $checkout->setMollieSurchargeAmount(null); } } + + /** + * @return SurchargeService + */ + protected function getSurchargeService() + { + /** @var SurchargeService $surchargeService */ + $surchargeService = ServiceRegister::getService(SurchargeService::CLASS_NAME); + + return $surchargeService; + } + + /** + * @param Checkout $checkout + * @return float|int + */ + protected function calculateSubtotal(Checkout $checkout) + { + $subtotal = 0; + $checkoutSubtotals = $checkout->getSubtotals(); + foreach ($checkoutSubtotals as $checkoutSubtotal) { + $subtotal += $checkoutSubtotal->getSubtotal()->getAmount(); + } + + return $subtotal; + } } diff --git a/Form/EventListener/ChannelSettingsTypeSubscriber.php b/Form/EventListener/ChannelSettingsTypeSubscriber.php index 4f95e40..2be3fb2 100644 --- a/Form/EventListener/ChannelSettingsTypeSubscriber.php +++ b/Form/EventListener/ChannelSettingsTypeSubscriber.php @@ -413,11 +413,27 @@ protected function setPaymentMethodConfigurations(ChannelSettings $channelSettin ); } + if (!empty($paymentMethodSetting->getSingleClickPaymentApprovalText()) && $paymentMethodSetting->getSingleClickPaymentApprovalText()->isEmpty()) { + $paymentMethodSetting->addSingleClickPaymentApprovalText( + (new LocalizedFallbackValue())->setString($this->translator->trans('mollie.payment.config.payment_methods.single_click_payment_approval_text.value')) + ); + } + + if (!empty($paymentMethodSetting->getSingleClickPaymentDescription()) && $paymentMethodSetting->getSingleClickPaymentDescription()->isEmpty()) { + $paymentMethodSetting->addSingleClickPaymentDescription( + (new LocalizedFallbackValue())->setString($this->translator->trans('mollie.payment.config.payment_methods.single_click_payment_description.value')) + ); + } + $paymentMethodSetting->setPaymentMethodConfig($paymentMethodConfig); $paymentMethodSetting->setEnabled($paymentMethodConfig->isEnabled()); - $paymentMethodSetting->setSurcharge($paymentMethodConfig->getSurcharge()); + $paymentMethodSetting->setSurchargeType($paymentMethodConfig->getSurchargeType()); + $paymentMethodSetting->setSurchargeFixedAmount($paymentMethodConfig->getSurchargeFixedAmount()); + $paymentMethodSetting->setSurchargePercentage($paymentMethodConfig->getSurchargePercentage()); + $paymentMethodSetting->setSurchargeLimit($paymentMethodConfig->getSurchargeLimit()); $paymentMethodSetting->setMethod($paymentMethodConfig->getApiMethod()); $paymentMethodSetting->setMollieComponents($paymentMethodConfig->useMollieComponents()); + $paymentMethodSetting->setSingleClickPayment($paymentMethodConfig->useSingleClickPayment()); $paymentMethodSetting->setIssuerListStyle($paymentMethodConfig->getIssuerListStyle()); $paymentMethodSetting->setVoucherCategory($paymentMethodConfig->getVoucherCategory()); $paymentMethodSetting->setProductAttribute($paymentMethodConfig->getProductAttribute()); diff --git a/Form/Type/PaymentMethodSettingsType.php b/Form/Type/PaymentMethodSettingsType.php index 81e077d..71df03a 100644 --- a/Form/Type/PaymentMethodSettingsType.php +++ b/Form/Type/PaymentMethodSettingsType.php @@ -5,6 +5,7 @@ use Mollie\Bundle\PaymentBundle\Entity\PaymentMethodSettings; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\PaymentMethod\Model\PaymentMethodConfig; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\PaymentMethod\PaymentMethods; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Surcharge\SurchargeType; use Mollie\Bundle\PaymentBundle\Manager\ProductAttributesProvider; use Oro\Bundle\ApiBundle\Form\Type\NumberType; use Oro\Bundle\LocaleBundle\Form\Type\LocalizedFallbackValueCollectionType; @@ -132,26 +133,11 @@ public function onPreSetData(FormEvent $event) return; } - $surchargeTooltip = 'mollie.payment.config.payment_methods.surcharge.tooltip'; - if ($paymentMethodConfig->isSurchargeRestricted()) { - $surchargeTooltip = 'mollie.payment.config.payment_methods.surcharge.klarna_tooltip'; - } - $orderExpiryDaysTooltip = $paymentMethodConfig->isApiMethodRestricted() ? 'mollie.payment.config.payment_methods.orderExpiryDays.klarna_tooltip' : 'mollie.payment.config.payment_methods.orderExpiryDays.tooltip'; $event->getForm()->add( - 'surcharge', - NumberType::class, - [ - 'label' => 'mollie.payment.config.payment_methods.surcharge.label', - 'tooltip' => $surchargeTooltip, - 'required' => false, - 'attr' => ['autocomplete' => 'off'], - 'constraints' => [new Range(['min' => 0])], - ] - )->add( 'orderExpiryDays', IntegerType::class, [ @@ -175,6 +161,79 @@ public function onPreSetData(FormEvent $event) ); } + if (!$paymentMethodConfig->isSurchargeRestricted()) { + $surchargeTypeChoices = [ + 'mollie.payment.config.payment_methods.payment_surcharge.option.no_fee.label' => SurchargeType::NO_FEE, + 'mollie.payment.config.payment_methods.payment_surcharge.option.fixed_fee.label' => SurchargeType::FIXED_FEE, + 'mollie.payment.config.payment_methods.payment_surcharge.option.percentage.label' => SurchargeType::PERCENTAGE, + 'mollie.payment.config.payment_methods.payment_surcharge.option.fixed_fee_and_percentage.label' => SurchargeType::FIXED_FEE_AND_PERCENTAGE + ]; + $event->getForm()->add( + 'surchargeType', + ChoiceType::class, + [ + 'choices' => $surchargeTypeChoices, + 'label' => 'mollie.payment.config.payment_methods.payment_surcharge.label', + 'tooltip' => 'mollie.payment.config.payment_methods.payment_surcharge.tooltip', + 'required' => true, + 'placeholder' => false, + 'attr' => [ + 'class' => 'mollie-surcharge-type-select', + 'data-method-wrapper' => $paymentMethodConfig->getMollieId(), + ], + ] + ); + + $surchargeFixedAmountTooltip = 'mollie.payment.config.payment_methods.surcharge_fixed_amount.tooltip'; + if ($paymentMethodConfig->isSurchargeRestricted()) { + $surchargeFixedAmountTooltip = 'mollie.payment.config.payment_methods.surcharge_fixed_amount.klarna_tooltip'; + } + + $event->getForm()->add( + 'surchargeFixedAmount', + NumberType::class, + [ + 'label' => 'mollie.payment.config.payment_methods.surcharge_fixed_amount.label', + 'tooltip' => $surchargeFixedAmountTooltip, + 'required' => false, + 'attr' => ['autocomplete' => 'off'], + 'constraints' => [new Range(['min' => 0])], + ] + ); + + $surchargePercentageTooltip = 'mollie.payment.config.payment_methods.surcharge_percentage.tooltip'; + if ($paymentMethodConfig->isSurchargeRestricted()) { + $surchargePercentageTooltip = 'mollie.payment.config.payment_methods.surcharge_percentage.klarna_tooltip'; + } + + $surchargeLimitTooltip = 'mollie.payment.config.payment_methods.surcharge_limit.tooltip'; + if ($paymentMethodConfig->isSurchargeRestricted()) { + $surchargeLimitTooltip = 'mollie.payment.config.payment_methods.surcharge_limit.klarna_tooltip'; + } + + $event->getForm()->add( + 'surchargePercentage', + NumberType::class, + [ + 'label' => 'mollie.payment.config.payment_methods.surcharge_percentage.label', + 'tooltip' => $surchargePercentageTooltip, + 'required' => false, + 'attr' => ['autocomplete' => 'off'], + 'constraints' => [new Range(['min' => 0, 'max' => 100])], + ] + )->add( + 'surchargeLimit', + NumberType::class, + [ + 'label' => 'mollie.payment.config.payment_methods.surcharge_limit.label', + 'tooltip' => $surchargeLimitTooltip, + 'required' => false, + 'attr' => ['autocomplete' => 'off'], + 'constraints' => [new Range(['min' => 0])], + ] + ); + } + if (!$paymentMethodConfig->isApiMethodRestricted()) { $paymentMethodApiChoices = [ 'mollie.payment.config.payment_methods.method.option.payment_api.label' => PaymentMethodConfig::API_METHOD_PAYMENT, @@ -217,6 +276,37 @@ public function onPreSetData(FormEvent $event) 'tooltip' => 'mollie.payment.config.payment_methods.mollie_components.tooltip', 'required' => true, ] + )->add( + 'singleClickPayment', + CheckboxType::class, + [ + 'value' => 1, + 'label' => 'mollie.payment.config.payment_methods.single_click_payment.label', + 'tooltip' => 'mollie.payment.config.payment_methods.single_click_payment.tooltip', + 'required' => true, + ] + ); + } + + if ($paymentMethodConfig->isSingleClickPaymentSupported()) { + $event->getForm()->add( + 'singleClickPaymentApprovalText', + LocalizedFallbackValueCollectionType::class, + [ + 'label' => 'mollie.payment.config.payment_methods.single_click_payment_approval_text.label', + 'tooltip' => 'mollie.payment.config.payment_methods.single_click_payment_approval_text.tooltip', + 'required' => true, + 'entry_options' => ['constraints' => [new NotBlank()]], + ] + )->add( + 'singleClickPaymentDescription', + LocalizedFallbackValueCollectionType::class, + [ + 'label' => 'mollie.payment.config.payment_methods.single_click_payment_description.label', + 'tooltip' => 'mollie.payment.config.payment_methods.single_click_payment_description.tooltip', + 'required' => true, + 'entry_options' => ['constraints' => [new NotBlank()]], + ] ); } diff --git a/IntegrationCore/BusinessLogic/BootstrapComponent.php b/IntegrationCore/BusinessLogic/BootstrapComponent.php index ae53a63..636d280 100644 --- a/IntegrationCore/BusinessLogic/BootstrapComponent.php +++ b/IntegrationCore/BusinessLogic/BootstrapComponent.php @@ -3,6 +3,8 @@ namespace Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\CheckoutLink\CheckoutLinkService; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Customer\CustomerService; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\CustomerReference\CustomerReferenceService; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\OrgToken\ProxyDataProvider; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\Proxy; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Integration\Event\IntegrationOrderBillingAddressChangedEvent; @@ -36,6 +38,8 @@ use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Refunds\WebHookHandler\OrderLineRefundWebHookHandler; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Refunds\WebHookHandler\OrderRefundWebHookHandler; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Shipments\ShipmentService; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Surcharge\SurchargeCalculationService; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Surcharge\SurchargeService; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\VersionCheck\Http\VersionCheckProxy; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\WebHook\OrderChangedWebHookEvent; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\WebHook\PaymentChangedWebHookEvent; @@ -110,6 +114,20 @@ function () { } ); + ServiceRegister::registerService( + CustomerReferenceService::CLASS_NAME, + function () { + return CustomerReferenceService::getInstance(); + } + ); + + ServiceRegister::registerService( + CustomerService::CLASS_NAME, + function () { + return CustomerService::getInstance(); + } + ); + ServiceRegister::registerService( OrderReferenceService::CLASS_NAME, function () { @@ -131,6 +149,13 @@ function () { } ); + ServiceRegister::registerService( + SurchargeCalculationService::CLASS_NAME, + function () { + return SurchargeService::getInstance(); + } + ); + ServiceRegister::registerService( CheckoutLinkService::CLASS_NAME, function () { diff --git a/IntegrationCore/BusinessLogic/Customer/CustomerService.php b/IntegrationCore/BusinessLogic/Customer/CustomerService.php new file mode 100644 index 0000000..d6132ab --- /dev/null +++ b/IntegrationCore/BusinessLogic/Customer/CustomerService.php @@ -0,0 +1,110 @@ +getCustomerReferenceService()->getByShopReference($shopReference); + + if ($customerReference) { + return $customerReference->getMollieReference(); + } + + try { + $mollieCustomer = $this->getProxy()->createCustomer($customer); + } catch (UnprocessableEntityRequestException $exception) { + return null; + } + + $this->getCustomerReferenceService()->saveCustomerReference($mollieCustomer, $shopReference); + + return ($mollieCustomer->getId() !== null && $mollieCustomer->getId() !== '') + ? $mollieCustomer->getId() : null; + } + + /** + * Returns customer id from local db by shop reference + * + * @param $shopReference + * + * @return string|null + */ + public function getSavedCustomerId($shopReference) + { + $customer = $this->getCustomerReferenceService()->getByShopReference($shopReference); + + return $customer ? $customer->getMollieReference() : null; + } + + /** + * Removes customer from local database and from mollie api + * + * @param string $shopReference + * + * @throws UnprocessableEntityRequestException + * @throws HttpAuthenticationException + * @throws HttpCommunicationException + * @throws HttpRequestException + */ + public function removeCustomer($shopReference) + { + $customerReference = $this->getCustomerReferenceService()->getByShopReference($shopReference); + + if ($customerReference) { + $this->getProxy()->deleteCustomer($customerReference->getMollieReference()); + } + + $this->getCustomerReferenceService()->deleteByShopReference($shopReference); + } + + /** + * @return CustomerReferenceService + */ + protected function getCustomerReferenceService() + { + /** @var CustomerReferenceService $customerReferenceService */ + $customerReferenceService = ServiceRegister::getService(CustomerReferenceService::CLASS_NAME); + + return $customerReferenceService; + } +} diff --git a/IntegrationCore/BusinessLogic/CustomerReference/CustomerReferenceService.php b/IntegrationCore/BusinessLogic/CustomerReference/CustomerReferenceService.php new file mode 100644 index 0000000..b3de643 --- /dev/null +++ b/IntegrationCore/BusinessLogic/CustomerReference/CustomerReferenceService.php @@ -0,0 +1,109 @@ +setShopReference($shopReference); + $customerReference->setMollieReference($customer->getId()); + $customerReference->setPayload($customer->toArray()); + + return $this->getRepository(CustomerReference::CLASS_NAME)->save($customerReference); + } + + /** + * Return customer by its shop identifier + * + * @param string $shopReference + * + * @return CustomerReference|null + */ + public function getByShopReference($shopReference) + { + /** @var CustomerReference|null $customerReference */ + $customerReference = $this->getRepository(CustomerReference::CLASS_NAME)->selectOne( + $this->setFilterCondition( + new QueryFilter(), + 'shopReference', + Operators::EQUALS, + (string)$shopReference + ) + ); + + return $customerReference; + } + + /** + * Return customer by its Mollie identifier + * + * @param string $mollieReference + * + * @return CustomerReference|null + */ + public function getByMollieReference($mollieReference) + { + /** @var CustomerReference|null $customerReference */ + $customerReference = $this->getRepository(CustomerReference::CLASS_NAME)->selectOne( + $this->setFilterCondition( + new QueryFilter(), + 'mollieReference', + Operators::EQUALS, + (string)$mollieReference + ) + ); + + return $customerReference; + } + + /** + * Removes customer from customer reference table by its shop identifier + * + * @param string $shopReference + */ + public function deleteByShopReference($shopReference) + { + $this->getRepository(CustomerReference::CLASS_NAME)->deleteBy( + $this->setFilterCondition( + new QueryFilter(), + 'shopReference', + Operators::EQUALS, + (string)$shopReference + ) + ); + } +} diff --git a/IntegrationCore/BusinessLogic/CustomerReference/Model/CustomerReference.php b/IntegrationCore/BusinessLogic/CustomerReference/Model/CustomerReference.php new file mode 100644 index 0000000..139a499 --- /dev/null +++ b/IntegrationCore/BusinessLogic/CustomerReference/Model/CustomerReference.php @@ -0,0 +1,105 @@ +addStringIndex('shopReference'); + $map->addStringIndex('mollieReference'); + + return new EntityConfiguration($map, 'CustomerReference'); + } + + /** + * @return string + */ + public function getShopReference() + { + return $this->shopReference; + } + + /** + * @param string $shopReference + */ + public function setShopReference($shopReference) + { + $this->shopReference = $shopReference; + } + + /** + * @return string + */ + public function getMollieReference() + { + return $this->mollieReference; + } + + /** + * @param string $mollieReference + */ + public function setMollieReference($mollieReference) + { + $this->mollieReference = $mollieReference; + } + + /** + * @return array + */ + public function getPayload() + { + return $this->payload; + } + + /** + * @param array $payload + */ + public function setPayload($payload) + { + $this->payload = $payload; + } +} diff --git a/IntegrationCore/BusinessLogic/Http/DTO/Customer.php b/IntegrationCore/BusinessLogic/Http/DTO/Customer.php new file mode 100644 index 0000000..359f2fb --- /dev/null +++ b/IntegrationCore/BusinessLogic/Http/DTO/Customer.php @@ -0,0 +1,234 @@ +resource = static::getValue($raw, 'resource'); + $customer->id = static::getValue($raw, 'id'); + $customer->name = static::getValue($raw, 'name'); + $customer->mode = static::getValue($raw, 'mode'); + $customer->email = static::getValue($raw, 'email'); + $customer->locale = static::getValue($raw, 'locale'); + $customer->metadata = static::getValue($raw, 'metadata', array()); + $customer->createdAt = static::getValue($raw, 'createdAt'); + + foreach (static::getValue($raw, '_links', array()) as $linkKey => $linkData) { + $customer->links[$linkKey] = Link::fromArray($linkData); + } + + return $customer; + } + + /** + * @return string + */ + public function getResource() + { + return $this->resource; + } + + /** + * @param string $resource + */ + public function setResource($resource) + { + $this->resource = $resource; + } + + /** + * @return string + */ + public function getId() + { + return $this->id; + } + + /** + * @param string $id + */ + public function setId($id) + { + $this->id = $id; + } + + /** + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * @param string $name + */ + public function setName($name) + { + $this->name = $name; + } + + /** + * @return string + */ + public function getMode() + { + return $this->mode; + } + + /** + * @param string $mode + */ + public function setMode($mode) + { + $this->mode = $mode; + } + + /** + * @return string + */ + public function getEmail() + { + return $this->email; + } + + /** + * @param string $email + */ + public function setEmail($email) + { + $this->email = $email; + } + + /** + * @return string + */ + public function getLocale() + { + return $this->locale; + } + + /** + * @param string $locale + */ + public function setLocale($locale) + { + $this->locale = $locale; + } + + /** + * @return array + */ + public function getMetadata() + { + return $this->metadata; + } + + /** + * @param array $metadata + */ + public function setMetadata($metadata) + { + $this->metadata = $metadata; + } + + /** + * @return DateTime + */ + public function getCreatedAt() + { + return $this->createdAt; + } + + /** + * @param DateTime $createdAt + */ + public function setCreatedAt($createdAt) + { + $this->createdAt = $createdAt; + } + + /** + * @return Link[] + */ + public function getLinks() + { + return $this->links; + } + + /** + * @param Link[] $links + */ + public function setLinks($links) + { + $this->links = $links; + } + + public function toArray() + { + $links = array(); + foreach ($this->links as $linkKey => $link) { + $links[$linkKey] = $link->toArray(); + } + + return array( + 'resource' => $this->resource, + 'id' => $this->id, + 'name' => $this->name, + 'mode' => $this->mode, + 'email' => $this->email, + 'locale' => $this->locale, + 'metadata' => $this->metadata, + 'createdAt' => $this->createdAt, + '_links' => $links, + ); + } +} diff --git a/IntegrationCore/BusinessLogic/Http/DTO/Payment.php b/IntegrationCore/BusinessLogic/Http/DTO/Payment.php index b9fbeb3..560ca15 100644 --- a/IntegrationCore/BusinessLogic/Http/DTO/Payment.php +++ b/IntegrationCore/BusinessLogic/Http/DTO/Payment.php @@ -28,6 +28,10 @@ class Payment extends BaseDto * @var string */ protected $orderId; + /** + * @var string + */ + protected $customerId; /** * @var string */ @@ -112,6 +116,7 @@ public static function fromArray(array $raw) $result->id = static::getValue($raw, 'id'); $result->profileId = static::getValue($raw, 'profileId'); $result->orderId = static::getValue($raw, 'orderId'); + $result->customerId = static::getValue($raw, 'customerId'); $result->description = static::getValue($raw, 'description'); $result->amount = Amount::fromArray(static::getValue($raw, 'amount', array())); $result->amountRefunded = Amount::fromArray(static::getValue($raw, 'amountRefunded', array())); @@ -172,6 +177,7 @@ public function toArray() 'id' => $this->id, 'profileId' => $this->profileId, 'orderId' => $this->orderId, + 'customerId' => $this->customerId, 'description' => $this->description, 'amount' => $this->amount->toArray(), 'amountRefunded' => $this->amountRefunded->toArray(), @@ -262,6 +268,22 @@ public function setOrderId($orderId) $this->orderId = $orderId; } + /** + * @return string + */ + public function getCustomerId() + { + return $this->customerId; + } + + /** + * @param string $customerId + */ + public function setCustomerId($customerId) + { + $this->customerId = $customerId; + } + /** * @return string */ diff --git a/IntegrationCore/BusinessLogic/Http/OrgToken/ProxyDataProvider.php b/IntegrationCore/BusinessLogic/Http/OrgToken/ProxyDataProvider.php index e063f8b..d25137a 100644 --- a/IntegrationCore/BusinessLogic/Http/OrgToken/ProxyDataProvider.php +++ b/IntegrationCore/BusinessLogic/Http/OrgToken/ProxyDataProvider.php @@ -4,6 +4,7 @@ use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Configuration; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\Address; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\Customer; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\Orders\Order; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\Orders\OrderLine; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\Orders\Shipment; @@ -46,6 +47,7 @@ public function transformPayment(Payment $payment) $result = array( 'profileId' => $payment->getProfileId(), + 'customerId' => $payment->getCustomerId(), 'description' => $payment->getDescription(), 'amount' => $payment->getAmount()->toArray(), 'redirectUrl' => $payment->getRedirectUrl(), @@ -414,6 +416,10 @@ protected function getCommonPaymentParameters(Payment $payment) $paymentSpecific['dueDate'] = $payment->getDueDate()->format(Order::MOLLIE_DATE_FORMAT); } + if ($payment->getCustomerId()) { + $paymentSpecific['customerId'] =$payment->getCustomerId(); + } + return $paymentSpecific; } @@ -471,4 +477,19 @@ protected function getConfigService() return $this->configService; } + + /** + * @param Customer $customer + * + * @return array + */ + public function transformCustomer(Customer $customer) + { + return array( + 'name' => $customer->getName(), + 'email' => $customer->getEmail(), + 'locale' => $customer->getLocale(), + 'metadata' => $customer->getMetadata(), + ); + } } diff --git a/IntegrationCore/BusinessLogic/Http/Proxy.php b/IntegrationCore/BusinessLogic/Http/Proxy.php index b65abee..dc9b63f 100644 --- a/IntegrationCore/BusinessLogic/Http/Proxy.php +++ b/IntegrationCore/BusinessLogic/Http/Proxy.php @@ -3,6 +3,7 @@ namespace Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\Amount; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\Customer; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\Orders\Order; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\Orders\OrderLine; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\Orders\Shipment; @@ -236,7 +237,8 @@ public function getAllPaymentMethods() } /** - * Gets all enabled payment methods from Mollie API + * Gets all enabled payment methods from Mollie API in form of a dictionary, where dictionary key is payment method id and + * value is payment method DTO * * @param string|null $billingCountry The billing country of your customer in ISO 3166-1 alpha-2 format. * @param Amount|null $amount @@ -250,25 +252,23 @@ public function getAllPaymentMethods() * @throws HttpRequestException * @throws UnprocessableEntityRequestException */ - public function getEnabledPaymentMethods( + public function getEnabledPaymentMethodsMap( $billingCountry = null, $amount = null, $apiMethod = PaymentMethodConfig::API_METHOD_ORDERS, $orderLineCategories = array() ) { - $queryString = $this->buildQueryParamsForEnabledMethod($apiMethod, $billingCountry, $amount, $orderLineCategories); - - $response = $this->call(self::HTTP_METHOD_GET, "/methods?{$queryString}"); - $result = $response->decodeBodyAsJson(); + $paymentMethodsMap = array(); + $paymentMethods = $this->getEnabledPaymentMethods($billingCountry, $amount, $apiMethod, $orderLineCategories); + foreach ($paymentMethods as $paymentMethod) { + $paymentMethodsMap[$paymentMethod->getId()] = $paymentMethod; + } - return PaymentMethod::fromArrayBatch( - !empty($result['_embedded']['methods']) ? $result['_embedded']['methods'] : array() - ); + return $paymentMethodsMap; } /** - * Gets all enabled payment methods from Mollie API in form of a dictionary, where dictionary key is payment method id and - * value is payment method DTO + * Gets all enabled payment methods from Mollie API * * @param string|null $billingCountry The billing country of your customer in ISO 3166-1 alpha-2 format. * @param Amount|null $amount @@ -282,23 +282,56 @@ public function getEnabledPaymentMethods( * @throws HttpRequestException * @throws UnprocessableEntityRequestException */ - public function getEnabledPaymentMethodsMap( + public function getEnabledPaymentMethods( $billingCountry = null, $amount = null, $apiMethod = PaymentMethodConfig::API_METHOD_ORDERS, $orderLineCategories = array() ) { - $paymentMethodsMap = array(); - $paymentMethods = $this->getEnabledPaymentMethods($billingCountry, $amount, $apiMethod, $orderLineCategories); - foreach ($paymentMethods as $paymentMethod) { - $paymentMethodsMap[$paymentMethod->getId()] = $paymentMethod; + $queryString = $this->buildQueryParamsForEnabledMethod($apiMethod, $billingCountry, $amount, $orderLineCategories); + + $response = $this->call(self::HTTP_METHOD_GET, "/methods?{$queryString}"); + $result = $response->decodeBodyAsJson(); + + return PaymentMethod::fromArrayBatch( + !empty($result['_embedded']['methods']) ? $result['_embedded']['methods'] : array() + ); + } + + /** + * @param string $apiMethod + * @param string $billingCountry + * @param Amount $amount + * @param array $orderLineCategories + * + * @return string + */ + protected function buildQueryParamsForEnabledMethod($apiMethod, $billingCountry, $amount, $orderLineCategories) + { + $params = array( + 'include' => 'issuers', + 'includeWallets' => 'applepay', + 'resource' => $apiMethod === PaymentMethodConfig::API_METHOD_PAYMENT ? 'payments' : 'orders', + ); + + if (!empty($billingCountry)) { + $params['billingCountry'] = $billingCountry; } - return $paymentMethodsMap; + if ($amount) { + $params['amount'] = $amount->toArray(); + } + + if (!empty($orderLineCategories)) { + $params['orderLineCategories'] = implode(',', $orderLineCategories); + } + + return http_build_query($params); } /** * Returns enabled methods for the given profile ID + * * @param string $profileId * * @return PaymentMethod[] @@ -418,6 +451,45 @@ public function getOrder($orderId) return is_array($result) ? Order::fromArray($result) : new Order(); } + /** + * Creates customer on customers API + * + * @param Customer $customer + * + * @return Customer + * @throws HttpAuthenticationException + * @throws HttpCommunicationException + * @throws HttpRequestException + * @throws UnprocessableEntityRequestException + */ + public function createCustomer(Customer $customer) + { + $customerData = $this->transformer->transformCustomer($customer); + $response = $this->call( + self::HTTP_METHOD_POST, + 'customers', + $customerData + ); + $result = $response->decodeBodyAsJson(); + + return is_array($result) ? Customer::fromArray($result) : new Customer(); + } + + /** + * Removes customer from Mollie by its id + * + * @param string $id customer identifier on Mollie + * + * @throws HttpAuthenticationException + * @throws HttpCommunicationException + * @throws HttpRequestException + * @throws UnprocessableEntityRequestException + */ + public function deleteCustomer($id) + { + $this->call(self::HTTP_METHOD_DELETE, "customers/$id"); + } + /** * Creates order shipment on Mollie * @@ -465,35 +537,4 @@ public function getShipments($orderId) return Shipment::fromArrayBatch($result['_embedded']['shipments']); } - - /** - * @param string $apiMethod - * @param string $billingCountry - * @param Amount $amount - * @param array $orderLineCategories - * - * @return string - */ - protected function buildQueryParamsForEnabledMethod($apiMethod, $billingCountry, $amount, $orderLineCategories) - { - $params = array( - 'include' => 'issuers', - 'includeWallets' => 'applepay', - 'resource' => $apiMethod === PaymentMethodConfig::API_METHOD_PAYMENT ? 'payments' : 'orders', - ); - - if (!empty($billingCountry)) { - $params['billingCountry'] = $billingCountry; - } - - if ($amount) { - $params['amount'] = $amount->toArray(); - } - - if (!empty($orderLineCategories)) { - $params['orderLineCategories'] = implode(',', $orderLineCategories); - } - - return http_build_query($params); - } } diff --git a/IntegrationCore/BusinessLogic/PaymentMethod/Model/PaymentMethodConfig.php b/IntegrationCore/BusinessLogic/PaymentMethod/Model/PaymentMethodConfig.php index ce025eb..840a35a 100644 --- a/IntegrationCore/BusinessLogic/PaymentMethod/Model/PaymentMethodConfig.php +++ b/IntegrationCore/BusinessLogic/PaymentMethod/Model/PaymentMethodConfig.php @@ -4,6 +4,7 @@ use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Http\DTO\PaymentMethod; use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\PaymentMethod\PaymentMethods; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Surcharge\SurchargeType; use Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\ORM\Configuration\EntityConfiguration; use Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\ORM\Configuration\IndexMap; use Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\ORM\Entity; @@ -36,6 +37,13 @@ class PaymentMethodConfig extends Entity const DEFAULT_TRANSACTION_DESCRIPTION = '{orderNumber}'; + protected static $allowedSurchargeTypes = array( + SurchargeType::NO_FEE, + SurchargeType::FIXED_FEE, + SurchargeType::PERCENTAGE, + SurchargeType::FIXED_FEE_AND_PERCENTAGE + ); + /** * @var string[] */ @@ -60,6 +68,11 @@ class PaymentMethodConfig extends Entity */ protected static $mollieComponentsSupportedMethods = array(PaymentMethods::CreditCard); + /** + * @var array + */ + protected static $singleClickSupportedMethods = array(PaymentMethods::CreditCard); + /** * @var array */ @@ -78,10 +91,16 @@ class PaymentMethodConfig extends Entity 'name', 'description', 'apiMethod', - 'surcharge', + 'surchargeType', + 'surchargeFixedAmount', + 'surchargePercentage', + 'surchargeLimit', 'image', 'enabled', 'useMollieComponents', + 'useSingleClickPayment', + 'singleClickPaymentApprovalText', + 'singleClickPaymentDescription', 'issuerListStyle', 'daysToOrderExpire', 'daysToPaymentExpire', @@ -107,10 +126,23 @@ class PaymentMethodConfig extends Entity * @var string One of PaymentMethodConfig::API_METHOD_PAYMENT or PaymentMethodConfig::API_METHOD_ORDERS */ protected $apiMethod; + /** + * @var string One of SurchargeType::NO_FEE, SurchargeType::FIXED_FEE, SurchargeType::PERCENTAGE or + * SurchargeType::FIXED_FEE_AND_PERCENTAGE + */ + protected $surchargeType; + /** + * @var float + */ + protected $surchargeFixedAmount; + /** + * @var float + */ + protected $surchargePercentage; /** * @var float */ - protected $surcharge; + protected $surchargeLimit; /** * @var null|string */ @@ -128,6 +160,22 @@ class PaymentMethodConfig extends Entity * @var bool */ protected $useMollieComponents = true; + + /** + * @var bool + */ + protected $useSingleClickPayment = true; + + /** + * @var string + */ + protected $singleClickPaymentApprovalText; + + /** + * @var string + */ + protected $singleClickPaymentDescription; + /** * @var string */ @@ -217,6 +265,14 @@ public function isMollieComponentsSupported() return in_array($this->getMollieId(), static::$mollieComponentsSupportedMethods, true); } + /** + * @return bool + */ + public function isSingleClickPaymentSupported() + { + return in_array($this->getMollieId(), static::$singleClickSupportedMethods, true); + } + /** * @return bool */ @@ -378,20 +434,78 @@ public function setOriginalAPIConfig($originalAPIConfig) $this->originalAPIConfig = $originalAPIConfig; } + /** + * @return string + */ + public function getSurchargeType() + { + return $this->surchargeType ?: SurchargeType::NO_FEE; + } + + /** + * @param string $surchargeType + */ + public function setSurchargeType($surchargeType) + { + if (!in_array($surchargeType, static::$allowedSurchargeTypes, true)) { + throw new \InvalidArgumentException( + sprintf( + 'Invalid surcharge type value %s. Surcharge type can be one of (%s) values', + $surchargeType, + implode(', ', static::$allowedSurchargeTypes) + ) + ); + } + + $this->surchargeType = $surchargeType; + } + /** * @return float */ - public function getSurcharge() + public function getSurchargeFixedAmount() { - return $this->surcharge; + return $this->surchargeFixedAmount; } /** - * @param float $surcharge + * @param float $surchargeFixedAmount */ - public function setSurcharge($surcharge) + public function setSurchargeFixedAmount($surchargeFixedAmount) { - $this->surcharge = $surcharge; + $this->surchargeFixedAmount = $surchargeFixedAmount; + } + + /** + * @return float + */ + public function getSurchargePercentage() + { + return $this->surchargePercentage; + } + + /** + * @param float $surchargePercentage + */ + public function setSurchargePercentage($surchargePercentage) + { + $this->surchargePercentage = $surchargePercentage; + } + + /** + * @return float + */ + public function getSurchargeLimit() + { + return $this->surchargeLimit; + } + + /** + * @param float $surchargeLimit + */ + public function setSurchargeLimit($surchargeLimit) + { + $this->surchargeLimit = $surchargeLimit; } /** @@ -410,6 +524,54 @@ public function setUseMollieComponents($useMollieComponents) $this->useMollieComponents = $useMollieComponents; } + /** + * @return bool + */ + public function useSingleClickPayment() + { + return $this->useSingleClickPayment; + } + + /** + * @param bool $useSingleClickPayment + */ + public function setUseSingleClickPayment($useSingleClickPayment) + { + $this->useSingleClickPayment = $useSingleClickPayment; + } + + /** + * @return string + */ + public function getSingleClickPaymentApprovalText() + { + return $this->singleClickPaymentApprovalText; + } + + /** + * @param string $singleClickPaymentApprovalText + */ + public function setSingleClickPaymentApprovalText($singleClickPaymentApprovalText) + { + $this->singleClickPaymentApprovalText = $singleClickPaymentApprovalText; + } + + /** + * @return string + */ + public function getSingleClickPaymentDescription() + { + return $this->singleClickPaymentDescription; + } + + /** + * @param string $singleClickPaymentDescription + */ + public function setSingleClickPaymentDescription($singleClickPaymentDescription) + { + $this->singleClickPaymentDescription = $singleClickPaymentDescription; + } + /** * @return string */ diff --git a/IntegrationCore/BusinessLogic/Surcharge/SurchargeCalculationService.php b/IntegrationCore/BusinessLogic/Surcharge/SurchargeCalculationService.php new file mode 100644 index 0000000..af4d9cb --- /dev/null +++ b/IntegrationCore/BusinessLogic/Surcharge/SurchargeCalculationService.php @@ -0,0 +1,29 @@ + $limit) { + return $limit; + } + + return $surcharge; + case SurchargeType::FIXED_FEE_AND_PERCENTAGE: + $surcharge = $fixedAmount + $subtotal * $percentage / 100; + + if ($surcharge > $limit) { + return $limit; + } + + return $surcharge; + default: + return 0; + } + } +} diff --git a/IntegrationCore/BusinessLogic/Surcharge/SurchargeType.php b/IntegrationCore/BusinessLogic/Surcharge/SurchargeType.php new file mode 100644 index 0000000..642f24d --- /dev/null +++ b/IntegrationCore/BusinessLogic/Surcharge/SurchargeType.php @@ -0,0 +1,16 @@ +localizationHelper->getCurrentLocalization(); + + $cardToken = $this->getRequestParam('mollie-card-token', $paymentTransaction->getPaymentMethod()); + $mollieCustomerId = ''; + $saveSingleClickPayment = $this->getRequestParam( + 'mollie-save-single-click-payment', + $paymentTransaction->getPaymentMethod() + ) === 'true'; + $useSavedSingleClickPayment = $this->getRequestParam( + 'mollie-use-saved-single-click-payment', + $paymentTransaction->getPaymentMethod() + ) === 'true'; + + $customerId = $order->getCustomerUser()->getId(); + if ($useSavedSingleClickPayment) { + $customer = $this->getCustomerReferenceService()->getByShopReference($customerId); + + if ($customer) { + $mollieCustomerId = $customer->getMollieReference(); + } + + $cardToken = ''; + } elseif ($saveSingleClickPayment) { + $mollieCustomerId = $this->getCustomerService()->createCustomer( + $this->getCurrentCustomerOrderAPI($order), + (string)$customerId + ); + } + $orderData = Order::fromArray([ 'locale' => $currentLocalization ? $currentLocalization->getLanguageCode() : LocaleConfiguration::DEFAULT_LANGUAGE, 'orderNumber' => $order->getIdentifier(), @@ -155,7 +187,8 @@ public function getOrderData(PaymentTransaction $paymentTransaction) ), 'payment' => [ 'issuer' => $this->getRequestParam('mollie-issuer', $paymentTransaction->getPaymentMethod()), - 'cardToken' => $this->getRequestParam('mollie-card-token', $paymentTransaction->getPaymentMethod()), + 'cardToken' => $cardToken, + 'customerId' => $mollieCustomerId, ], 'webhookUrl' => $this->ensureDebugWebhookUrl( $this->router->generate( @@ -226,51 +259,6 @@ public function getOrderLine(OrderLineItem $orderLine) return $orderLineData; } - /** - * {@inheritdoc} - */ - public function getPaymentData(PaymentTransaction $paymentTransaction) - { - $currentLocalization = $this->localizationHelper->getCurrentLocalization(); - - $payment = Payment::fromArray([ - 'locale' => $currentLocalization ? $currentLocalization->getLanguageCode() : LocaleConfiguration::DEFAULT_LANGUAGE, - 'amount' => [ - 'value' => $paymentTransaction->getAmount(), - 'currency' => $paymentTransaction->getCurrency() - ], - 'metadata' => [ - 'order_id' => $paymentTransaction->getEntityIdentifier() - ], - 'redirectUrl' => $this->ensureDebugWebhookUrl( - $this->router->generate( - 'oro_payment_callback_return', - ['accessIdentifier' => $paymentTransaction->getAccessIdentifier()], - UrlGeneratorInterface::ABSOLUTE_URL - ) - ), - 'webhookUrl' => $this->ensureDebugWebhookUrl( - $this->router->generate( - 'oro_payment_callback_notify', - [ - 'accessIdentifier' => $paymentTransaction->getAccessIdentifier(), - 'accessToken' => $paymentTransaction->getAccessToken(), - ], - UrlGeneratorInterface::ABSOLUTE_URL - ) - ), - 'issuer' => $this->getRequestParam('mollie-issuer', $paymentTransaction->getPaymentMethod()), - 'cardToken' => $this->getRequestParam('mollie-card-token', $paymentTransaction->getPaymentMethod()), - ]); - - if (($order = $this->getOrderEntity($paymentTransaction)) && ($shippingAddress = $order->getShippingAddress())) { - $payment->setShippingAddress($this->getAddressData($shippingAddress, $order->getEmail())); - $payment->setDescription($this->getDescription($order, $paymentTransaction)); - } - - return $payment; - } - /** * {@inheritdoc} */ @@ -411,6 +399,129 @@ public function getSurcharges(OroOrder $order) return $orderLinesData; } + /** + * {@inheritdoc} + */ + public function getPaymentData(PaymentTransaction $paymentTransaction) + { + $currentLocalization = $this->localizationHelper->getCurrentLocalization(); + + $cardToken = $this->getRequestParam('mollie-card-token', $paymentTransaction->getPaymentMethod()); + $mollieCustomerId = ''; + $saveSingleClickPayment = $this->getRequestParam( + 'mollie-save-single-click-payment', + $paymentTransaction->getPaymentMethod() + ) === 'true'; + $useSavedSingleClickPayment = $this->getRequestParam( + 'mollie-use-saved-single-click-payment', + $paymentTransaction->getPaymentMethod() + ) === 'true'; + + $customerId = $paymentTransaction->getFrontendOwner()->getId(); + if ($useSavedSingleClickPayment) { + $customer = $this->getCustomerReferenceService()->getByShopReference($customerId); + + if ($customer) { + $mollieCustomerId = $customer->getMollieReference(); + } + + $cardToken = ''; + } elseif ($saveSingleClickPayment) { + $mollieCustomerId = $this->getCustomerService()->createCustomer( + $this->getCurrentCustomerPaymentAPI($paymentTransaction), + (string)$customerId + ); + } + + $payment = Payment::fromArray([ + 'locale' => $currentLocalization ? $currentLocalization->getLanguageCode() : LocaleConfiguration::DEFAULT_LANGUAGE, + 'amount' => [ + 'value' => $paymentTransaction->getAmount(), + 'currency' => $paymentTransaction->getCurrency() + ], + 'metadata' => [ + 'order_id' => $paymentTransaction->getEntityIdentifier() + ], + 'redirectUrl' => $this->ensureDebugWebhookUrl( + $this->router->generate( + 'oro_payment_callback_return', + ['accessIdentifier' => $paymentTransaction->getAccessIdentifier()], + UrlGeneratorInterface::ABSOLUTE_URL + ) + ), + 'webhookUrl' => $this->ensureDebugWebhookUrl( + $this->router->generate( + 'oro_payment_callback_notify', + [ + 'accessIdentifier' => $paymentTransaction->getAccessIdentifier(), + 'accessToken' => $paymentTransaction->getAccessToken(), + ], + UrlGeneratorInterface::ABSOLUTE_URL + ) + ), + 'issuer' => $this->getRequestParam('mollie-issuer', $paymentTransaction->getPaymentMethod()), + 'cardToken' => $cardToken, + 'customerId' => $mollieCustomerId, + ]); + + if (($order = $this->getOrderEntity($paymentTransaction)) && ($shippingAddress = $order->getShippingAddress())) { + $payment->setShippingAddress($this->getAddressData($shippingAddress, $order->getEmail())); + $payment->setDescription($this->getDescription($order, $paymentTransaction)); + } + + return $payment; + } + + /** + * @param OroOrder $order + * + * @return MollieCustomer + */ + protected function getCurrentCustomerOrderAPI(OroOrder $order): MollieCustomer + { + $customer = new MollieCustomer(); + $customer->setName($order->getCustomerUser()->getFirstName() . ' ' . $order->getCustomerUser()->getLastName()); + $customer->setEmail($order->getCustomerUser()->getEmail()); + + return $customer; + } + + /** + * @param PaymentTransaction $paymentTransaction + * + * @return MollieCustomer + */ + protected function getCurrentCustomerPaymentAPI(PaymentTransaction $paymentTransaction): MollieCustomer + { + $customer = new MollieCustomer(); + $customer->setName($paymentTransaction->getFrontendOwner()->getFirstName() . ' ' . $paymentTransaction->getFrontendOwner()->getLastName()); + $customer->setEmail($paymentTransaction->getFrontendOwner()->getEmail()); + + return $customer; + } + + /** + * @return CustomerService + */ + protected function getCustomerService(): CustomerService + { + /** @var CustomerService $customerService */ + $customerService = ServiceRegister::getService(CustomerService::CLASS_NAME); + + return $customerService; + } + + /** + * @return CustomerReferenceService + */ + protected function getCustomerReferenceService(): CustomerReferenceService + { + /** @var CustomerReferenceService $customerReferenceService */ + $customerReferenceService = ServiceRegister::getService(CustomerReferenceService::CLASS_NAME); + + return $customerReferenceService; + } + /** * Gets tax row model for a given order line * diff --git a/Migrations/Schema/v1_2/MollieSingleClickPayment.php b/Migrations/Schema/v1_2/MollieSingleClickPayment.php new file mode 100644 index 0000000..0c69aca --- /dev/null +++ b/Migrations/Schema/v1_2/MollieSingleClickPayment.php @@ -0,0 +1,109 @@ +hasTable(self::SINGLE_CLICK_PAYMENT_APPROVAL_TEXT)) { + $this->createMolliePaymentSettingsSingleClickApprovalTextTable($schema); + $this->addMolliePaymentSettingsSingleSlickApprovalTextForeignKeys($schema); + } + + if (!$schema->hasTable(self::SINGLE_CLICK_PAYMENT_DESCRIPTION)) { + $this->createMolliePaymentSettingsSingleClickDescriptionTable($schema); + $this->addMolliePaymentSettingsSingleSlickDescriptionForeignKeys($schema); + } + } + + /** + * Create mollie_single_click_appr_text table + * + * @param Schema $schema + */ + protected function createMolliePaymentSettingsSingleClickApprovalTextTable(Schema $schema) + { + $table = $schema->createTable(self::SINGLE_CLICK_PAYMENT_APPROVAL_TEXT); + $table->addColumn('payment_setting_id', 'integer', []); + $table->addColumn('localized_value_id', 'integer', []); + $table->setPrimaryKey(['payment_setting_id', 'localized_value_id']); + $table->addUniqueIndex(['localized_value_id'], 'UNIQ_Single_Click_Approval_Text'); + $table->addIndex(['payment_setting_id'], 'IDX_Single_Click_Approval_Text', []); + } + + /** + * Create mollie_single_click_desc table + * + * @param Schema $schema + */ + protected function createMolliePaymentSettingsSingleClickDescriptionTable(Schema $schema) + { + $table = $schema->createTable(self::SINGLE_CLICK_PAYMENT_DESCRIPTION); + $table->addColumn('payment_setting_id', 'integer', []); + $table->addColumn('localized_value_id', 'integer', []); + $table->setPrimaryKey(['payment_setting_id', 'localized_value_id']); + $table->addUniqueIndex(['localized_value_id'], 'UNIQ_Single_Click_Description'); + $table->addIndex(['payment_setting_id'], 'IDX_Single_Click_Description', []); + } + + /** + * Add mollie_single_click_appr_text foreign keys. + * + * @param Schema $schema + * + * @throws \Doctrine\DBAL\Schema\SchemaException + */ + protected function addMolliePaymentSettingsSingleSlickApprovalTextForeignKeys(Schema $schema) + { + $table = $schema->getTable(self::SINGLE_CLICK_PAYMENT_APPROVAL_TEXT); + $table->addForeignKeyConstraint( + $schema->getTable('mollie_payment_settings'), + ['payment_setting_id'], + ['id'], + ['onDelete' => 'CASCADE', 'onUpdate' => null] + ); + $table->addForeignKeyConstraint( + $schema->getTable('oro_fallback_localization_val'), + ['localized_value_id'], + ['id'], + ['onDelete' => 'CASCADE', 'onUpdate' => null] + ); + } + + /** + * Add mollie_single_click_desc foreign keys. + * + * @param Schema $schema + * + * @throws \Doctrine\DBAL\Schema\SchemaException + */ + protected function addMolliePaymentSettingsSingleSlickDescriptionForeignKeys(Schema $schema) + { + $table = $schema->getTable(self::SINGLE_CLICK_PAYMENT_DESCRIPTION); + $table->addForeignKeyConstraint( + $schema->getTable('mollie_payment_settings'), + ['payment_setting_id'], + ['id'], + ['onDelete' => 'CASCADE', 'onUpdate' => null] + ); + $table->addForeignKeyConstraint( + $schema->getTable('oro_fallback_localization_val'), + ['localized_value_id'], + ['id'], + ['onDelete' => 'CASCADE', 'onUpdate' => null] + ); + } +} diff --git a/PaymentMethod/Config/Factory/PaymentConfigFactory.php b/PaymentMethod/Config/Factory/PaymentConfigFactory.php index 56199d7..d7c158a 100644 --- a/PaymentMethod/Config/Factory/PaymentConfigFactory.php +++ b/PaymentMethod/Config/Factory/PaymentConfigFactory.php @@ -66,6 +66,9 @@ public function create(PaymentMethodSettings $paymentMethodSetting) $paymentDescription = $this->getLocalizedValue($paymentMethodSetting->getPaymentDescriptions()); $transactionDescription = $this->getLocalizedValue($paymentMethodSetting->getTransactionDescriptions()); + $singleClickPaymentApprovalText = $this->getLocalizedValue($paymentMethodSetting->getSingleClickPaymentApprovalText()); + $singleClickPaymentDescription = $this->getLocalizedValue($paymentMethodSetting->getSingleClickPaymentDescription()); + $paymentLabel = $this->getLocalizedValue($paymentMethodSetting->getDescriptions()); $adminLabel = "{$channel->getName()} - {$paymentLabel}"; @@ -97,9 +100,16 @@ public function create(PaymentMethodSettings $paymentMethodSetting) $configParams[MolliePaymentConfig::IS_API_METHOD_RESTRICTED] = $mollieMethodConfig->isApiMethodRestricted(); $configParams[MolliePaymentConfig::PROFILE_ID] = $mollieMethodConfig->getProfileId(); $configParams[MolliePaymentConfig::CHANNEL_ID] = $channel->getId(); - $configParams[MolliePaymentConfig::SURCHARGE_AMOUNT] = $mollieMethodConfig->getSurcharge(); + $configParams[MolliePaymentConfig::SURCHARGE_TYPE] = $mollieMethodConfig->getSurchargeType(); + $configParams[MolliePaymentConfig::SURCHARGE_FIXED_AMOUNT] = $mollieMethodConfig->getSurchargeFixedAmount(); + $configParams[MolliePaymentConfig::SURCHARGE_PERCENTAGE] = $mollieMethodConfig->getSurchargePercentage(); + $configParams[MolliePaymentConfig::SURCHARGE_LIMIT] = $mollieMethodConfig->getSurchargeLimit(); $configParams[MolliePaymentConfig::ISSUER_LIST_STYLE] = $mollieMethodConfig->getIssuerListStyle(); $configParams[MolliePaymentConfig::USE_MOLLIE_COMPONENTS] = $useMollieComponents; + $configParams[MolliePaymentConfig::USE_SINGLE_CLICK_PAYMENT] = $useMollieComponents && + $mollieMethodConfig->useSingleClickPayment(); + $configParams[MolliePaymentConfig::SINGLE_CLICK_PAYMENT_APPROVAL_TEXT] = $singleClickPaymentApprovalText; + $configParams[MolliePaymentConfig::SINGLE_CLICK_PAYMENT_DESCRIPTION_TEXT] = $singleClickPaymentDescription; $configParams[MolliePaymentConfig::ISSUERS] = $this->getIssuers($mollieMethodConfig, $channel->getId()); $configParams[MolliePaymentConfig::ORDER_EXPIRY_DAYS] = $mollieMethodConfig->getDaysToOrderExpire(); $configParams[MolliePaymentConfig::PAYMENT_EXPIRY_DAYS] = $mollieMethodConfig->getDaysToPaymentExpire(); diff --git a/PaymentMethod/Config/MolliePaymentConfig.php b/PaymentMethod/Config/MolliePaymentConfig.php index ee61f23..810b122 100644 --- a/PaymentMethod/Config/MolliePaymentConfig.php +++ b/PaymentMethod/Config/MolliePaymentConfig.php @@ -19,9 +19,15 @@ class MolliePaymentConfig extends AbstractParameterBagPaymentConfig implements M const IS_API_METHOD_RESTRICTED = 'is_api_method_restricted'; const PROFILE_ID = 'profile_id'; const CHANNEL_ID = 'channel_id'; - const SURCHARGE_AMOUNT = 'surcharge_amount'; + const SURCHARGE_TYPE = 'surcharge_type'; + const SURCHARGE_FIXED_AMOUNT = 'surcharge_fixed_amount'; + const SURCHARGE_PERCENTAGE = 'surcharge_percentage'; + const SURCHARGE_LIMIT = 'surcharge_limit'; const ISSUER_LIST_STYLE = 'issuer_list_style'; const USE_MOLLIE_COMPONENTS = 'use_mollie_components'; + const USE_SINGLE_CLICK_PAYMENT = 'use_single_click_payment'; + const SINGLE_CLICK_PAYMENT_APPROVAL_TEXT = 'single_click_payment_approval_text'; + const SINGLE_CLICK_PAYMENT_DESCRIPTION_TEXT = 'single_click_payment_description'; const ISSUERS = 'issuers'; const PAYMENT_DESCRIPTION = 'payment_description'; const TRANSACTION_DESCRIPTION = 'transaction_description'; @@ -97,9 +103,33 @@ public function getChannelId() /** * {@inheritdoc} */ - public function getSurchargeAmount() + public function getSurchargeType() { - return (float)$this->get(self::SURCHARGE_AMOUNT); + return (string)$this->get(self::SURCHARGE_TYPE); + } + + /** + * {@inheritdoc} + */ + public function getSurchargeFixedAmount() + { + return (float)$this->get(self::SURCHARGE_FIXED_AMOUNT); + } + + /** + * {@inheritdoc} + */ + public function getSurchargePercentage() + { + return (float)$this->get(self::SURCHARGE_PERCENTAGE); + } + + /** + * {@inheritdoc} + */ + public function getSurchargeLimit() + { + return (float)$this->get(self::SURCHARGE_LIMIT); } /** @@ -110,6 +140,30 @@ public function useMollieComponents() return (bool)$this->get(self::USE_MOLLIE_COMPONENTS); } + /** + * {@inheritdoc } + */ + public function useSingleClickPayment() + { + return (bool)$this->get(self::USE_SINGLE_CLICK_PAYMENT); + } + + /** + * {@inheritdoc} + */ + public function getSingleClickPaymentApprovalText() + { + return (string)$this->get(self::SINGLE_CLICK_PAYMENT_APPROVAL_TEXT); + } + + /** + * {@inheritdoc} + */ + public function getSingleClickPaymentDescription() + { + return (string)$this->get(self::SINGLE_CLICK_PAYMENT_DESCRIPTION_TEXT); + } + /** * {@inheritdoc } */ diff --git a/PaymentMethod/Config/MolliePaymentConfigInterface.php b/PaymentMethod/Config/MolliePaymentConfigInterface.php index 3c03b6e..49041ea 100644 --- a/PaymentMethod/Config/MolliePaymentConfigInterface.php +++ b/PaymentMethod/Config/MolliePaymentConfigInterface.php @@ -52,16 +52,46 @@ public function getProfileId(); */ public function getChannelId(); + /** + * @return string + */ + public function getSurchargeType(); + + /** + * @return float + */ + public function getSurchargeFixedAmount(); + + /** + * @return float + */ + public function getSurchargePercentage(); + /** * @return float */ - public function getSurchargeAmount(); + public function getSurchargeLimit(); /** * @return bool */ public function useMollieComponents(); + /** + * @return bool + */ + public function useSingleClickPayment(); + + /** + * @return string + */ + public function getSingleClickPaymentApprovalText(); + + /** + * @return string + */ + public function getSingleClickPaymentDescription(); + /** * @return string */ diff --git a/PaymentMethod/Config/Provider/MolliePaymentConfigProvider.php b/PaymentMethod/Config/Provider/MolliePaymentConfigProvider.php index c5fec3c..4505853 100644 --- a/PaymentMethod/Config/Provider/MolliePaymentConfigProvider.php +++ b/PaymentMethod/Config/Provider/MolliePaymentConfigProvider.php @@ -167,7 +167,6 @@ protected function createPaymentLinkMethodSetting( $paymentLinkMethod->getPaymentMethodConfig()->getOriginalAPIConfig()->setId(null); $paymentLinkMethod->getPaymentMethodConfig()->getOriginalAPIConfig()->setImage(Image::fromArray([])); $paymentLinkMethod->getPaymentMethodConfig()->setApiMethod(PaymentMethodConfig::API_METHOD_PAYMENT); - $paymentLinkMethod->getPaymentMethodConfig()->setSurcharge(0); return $paymentLinkMethod; } @@ -285,9 +284,24 @@ protected function getPaymentMethodConfigurations(ChannelSettings $channelSettin ); } + if ($paymentMethodSetting->getSingleClickPaymentApprovalText()->isEmpty()) { + $paymentMethodSetting->addSingleClickPaymentApprovalText( + (new LocalizedFallbackValue())->setString($this->translator->trans('mollie.payment.config.payment_methods.single_click_payment_approval_text.value')) + ); + } + + if ($paymentMethodSetting->getSingleClickPaymentDescription()->isEmpty()) { + $paymentMethodSetting->addSingleClickPaymentDescription( + (new LocalizedFallbackValue())->setString($this->translator->trans('mollie.payment.config.payment_methods.single_click_payment_description.value')) + ); + } + $paymentMethodSetting->setPaymentMethodConfig($paymentMethodConfig); $paymentMethodSetting->setEnabled($paymentMethodConfig->isEnabled()); - $paymentMethodSetting->setSurcharge($paymentMethodConfig->getSurcharge()); + $paymentMethodSetting->setSurchargeType($paymentMethodConfig->getSurchargeType()); + $paymentMethodSetting->setSurchargeFixedAmount($paymentMethodConfig->getSurchargeFixedAmount()); + $paymentMethodSetting->setSurchargePercentage($paymentMethodConfig->getSurchargePercentage()); + $paymentMethodSetting->setSurchargeLimit($paymentMethodConfig->getSurchargeLimit()); $paymentMethodSetting->setMethod($paymentMethodConfig->getApiMethod()); $paymentMethodSetting->setOriginalImagePath($paymentMethodConfig->getOriginalAPIConfig()->getImage()->getSize2x()); $paymentMethodSetting->setImagePath( diff --git a/PaymentMethod/View/MolliePaymentView.php b/PaymentMethod/View/MolliePaymentView.php index 35fb55a..4342d60 100644 --- a/PaymentMethod/View/MolliePaymentView.php +++ b/PaymentMethod/View/MolliePaymentView.php @@ -2,10 +2,13 @@ namespace Mollie\Bundle\PaymentBundle\PaymentMethod\View; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\Surcharge\SurchargeService; use Mollie\Bundle\PaymentBundle\PaymentMethod\Config\MolliePaymentConfigInterface; use Oro\Bundle\PaymentBundle\Context\PaymentContextInterface; use Oro\Bundle\PaymentBundle\Method\Provider\PaymentMethodProvider; use Oro\Bundle\PaymentBundle\Method\View\PaymentMethodViewInterface; +use Mollie\Bundle\PaymentBundle\IntegrationCore\BusinessLogic\CustomerReference\CustomerReferenceService; +use Mollie\Bundle\PaymentBundle\IntegrationCore\Infrastructure\ServiceRegister; /** * Class MolliePaymentView @@ -40,12 +43,39 @@ public function __construct(MolliePaymentConfigInterface $config, PaymentMethodP */ public function getOptions(PaymentContextInterface $context) { + $renderSaveCreditCardCheckbox = false; + $renderUseSavedCreditCardCheckbox = false; + + if ($this->config->useSingleClickPayment() && !$context->getCustomerUser()->isGuest()) { + $customerFromDb = $this->getCustomerReferenceService()->getByShopReference($context->getCustomerUser()->getId()); + if (!$customerFromDb) { + $renderSaveCreditCardCheckbox = true; + } else { + $renderUseSavedCreditCardCheckbox = true; + } + } + + $surchargeType = $this->config->getSurchargeType(); + $surchargeFixedAmount = $this->config->getSurchargeFixedAmount(); + $surchargePercentage = $this->config->getSurchargePercentage(); + $surchargeLimit = $this->config->getSurchargeLimit(); + return [ 'isApplePay' => false !== strpos($this->config->getPaymentMethodIdentifier(), 'applepay'), 'icon' => $this->config->getIcon(), - 'surchargeAmount' => $this->config->getSurchargeAmount(), + 'surchargeAmount' => round($this->getSurchargeService()->calculateSurchargeAmount( + $surchargeType, + $surchargeFixedAmount, + $surchargePercentage, + $surchargeLimit, + $context->getSubtotal()->getValue()), 2 + ), 'currency' => $context->getCurrency(), 'useMollieComponents' => $this->config->useMollieComponents() && !$this->isMultipleCreditCard($context), + 'useSingleClickPayment' => $this->config->useMollieComponents() && !$this->isMultipleCreditCard($context) && + $this->config->useSingleClickPayment(), + 'singleClickPaymentApprovalText' => $this->config->getSingleClickPaymentApprovalText(), + 'singleClickPaymentDescription' => $this->config->getSingleClickPaymentDescription(), 'issuerListStyle' => $this->config->getIssuerListStyle(), 'issuers' => $this->config->getIssuers(), 'paymentMethod' => $this->config->getPaymentMethodIdentifier(), @@ -53,9 +83,51 @@ public function getOptions(PaymentContextInterface $context) 'profileId' => $this->config->getProfileId(), 'lang' => '', 'paymentDescription' => $this->config->getPaymentDescription(), + 'renderSaveCreditCardCheckbox' => $renderSaveCreditCardCheckbox, + 'renderUseSavedCreditCardCheckbox' => $renderUseSavedCreditCardCheckbox, ]; } + /** + * @return CustomerReferenceService + */ + protected function getCustomerReferenceService(): CustomerReferenceService + { + /** @var CustomerReferenceService $customerReferenceService */ + $customerReferenceService = ServiceRegister::getService(CustomerReferenceService::CLASS_NAME); + + return $customerReferenceService; + } + + /** + * @return SurchargeService + */ + protected function getSurchargeService() + { + /** @var SurchargeService $surchargeService */ + $surchargeService = ServiceRegister::getService(SurchargeService::CLASS_NAME); + + return $surchargeService; + } + + /** + * @param PaymentContextInterface $context + * + * @return bool + */ + private function isMultipleCreditCard(PaymentContextInterface $context) + { + $applicablePaymentMethods = $this->paymentMethodProvider->getApplicablePaymentMethods($context); + $numberOfMollieCreditCards = 0; + foreach ($applicablePaymentMethods as $key => $config) { + if (preg_match('/^mollie.*creditcard$/', $key)) { + $numberOfMollieCreditCards++; + } + } + + return $numberOfMollieCreditCards > 1; + } + /** * {@inheritdoc} */ @@ -93,22 +165,4 @@ public function getPaymentMethodIdentifier() { return $this->config->getPaymentMethodIdentifier(); } - - /** - * @param PaymentContextInterface $context - * - * @return bool - */ - private function isMultipleCreditCard(PaymentContextInterface $context) - { - $applicablePaymentMethods = $this->paymentMethodProvider->getApplicablePaymentMethods($context); - $numberOfMollieCreditCards = 0; - foreach ($applicablePaymentMethods as $key => $config) { - if (preg_match('/^mollie.*creditcard$/', $key)) { - $numberOfMollieCreditCards++; - } - } - - return $numberOfMollieCreditCards > 1; - } } diff --git a/README.md b/README.md index 367546c..47df711 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,9 @@ To finalize the installation you need to enter your organization API token in th Read more about the integration configuration on [our Wiki](https://github.com/mollie/orocommerce/wiki). ## Release notes + - **4.1.10:** + - Added single-click payments. + - Added surcharge rules. - **4.1.9:** - Added support for the Klarna Pay Now payment method. - **4.1.8:** diff --git a/Resources/config/services.yml b/Resources/config/services.yml index 06bb01f..5ce0203 100755 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -1,5 +1,5 @@ parameters: - mollie_payment.version: 4.1.9 + mollie_payment.version: 4.1.10 mollie_payment.method.identifier_prefix.mollie_payment: 'mollie_payment' mollie_payment.uploader.public_image_path: 'bundles/molliepayment/img/uploads' mollie_payment.uploader.image_dir: '%kernel.project_dir%/public/%mollie_payment.uploader.public_image_path%' diff --git a/Resources/public/default/scss/components/paument-methods.scss b/Resources/public/default/scss/components/paument-methods.scss index baf27d1..351a3eb 100755 --- a/Resources/public/default/scss/components/paument-methods.scss +++ b/Resources/public/default/scss/components/paument-methods.scss @@ -146,6 +146,19 @@ .form-group--cardNumber { grid-column: span 2; } + + .form-group--useSavedCreditCardCheckbox, + .form-group--saveCreditCardCheckbox { + grid-column: span 2; + + label { + left: 0; + + input { + transform: translateY(10%); + } + } + } } @media (min-width: 480px) { diff --git a/Resources/public/js/app/components/mollie-credit-card.js b/Resources/public/js/app/components/mollie-credit-card.js index 89cc007..4bc9f30 100644 --- a/Resources/public/js/app/components/mollie-credit-card.js +++ b/Resources/public/js/app/components/mollie-credit-card.js @@ -105,7 +105,21 @@ define(function(require) { }, mountComponents: function () { - let locale = document.querySelector('html').getAttribute('lang'); + let locale = document.querySelector('html').getAttribute('lang'), + useSavedCreditCardWrapper = document.getElementsByClassName('form-group--useSavedCreditCardCheckbox'), + useSavedCreditCard = document.getElementById(this.options.paymentMethod + '-use-saved-credit-card-checkbox'), + descriptionUseSingleClick = document.getElementsByClassName('mollie-payment-description single-click'), + descriptionUseMollieComponents = document.getElementsByClassName('mollie-payment-description use-components'); + + if (descriptionUseMollieComponents.length > 0) { + descriptionUseMollieComponents[0].classList.add('hidden'); + } + + if (descriptionUseSingleClick.length > 0) { + descriptionUseSingleClick[0].innerHTML = document.getElementById('mollie-credit-card-use-saved-description-input').value; + descriptionUseSingleClick[0].classList.add('hidden'); + } + this.$mollieTools = Mollie( this.options.profileId, { @@ -149,9 +163,72 @@ define(function(require) { this.addListeners(this.$verificationCode, this.options.verificationCodeSelector); this.addFormListener(); + if (useSavedCreditCardWrapper.length > 0) { + if (useSavedCreditCardWrapper[0].classList.contains('hidden')) { + useSavedCreditCard.checked = false; + this.showComponents(); + } else { + useSavedCreditCard.addEventListener('change', event => this.handleCheckboxUseSavedChange(event, this, descriptionUseSingleClick)); + + if (useSavedCreditCard.checked === false) { + this.showComponents(); + document.getElementsByClassName('form-group--saveCreditCardCheckbox')[0].classList.remove('hidden'); + } else { + if (descriptionUseSingleClick.length > 0) { + descriptionUseSingleClick[0].classList.remove('hidden'); + } + + this.hideComponents(); + } + } + } + }, + + handleCheckboxUseSavedChange: function (e, component, description) { + let target = e.target; + + if (target.checked) { + if (description.length > 0) { + description[0].classList.remove('hidden'); + } + + component.hideComponents(); + } else if (document.getElementsByClassName('form-group--cardHolder')[0].classList.contains('hidden')) { + document.getElementsByClassName('form-group--saveCreditCardCheckbox')[0].classList.remove('hidden'); + if (description.length > 0) { + description[0].classList.add('hidden'); + } + + component.showComponents(); + } else { + if (description.length > 0) { + description[0].classList.add('hidden'); + } + + } + }, + + hideComponents: function () { + document.getElementsByClassName('form-group--cardHolder')[0].classList.add('hidden'); + document.getElementsByClassName('form-group--cardNumber')[0].classList.add('hidden'); + document.getElementsByClassName('form-group--expiryDate')[0].classList.add('hidden'); + document.getElementsByClassName('form-group--verificationCode')[0].classList.add('hidden'); + document.getElementsByClassName('form-group--saveCreditCardCheckbox')[0].classList.add('hidden'); + } + , + + showComponents: function () { + document.getElementsByClassName('form-group--cardHolder')[0].classList.remove('hidden'); + document.getElementsByClassName('form-group--cardNumber')[0].classList.remove('hidden'); + document.getElementsByClassName('form-group--expiryDate')[0].classList.remove('hidden'); + document.getElementsByClassName('form-group--verificationCode')[0].classList.remove('hidden'); }, addFormListener: function () { + let useSavedCreditCard = document.getElementById(this.options.paymentMethod + '-use-saved-credit-card-checkbox'), + saveCreditCard = document.getElementById(this.options.paymentMethod + '-save-credit-card-checkbox'), + useSavedCreditCardWrapper = document.getElementsByClassName('form-group--useSavedCreditCardCheckbox'); + var form = document.forms[this.options.formSelector]; var me = this; @@ -160,18 +237,28 @@ define(function(require) { var target = $(event.target); if (isSubmitButton(target) && isCreditCard()) { - let selector = '#' + me.options.paymentMethod + '-mollie-card-token'; - var input = $(selector); - if (!input.val()) { - event.preventDefault(); - event.stopPropagation(); - me.$mollieTools.createToken().then((token) => { - if (token.token) { - input.val(token.token); - window.localStorage.setItem('mollieToken', token.token); - target.click(); - } - }); + if (useSavedCreditCardWrapper.length === 0 || (useSavedCreditCardWrapper.length > 0 && useSavedCreditCardWrapper[0].classList.contains('hidden'))) { + let selector = '#' + me.options.paymentMethod + '-mollie-card-token'; + var input = $(selector); + if (!input.val()) { + event.preventDefault(); + event.stopPropagation(); + me.$mollieTools.createToken().then((token) => { + if (token.token) { + input.val(token.token); + window.localStorage.setItem('mollieToken', token.token); + target.click(); + } + }); + } + } + + if (useSavedCreditCard !== null) { + window.localStorage.setItem('useSavedSingleClickCreditCardPayment', useSavedCreditCard.checked); + } + + if (saveCreditCard !== null) { + window.localStorage.setItem('saveSingleClickCreditCardPayment', saveCreditCard.checked); } } }); diff --git a/Resources/public/js/app/components/mollie-order-submit.js b/Resources/public/js/app/components/mollie-order-submit.js index a5400e5..20a26ee 100644 --- a/Resources/public/js/app/components/mollie-order-submit.js +++ b/Resources/public/js/app/components/mollie-order-submit.js @@ -47,6 +47,18 @@ define(function(require) { this.addToForm('mollie-card-token', window.localStorage.getItem('mollieToken'), form); window.localStorage.removeItem('mollieToken'); } + + let saveSingleClickCreditCardPaymentValue = window.localStorage.getItem('saveSingleClickCreditCardPayment'); + if (saveSingleClickCreditCardPaymentValue) { + this.addToForm('mollie-save-single-click-payment', window.localStorage.getItem('saveSingleClickCreditCardPayment'), form); + window.localStorage.removeItem('saveSingleClickCreditCardPayment'); + } + + let useSavedSingleClickCreditCardPaymentValue = window.localStorage.getItem('useSavedSingleClickCreditCardPayment'); + if (useSavedSingleClickCreditCardPaymentValue) { + this.addToForm('mollie-use-saved-single-click-payment', window.localStorage.getItem('useSavedSingleClickCreditCardPayment'), form); + window.localStorage.removeItem('useSavedSingleClickCreditCardPayment'); + } }, addToForm: function (name, value, form) { diff --git a/Resources/public/js/app/views/mollie-accordion-view.js b/Resources/public/js/app/views/mollie-accordion-view.js index c1ab7c3..54d0ff9 100644 --- a/Resources/public/js/app/views/mollie-accordion-view.js +++ b/Resources/public/js/app/views/mollie-accordion-view.js @@ -13,6 +13,14 @@ define(function (require) { }, apiMethodChooserSelector: 'select.mollie-method-select', + singleClickPaymentCheckbox: 'input.mollie-payment-single-click-status', + surchargeTypeChooserSelector: 'select.mollie-surcharge-type-select', + surchargeType: { + NO_FEE: 'no_fee', + FIXED_FEE: 'fixed_fee', + PERCENTAGE: 'percentage', + FIXED_FEE_AND_PERCENTAGE: 'fixed_fee_and_percentage' + }, /** * Renders a tabs view @@ -29,10 +37,18 @@ define(function (require) { $(this.apiMethodChooserSelector).each(function () { self.displayFieldsBasedOnMethod($(this).val(),$(this).attr('data-method-wrapper')); }); + $(this.surchargeTypeChooserSelector).each(function () { + self.displayFieldsBasedOnSyrchargeType($(this).val(), $(this).attr('data-method-wrapper')); + }); + $(this.singleClickPaymentCheckbox).each(function () { + self.displayFieldsBasedOnSinglePaymentStatus($(this)[0].checked); + }); }, addListeners: function () { $(this.apiMethodChooserSelector).change(this.handleApiMethodChange.bind(this)); + $(this.singleClickPaymentCheckbox).change(this.handleSingleClickStatusChange.bind(this)); + $(this.surchargeTypeChooserSelector).change(this.handleSyrchargeTypeChange.bind(this)); }, handleApiMethodChange: function (event) { @@ -42,6 +58,12 @@ define(function (require) { }, + handleSyrchargeTypeChange: function (event) { + let target = $(event.target); + + this.displayFieldsBasedOnSyrchargeType(target.val(), target.attr('data-method-wrapper')); + }, + displayFieldsBasedOnMethod: function (apiMethod, identifier) { let wrapper = $('.mollie-payment-method[data-payment-method-id="'+ identifier +'"]'); if (wrapper.length === 0) { @@ -57,6 +79,52 @@ define(function (require) { } }, + displayFieldsBasedOnSyrchargeType: function (surchargeType, identifier) { + let wrapper = $('.mollie-payment-method[data-payment-method-id="' + identifier + '"]'); + if (wrapper.length === 0) { + return; + } + + switch (surchargeType) { + case this.surchargeType.NO_FEE: + wrapper.find('.mollie-surcharge-fixed-amount, .mollie-surcharge-percentage, .mollie-surcharge-limit').addClass('mollie-hide-row'); + break; + case this.surchargeType.FIXED_FEE: + wrapper.find('.mollie-surcharge-fixed-amount').removeClass('mollie-hide-row'); + wrapper.find('.mollie-surcharge-percentage, .mollie-surcharge-limit').addClass('mollie-hide-row'); + break; + case this.surchargeType.PERCENTAGE: + wrapper.find('.mollie-surcharge-fixed-amount').addClass('mollie-hide-row'); + wrapper.find('.mollie-surcharge-percentage, .mollie-surcharge-limit').removeClass('mollie-hide-row'); + break; + case this.surchargeType.FIXED_FEE_AND_PERCENTAGE: + wrapper.find('.mollie-surcharge-fixed-amount, .mollie-surcharge-percentage, .mollie-surcharge-limit').removeClass('mollie-hide-row'); + break; + } + }, + + handleSingleClickStatusChange: function (event) { + let target = $(event.target); + + this.displayFieldsBasedOnSinglePaymentStatus(target[0].checked); + + }, + + displayFieldsBasedOnSinglePaymentStatus: function (checked) { + let wrapper = $('.mollie-payment-method[data-payment-method-id="creditcard"]'); + if (wrapper.length === 0) { + return; + } + + let fields = wrapper.find('.mollie-payment-single-click-approval-text, .mollie-payment-single-click-description'); + + if (fields.length > 0 && checked) { + fields.removeClass('mollie-hide-row'); + } else { + fields.addClass('mollie-hide-row'); + } + }, + /** * Disposes the view */ diff --git a/Resources/translations/messages.de.yml b/Resources/translations/messages.de.yml index 093b0da..2e5f1e0 100644 --- a/Resources/translations/messages.de.yml +++ b/Resources/translations/messages.de.yml @@ -39,6 +39,7 @@ mollie: cardNumber: 'Kreditkartennummer' expiryDate: 'MM/JJ' verificationCode: 'CVV' + useSavedCreditCardText: 'Hinterlegte Kreditkartendaten verwenden' config: authorization: label: 'Befugnis' @@ -93,9 +94,39 @@ mollie: Verwenden Sie die neue Auftrags-API-Plattform, um mehr Einblicke in die Bestellungen zu erhalten. Read more.' option.payment_api.label: 'Zahlungs-API' option.order_api.label: 'Auftrags-API' + payment_surcharge: + label: 'Zahlungszuschlag' + tooltip: 'Wählen Sie einen Zuschlagstyp aus.' + option.no_fee.label: 'Keine Gebühr' + option.fixed_fee.label: 'Feste Gebühr' + option.percentage.label: 'Anteil' + option.fixed_fee_and_percentage.label: 'Feste Gebühr und Anteil' + surcharge_fixed_amount: + label: 'Fester Zahlungszuschlag' + klarna_tooltip: "Geben Sie die zusätzlichen Kosten für eine Klarna-Zahlung mit einem Höchstbetrag von 1,95 € ein. Höhere Beträge werden nicht akzeptiert." + tooltip: "Zusätzliche Kosten die für Zahlungsvorgänge anfallen und als fester Betrag in der Standardwährung des Shops berechnet werden." + surcharge_percentage: + label: 'Anteiliger Zahlungszuschlag' + klarna_tooltip: "Geben Sie die zusätzlichen Kosten für eine Klarna-Zahlung mit einem Höchstbetrag von 1,95 € ein. Höhere Beträge werden nicht akzeptiert." + tooltip: "Zusätzliche Kosten die für Zahlungsvorgänge anfallen und als Anteil am Gesamtwert des Einkaufswagens berechnet werden." + surcharge_limit: + label: 'Maximaler Zahlungszuschlag' + klarna_tooltip: "Geben Sie die zusätzlichen Kosten für eine Klarna-Zahlung mit einem Höchstbetrag von 1,95 € ein. Höhere Beträge werden nicht akzeptiert." + tooltip: "Maximaler Betrag eines Zahlungszuschlags der berechnet werden kann (in der Standardwährung des Shops)." mollie_components: label: 'Mollie Components verwenden' tooltip: 'Erfahren Sie mehr über Mollie-Komponenten und wie sie Ihre Umsatzquote steigern' + single_click_payment: + label: 'Ein-Klick-Zahlungen verwenden' + tooltip: 'Erfahren Sie mehr über Ein-Klick-Zahlungen und wie sie Ihre Umsatzquote steigern.' + single_click_payment_approval_text: + label: 'Bestätigungstext für Ein-Klick-Zahlungen' + tooltip: 'Legen Sie ein Label für die Bestätigung für Ein-Klick-Zahlungen fest.' + value: 'Kreditkartendaten für zukünftige Einkäufe hinterlegen' + single_click_payment_description: + label: 'Beschreibung für Ein-Klick-Zahlungen' + tooltip: 'Legen Sie einen Text fest der angezeigt wird wenn Kunden die Ein-Klick-Zahlung wählen.' + value: 'YSie haben Ihre Kartendaten bereits hinterlegt. Sie werden zu Mollie weitergeleitet.' issuer_list: label: 'Issuer List Style' tooltip: 'Choose the style in which issuer list will be displayed on checkout.' diff --git a/Resources/translations/messages.de_DE.yml b/Resources/translations/messages.de_DE.yml index 093b0da..2e5f1e0 100644 --- a/Resources/translations/messages.de_DE.yml +++ b/Resources/translations/messages.de_DE.yml @@ -39,6 +39,7 @@ mollie: cardNumber: 'Kreditkartennummer' expiryDate: 'MM/JJ' verificationCode: 'CVV' + useSavedCreditCardText: 'Hinterlegte Kreditkartendaten verwenden' config: authorization: label: 'Befugnis' @@ -93,9 +94,39 @@ mollie: Verwenden Sie die neue Auftrags-API-Plattform, um mehr Einblicke in die Bestellungen zu erhalten. Read more.' option.payment_api.label: 'Zahlungs-API' option.order_api.label: 'Auftrags-API' + payment_surcharge: + label: 'Zahlungszuschlag' + tooltip: 'Wählen Sie einen Zuschlagstyp aus.' + option.no_fee.label: 'Keine Gebühr' + option.fixed_fee.label: 'Feste Gebühr' + option.percentage.label: 'Anteil' + option.fixed_fee_and_percentage.label: 'Feste Gebühr und Anteil' + surcharge_fixed_amount: + label: 'Fester Zahlungszuschlag' + klarna_tooltip: "Geben Sie die zusätzlichen Kosten für eine Klarna-Zahlung mit einem Höchstbetrag von 1,95 € ein. Höhere Beträge werden nicht akzeptiert." + tooltip: "Zusätzliche Kosten die für Zahlungsvorgänge anfallen und als fester Betrag in der Standardwährung des Shops berechnet werden." + surcharge_percentage: + label: 'Anteiliger Zahlungszuschlag' + klarna_tooltip: "Geben Sie die zusätzlichen Kosten für eine Klarna-Zahlung mit einem Höchstbetrag von 1,95 € ein. Höhere Beträge werden nicht akzeptiert." + tooltip: "Zusätzliche Kosten die für Zahlungsvorgänge anfallen und als Anteil am Gesamtwert des Einkaufswagens berechnet werden." + surcharge_limit: + label: 'Maximaler Zahlungszuschlag' + klarna_tooltip: "Geben Sie die zusätzlichen Kosten für eine Klarna-Zahlung mit einem Höchstbetrag von 1,95 € ein. Höhere Beträge werden nicht akzeptiert." + tooltip: "Maximaler Betrag eines Zahlungszuschlags der berechnet werden kann (in der Standardwährung des Shops)." mollie_components: label: 'Mollie Components verwenden' tooltip: 'Erfahren Sie mehr über Mollie-Komponenten und wie sie Ihre Umsatzquote steigern' + single_click_payment: + label: 'Ein-Klick-Zahlungen verwenden' + tooltip: 'Erfahren Sie mehr über Ein-Klick-Zahlungen und wie sie Ihre Umsatzquote steigern.' + single_click_payment_approval_text: + label: 'Bestätigungstext für Ein-Klick-Zahlungen' + tooltip: 'Legen Sie ein Label für die Bestätigung für Ein-Klick-Zahlungen fest.' + value: 'Kreditkartendaten für zukünftige Einkäufe hinterlegen' + single_click_payment_description: + label: 'Beschreibung für Ein-Klick-Zahlungen' + tooltip: 'Legen Sie einen Text fest der angezeigt wird wenn Kunden die Ein-Klick-Zahlung wählen.' + value: 'YSie haben Ihre Kartendaten bereits hinterlegt. Sie werden zu Mollie weitergeleitet.' issuer_list: label: 'Issuer List Style' tooltip: 'Choose the style in which issuer list will be displayed on checkout.' diff --git a/Resources/translations/messages.en.yml b/Resources/translations/messages.en.yml index 0f8b69c..83abcf8 100644 --- a/Resources/translations/messages.en.yml +++ b/Resources/translations/messages.en.yml @@ -39,6 +39,7 @@ mollie: cardNumber: 'Card number' expiryDate: 'Expiry date' verificationCode: 'CVC/CVV' + useSavedCreditCardText: 'Use saved credit card information' config: authorization: label: 'Authorization' @@ -93,18 +94,44 @@ mollie: Use the new Order API Platform and get additional insights into the orders. Read more.' option.payment_api.label: 'Payment API' option.order_api.label: 'Orders API' + payment_surcharge: + label: 'Payment surcharge' + tooltip: 'Please select a surcharge type.' + option.no_fee.label: 'No fee' + option.fixed_fee.label: 'Fixed fee' + option.percentage.label: 'Percentage' + option.fixed_fee_and_percentage.label: 'Fixed fee and percentage' + surcharge_fixed_amount: + label: 'Payment surcharge fixed amount' + klarna_tooltip: "Enter the extra costs for a Klarna payment with a maximum of € 1.95. The greater amounts won't be accepted." + tooltip: "Extra cost to be charged to the customer for payment transactions defined as a fixed amount in default store currency." + surcharge_percentage: + label: 'Payment surcharge percentage' + klarna_tooltip: "Enter the extra costs for a Klarna payment with a maximum of € 1.95. The greater amounts won't be accepted." + tooltip: "Extra cost to be charged to the customer for payment transactions defined as a percentage of the cart subtotal." + surcharge_limit: + label: 'Payment surcharge limit' + klarna_tooltip: "Enter the extra costs for a Klarna payment with a maximum of € 1.95. The greater amounts won't be accepted." + tooltip: "Maximum amount of payment surcharge that should be charged to the customer (in default store currency)." mollie_components: label: 'Use Mollie Components' tooltip: 'Read more about Mollie Components and how it improves your conversion' + single_click_payment: + label: 'Use Single Click Payment' + tooltip: 'Read more about Single Click Payments and how it improves your conversion.' + single_click_payment_approval_text: + label: 'Single Click Payment Approval Text' + tooltip: 'Please define a label for the Single Click approval.' + value: 'Save credit card for future purchases' + single_click_payment_description: + label: 'Single Click Payment Description' + tooltip: 'Please define text that will be displayed when the customer selects Single Click payment.' + value: "You have previously saved your card. You'll be redirected to Mollie." issuer_list: label: 'Issuer List Style' tooltip: 'Choose the style in which issuer list will be displayed on checkout.' option.dropdown: "Dropdown" option.list: "List with the images" - surcharge: - label: 'Surcharge' - klarna_tooltip: "Enter the extra costs for a Klarna payment with a maximum of € 1.95. The greater amounts won't be accepted." - tooltip: "Enter the extra costs for a payment." orderExpiryDays: label: 'Days To Expire' tooltip: 'How many days before orders for this method becomes expired? Leave empty to use default expiration (28 days)' diff --git a/Resources/translations/messages.fr.yml b/Resources/translations/messages.fr.yml index 9a4b4cd..c4c6a45 100644 --- a/Resources/translations/messages.fr.yml +++ b/Resources/translations/messages.fr.yml @@ -39,6 +39,7 @@ mollie: cardNumber: 'Numero de carte de credit' expiryDate: 'MM/AA' verificationCode: 'CVV' + useSavedCreditCardText: 'Utilisez les informations de votre carte' config: authorization: label: 'Autorisation' @@ -93,9 +94,39 @@ mollie: Utilisez la nouvelle plateforme d'API de commande et obtenez plus d'informations sur les commandes. Read more." option.payment_api.label: 'API Paiements' option.order_api.label: 'API Commandes' + payment_surcharge: + label: 'Majoration de paiement' + tooltip: 'Veuillez sélectionner un type de majoration.' + option.no_fee.label: 'Aucuns frais' + option.fixed_fee.label: 'Frais fixes' + option.percentage.label: 'Pourcentage' + option.fixed_fee_and_percentage.label: 'Frais fixes et pourcentage' + surcharge_fixed_amount: + label: 'Montant fixe pour majoration de paiement' + klarna_tooltip: "Entrez le coût additionnel pour un paiement Klarna, avec un maximum de 1,95 €. Les montants supérieurs ne seront pas acceptés." + tooltip: "Coût supplémentaire à facturer au client pour les opérations de paiement défini comme un montant fixe dans la devise du magasin par défaut." + surcharge_percentage: + label: 'Pourcentage de majoration de paiement' + klarna_tooltip: "Entrez le coût additionnel pour un paiement Klarna, avec un maximum de 1,95 €. Les montants supérieurs ne seront pas acceptés." + tooltip: "Coût supplémentaire à facturer au client pour les opérations de paiement défini comme un pourcentage du sous-total du panier." + surcharge_limit: + label: 'Limite de majoration de paiement' + klarna_tooltip: "Entrez le coût additionnel pour un paiement Klarna, avec un maximum de 1,95 €. Les montants supérieurs ne seront pas acceptés." + tooltip: "Montant maximum de la majoration de paiement qui doit être facturée au client (dans la devise du magasin par défaut)." mollie_components: label: 'Utiliser les composants Mollie' tooltip: 'Vous pouvez lire plus sur Mollie Components et la manière dont il améliore vos transactions' + single_click_payment: + label: 'Utiliser des paiements Single Click' + tooltip: 'En savoir plus sur les paiements Single Click et la manière dont il améliore votre conversion.' + single_click_payment_approval_text: + label: 'Texte d’approbation des paiements Single Click' + tooltip: 'Veuillez définir une étiquette pour l’approbation Single Click.' + value: 'Enregistrer carte de crédit pour achats ultérieurs' + single_click_payment_description: + label: 'Description paiements Single Click' + tooltip: 'Veuillez définir le texte qui sera affiché lorsque le client sélectionne le paiement Single Click.' + value: 'Vous avez précédemment enregistrer votre carte. Vous allez être redirigé vers Mollie.' issuer_list: label: "Style de la liste d'émetteurs" tooltip: 'Choose the style in which issuer list will be displayed on checkout.' diff --git a/Resources/translations/messages.fr_FR.yml b/Resources/translations/messages.fr_FR.yml index 9a4b4cd..c4c6a45 100644 --- a/Resources/translations/messages.fr_FR.yml +++ b/Resources/translations/messages.fr_FR.yml @@ -39,6 +39,7 @@ mollie: cardNumber: 'Numero de carte de credit' expiryDate: 'MM/AA' verificationCode: 'CVV' + useSavedCreditCardText: 'Utilisez les informations de votre carte' config: authorization: label: 'Autorisation' @@ -93,9 +94,39 @@ mollie: Utilisez la nouvelle plateforme d'API de commande et obtenez plus d'informations sur les commandes. Read more." option.payment_api.label: 'API Paiements' option.order_api.label: 'API Commandes' + payment_surcharge: + label: 'Majoration de paiement' + tooltip: 'Veuillez sélectionner un type de majoration.' + option.no_fee.label: 'Aucuns frais' + option.fixed_fee.label: 'Frais fixes' + option.percentage.label: 'Pourcentage' + option.fixed_fee_and_percentage.label: 'Frais fixes et pourcentage' + surcharge_fixed_amount: + label: 'Montant fixe pour majoration de paiement' + klarna_tooltip: "Entrez le coût additionnel pour un paiement Klarna, avec un maximum de 1,95 €. Les montants supérieurs ne seront pas acceptés." + tooltip: "Coût supplémentaire à facturer au client pour les opérations de paiement défini comme un montant fixe dans la devise du magasin par défaut." + surcharge_percentage: + label: 'Pourcentage de majoration de paiement' + klarna_tooltip: "Entrez le coût additionnel pour un paiement Klarna, avec un maximum de 1,95 €. Les montants supérieurs ne seront pas acceptés." + tooltip: "Coût supplémentaire à facturer au client pour les opérations de paiement défini comme un pourcentage du sous-total du panier." + surcharge_limit: + label: 'Limite de majoration de paiement' + klarna_tooltip: "Entrez le coût additionnel pour un paiement Klarna, avec un maximum de 1,95 €. Les montants supérieurs ne seront pas acceptés." + tooltip: "Montant maximum de la majoration de paiement qui doit être facturée au client (dans la devise du magasin par défaut)." mollie_components: label: 'Utiliser les composants Mollie' tooltip: 'Vous pouvez lire plus sur Mollie Components et la manière dont il améliore vos transactions' + single_click_payment: + label: 'Utiliser des paiements Single Click' + tooltip: 'En savoir plus sur les paiements Single Click et la manière dont il améliore votre conversion.' + single_click_payment_approval_text: + label: 'Texte d’approbation des paiements Single Click' + tooltip: 'Veuillez définir une étiquette pour l’approbation Single Click.' + value: 'Enregistrer carte de crédit pour achats ultérieurs' + single_click_payment_description: + label: 'Description paiements Single Click' + tooltip: 'Veuillez définir le texte qui sera affiché lorsque le client sélectionne le paiement Single Click.' + value: 'Vous avez précédemment enregistrer votre carte. Vous allez être redirigé vers Mollie.' issuer_list: label: "Style de la liste d'émetteurs" tooltip: 'Choose the style in which issuer list will be displayed on checkout.' diff --git a/Resources/translations/messages.nl.yml b/Resources/translations/messages.nl.yml index 6f81819..c49b1d3 100644 --- a/Resources/translations/messages.nl.yml +++ b/Resources/translations/messages.nl.yml @@ -39,6 +39,7 @@ mollie: cardNumber: 'Creditcardnummer' expiryDate: 'MM/JJ' verificationCode: 'CVV' + useSavedCreditCardText: 'Gebruik opgeslagen creditcardinformatie' config: authorization: label: 'Autorisatie' @@ -93,9 +94,39 @@ mollie: Gebruik het nieuwe Order API Platform en krijg extra inzichten in de bestellingen. Lees meer.' option.payment_api.label: 'Payment API' option.order_api.label: 'Orders API' + payment_surcharge: + label: 'Betalingstoeslag' + tooltip: 'Selecteer het type toeslag.' + option.no_fee.label: 'Geen kosten' + option.fixed_fee.label: 'Vaste kosten' + option.percentage.label: 'Percentage' + option.fixed_fee_and_percentage.label: 'Vaste kosten en percentage' + surcharge_fixed_amount: + label: 'Betalingstoeslag vast bedrag' + klarna_tooltip: "Vul de extra kosten voor een Klarna-betaling in, met een maximum van € 1,95. Hogere bedragen worden niet geaccepteerd." + tooltip: "Extra kosten die aan de klant worden doorberekend voor betalingstransacties bepaald als een vast bedrag in standaard winkelvaluta." + surcharge_percentage: + label: 'Betalingstoeslag percentage' + klarna_tooltip: "Vul de extra kosten voor een Klarna-betaling in, met een maximum van € 1,95. Hogere bedragen worden niet geaccepteerd." + tooltip: "Extra kosten die aan de klant worden doorberekend voor betalingstransacties bepaald als een percentage van het subtotaal van de winkelwagen." + surcharge_limit: + label: 'Betalingstoeslag limiet' + klarna_tooltip: "Vul de extra kosten voor een Klarna-betaling in, met een maximum van € 1,95. Hogere bedragen worden niet geaccepteerd." + tooltip: "Maximumbedrag van de betalingstoeslag die aan de klant moet worden doorberekend (in standaard winkelvaluta)." mollie_components: label: 'Gebruik Mollie Components' tooltip: 'Lees meer over Mollie componentenen hoe het uw conversie kan verbeteren' + single_click_payment: + label: 'Gebruik betalen met één klik' + tooltip: 'Lees meer over betalen met één klik en hoe het uw conversie verbetert.' + single_click_payment_approval_text: + label: 'Toestemmingstekst betalen met één klik' + tooltip: 'Bepaal een label voor de toestemming voor betalen met één klik.' + value: 'Bewaar creditcard voor toekomstige aankopen' + single_click_payment_description: + label: 'Beschrijving betalen met één klik' + tooltip: 'Bepaal de tekst die wordt weergegeven wanneer de klant betalen met één klik selecteert.' + value: 'U heeft uw kaart eerder opgeslagen. U wordt doorgestuurd naar Mollie.' issuer_list: label: 'Issuer List Style' tooltip: 'Choose the style in which issuer list will be displayed on checkout.' diff --git a/Resources/translations/messages.nl_NL.yml b/Resources/translations/messages.nl_NL.yml index 6f81819..c49b1d3 100644 --- a/Resources/translations/messages.nl_NL.yml +++ b/Resources/translations/messages.nl_NL.yml @@ -39,6 +39,7 @@ mollie: cardNumber: 'Creditcardnummer' expiryDate: 'MM/JJ' verificationCode: 'CVV' + useSavedCreditCardText: 'Gebruik opgeslagen creditcardinformatie' config: authorization: label: 'Autorisatie' @@ -93,9 +94,39 @@ mollie: Gebruik het nieuwe Order API Platform en krijg extra inzichten in de bestellingen. Lees meer.' option.payment_api.label: 'Payment API' option.order_api.label: 'Orders API' + payment_surcharge: + label: 'Betalingstoeslag' + tooltip: 'Selecteer het type toeslag.' + option.no_fee.label: 'Geen kosten' + option.fixed_fee.label: 'Vaste kosten' + option.percentage.label: 'Percentage' + option.fixed_fee_and_percentage.label: 'Vaste kosten en percentage' + surcharge_fixed_amount: + label: 'Betalingstoeslag vast bedrag' + klarna_tooltip: "Vul de extra kosten voor een Klarna-betaling in, met een maximum van € 1,95. Hogere bedragen worden niet geaccepteerd." + tooltip: "Extra kosten die aan de klant worden doorberekend voor betalingstransacties bepaald als een vast bedrag in standaard winkelvaluta." + surcharge_percentage: + label: 'Betalingstoeslag percentage' + klarna_tooltip: "Vul de extra kosten voor een Klarna-betaling in, met een maximum van € 1,95. Hogere bedragen worden niet geaccepteerd." + tooltip: "Extra kosten die aan de klant worden doorberekend voor betalingstransacties bepaald als een percentage van het subtotaal van de winkelwagen." + surcharge_limit: + label: 'Betalingstoeslag limiet' + klarna_tooltip: "Vul de extra kosten voor een Klarna-betaling in, met een maximum van € 1,95. Hogere bedragen worden niet geaccepteerd." + tooltip: "Maximumbedrag van de betalingstoeslag die aan de klant moet worden doorberekend (in standaard winkelvaluta)." mollie_components: label: 'Gebruik Mollie Components' tooltip: 'Lees meer over Mollie componentenen hoe het uw conversie kan verbeteren' + single_click_payment: + label: 'Gebruik betalen met één klik' + tooltip: 'Lees meer over betalen met één klik en hoe het uw conversie verbetert.' + single_click_payment_approval_text: + label: 'Toestemmingstekst betalen met één klik' + tooltip: 'Bepaal een label voor de toestemming voor betalen met één klik.' + value: 'Bewaar creditcard voor toekomstige aankopen' + single_click_payment_description: + label: 'Beschrijving betalen met één klik' + tooltip: 'Bepaal de tekst die wordt weergegeven wanneer de klant betalen met één klik selecteert.' + value: 'U heeft uw kaart eerder opgeslagen. U wordt doorgestuurd naar Mollie.' issuer_list: label: 'Issuer List Style' tooltip: 'Choose the style in which issuer list will be displayed on checkout.' diff --git a/Resources/views/Form/payment-methods.html.twig b/Resources/views/Form/payment-methods.html.twig index f3d2a21..be7ef0e 100755 --- a/Resources/views/Form/payment-methods.html.twig +++ b/Resources/views/Form/payment-methods.html.twig @@ -48,12 +48,24 @@ - {% if paymentMethod.method is defined %} - {{ form_row(paymentMethod.method) }} + {% if paymentMethod.surchargeType is defined %} + {{ form_row(paymentMethod.surchargeType) }} + {% endif %} + + {% if paymentMethod.surchargeFixedAmount is defined %} + {{ form_row(paymentMethod.surchargeFixedAmount, { 'attr': {'class': 'mollie-surcharge-fixed-amount'}}) }} + {% endif %} + + {% if paymentMethod.surchargePercentage is defined %} + {{ form_row(paymentMethod.surchargePercentage, { 'attr': {'class': 'mollie-surcharge-percentage'} }) }} {% endif %} - {% if paymentMethod.surcharge is defined %} - {{ form_row(paymentMethod.surcharge) }} + {% if paymentMethod.surchargeLimit is defined %} + {{ form_row(paymentMethod.surchargeLimit, { 'attr': {'class': 'mollie-surcharge-limit'} }) }} + {% endif %} + + {% if paymentMethod.method is defined %} + {{ form_row(paymentMethod.method, { 'attr': {'class': 'mollie-transaction-description'} }) }} {% endif %} {% if paymentMethod.transactionDescriptions is defined %} @@ -68,6 +80,23 @@ {{ form_row(paymentMethod.paymentExpiryDays, { 'attr': {'class': 'mollie-payment-expiry-days'} }) }} {% endif %} + {% if paymentMethod.mollieComponents is defined %} + {{ form_row(paymentMethod.mollieComponents, { 'attr': {'class': 'mollie-payment-mollie-components'} }) }} + {% endif %} + + {% if paymentMethod.singleClickPayment is defined %} + {{ form_row(paymentMethod.singleClickPayment, { 'attr': {'class': 'mollie-payment-single-click-status'} }) }} + {% endif %} + + {% if paymentMethod.singleClickPaymentApprovalText is defined %} + {{ form_row(paymentMethod.singleClickPaymentApprovalText, { 'attr': {'class': 'mollie-payment-single-click-approval-text'} }) }} + {% endif %} + + {% if paymentMethod.singleClickPaymentDescription is defined %} + {{ form_row(paymentMethod.singleClickPaymentDescription, { 'attr': {'class': 'mollie-payment-single-click-description'} }) }} + {% endif %} + + {{ form_rest(paymentMethod) }} diff --git a/Resources/views/layouts/default/imports/oro_payment_method_options/layout.html.twig b/Resources/views/layouts/default/imports/oro_payment_method_options/layout.html.twig index 19084b1..ca2cf46 100755 --- a/Resources/views/layouts/default/imports/oro_payment_method_options/layout.html.twig +++ b/Resources/views/layouts/default/imports/oro_payment_method_options/layout.html.twig @@ -1,7 +1,7 @@ {% block _payment_methods_mollie_payment_widget %}