Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions Block/Adminhtml/Config/LegacyAuthInfo.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);

namespace Payplug\Payments\Block\Adminhtml\Config;

use Magento\Backend\Block\Template\Context;
use Magento\Backend\Block\Widget\Button;
use Magento\Config\Block\System\Config\Form\Field;
use Magento\Framework\Data\Form\Element\AbstractElement;
use Magento\Store\Model\ScopeInterface;
use Payplug\Payments\Helper\Config;

class LegacyAuthInfo extends Field
{
public function __construct(
Context $context,
private Config $helper,
array $data = []
) {
parent::__construct($context, $data);
}

protected function _getElementHtml(AbstractElement $element): string
{
$isLegacyConnected = $this->helper->isLegacyConnected(ScopeInterface::SCOPE_WEBSITE, (int)$this->_request->getParam('website'));
$isOauthConnected = $this->helper->isOauthConnected(ScopeInterface::SCOPE_WEBSITE, (int)$this->_request->getParam('website'));

if ($isLegacyConnected) {
$message = __('Connected with <strong>%1</strong>', $this->helper->getConfigValue('email'));
} elseif ($isOauthConnected) {
$message = __('Connected with OAuth2 Authentication');
} else {
$message = __('Not connected');
}

return $message->render();
}
}
30 changes: 30 additions & 0 deletions Block/Adminhtml/Config/LegacyLogin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace Payplug\Payments\Block\Adminhtml\Config;

use Magento\Backend\Block\Template\Context;
use Magento\Backend\Block\Widget\Button;
use Magento\Config\Block\System\Config\Form\Field;
use Magento\Framework\Data\Form\Element\AbstractElement;
use Magento\Store\Model\ScopeInterface;
use Payplug\Payments\Helper\Config;

class LegacyLogin extends Field
{
protected function _getElementHtml(AbstractElement $element): string
{
/** @var Button $buttonBlock */
$buttonBlock = $this->getForm()->getLayout()->createBlock(Button::class);
$websiteId = $this->getRequest()->getParam('website');

$data = [
'label' => $websiteId ? __('Connect to Payplug for this website') : __('Connect to Payplug'),
'onclick' => 'document.querySelector("#save").click();',
'class' => 'action-primary'
];

return $buttonBlock->setData($data)->toHtml();
}
}
14 changes: 7 additions & 7 deletions Block/Adminhtml/Config/Login.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ public function render(\Magento\Framework\Data\Form\Element\AbstractElement $ele

$this->helper->initScopeData();

$connected = $this->helper->isConnected(ScopeInterface::SCOPE_WEBSITE, $this->request->getParam('website'));
$legacyConnected = $this->helper->isLegacyConnected(ScopeInterface::SCOPE_WEBSITE, $this->request->getParam('website'));
$oauthConnected = $this->helper->isOauthConnected(ScopeInterface::SCOPE_WEBSITE, $this->request->getParam('website'));
$isVerified = $this->helper->getConfigValue('verified', ScopeInterface::SCOPE_WEBSITE, $this->request->getParam('website'));

$connexionFields = ['payplug_payments_general_email'];
$connexionFieldsWithPwd = ['payplug_payments_general_email', 'payplug_payments_general_pwd'];
$connexionFields = ['payplug_payments_auth_email', 'payplug_payments_auth_connect'];
$connexionFieldsWithPwd = ['payplug_payments_auth_email', 'payplug_payments_auth_pwd', 'payplug_payments_auth_connect'];

$disconnectionFields = ['payplug_payments_general_account_details'];
$disconnectionFields = ['payplug_payments_auth_account_details'];

$elements = '';
foreach ($element->getElements() as $field) {
Expand All @@ -67,7 +67,7 @@ public function render(\Magento\Framework\Data\Form\Element\AbstractElement $ele
}
}

if ($connected) {
if ($legacyConnected) {
if (in_array($field->getId(), $connexionFields)) {
continue;
}
Expand All @@ -88,14 +88,14 @@ public function render(\Magento\Framework\Data\Form\Element\AbstractElement $ele
$extraElements = '';

$extraElements .= '<input id="payplug_payments_is_connected" type="hidden" name="payplug_payments_is_connected"
value="'.(int)$connected.'" />';
value="'.(int)$legacyConnected.'" />';

$extraElements .= '<input id="payplug_payments_is_verified" type="hidden" name="payplug_payments_is_verified"
value="'.(int)$isVerified.'" />';

if ($this->helper->getConfigScope() == ScopeInterface::SCOPE_WEBSITES) {
$input = 'payplug_payments_prevent_default';
if (!$connected) {
if (!$legacyConnected) {
$input = 'payplug_payments_can_override_default';
}

Expand Down
3 changes: 1 addition & 2 deletions Block/Adminhtml/Config/Logout.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,13 @@ protected function _getElementHtml(AbstractElement $element): string
/** @var Button $buttonBlock */
$buttonBlock = $this->getForm()->getLayout()->createBlock(Button::class);

$html = '<p>' . $this->helper->getConfigValue('email') . '</p>';
$data = [
'id' => 'payplug_payments_disconnectUrl',
'label' => $element->getLabel(),
'onclick' => "setLocation('" . $this->getButtonUrl() . "')"
];

$html .= $buttonBlock->setData($data)->toHtml();
$html = $buttonBlock->setData($data)->toHtml();

return $html;
}
Expand Down
2 changes: 1 addition & 1 deletion Block/Adminhtml/Config/Oauth2Logout.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ private function getAccessTokenData(): ?array

private function getCurrentWebsite(): ?int
{
return $this->getRequest()->getParam('website') ?: null;
return (int)$this->getRequest()->getParam('website') ?: null;
}

private function isDeveloperMode(): bool
Expand Down
2 changes: 2 additions & 0 deletions Block/Info.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ protected function buildPaymentDetails(Payment $payment, OrderInterface $order):
$status = __('Partially Refunded');
} elseif ($payment->is_paid) {
$status = __('Paid');
} elseif ($payment->authorization->authorized_at) {
$status = __('Authorized');
}

$amount = $order->getOrderCurrency()->formatPrecision((float)($payment->amount / 100), 2, [], false, false);
Expand Down
47 changes: 47 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,53 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [4.6.2](https://github.com/payplug/payplug-magento2/releases/tag/v4.6.2) - 2026-01-26

### Features

- Fix exception when selecting PayPlug payment method in checkout (e.g., Hyvä Checkout) (MAG-590)

**[View diff](https://github.com/payplug/payplug-magento2/compare/v4.6.1...v4.6.2)**

### Fixed

- Fix exception when selecting PayPlug payment method in checkout (e.g., Hyvä Checkout) [#339](https://github.com/payplug/payplug-magento2/pull/339)

## [4.6.1](https://github.com/payplug/payplug-magento2/releases/tag/v4.6.1) - 2025-12-24

### Features

- Fix Cron auto-capture failing on carts with missing info (MAG-562)
- Fix OAUTH2 login UI with Legacy panel causing confusion (MAG-564)
- Fix error when configuring Payplug on a specific website scope (MAG-574)
- Improve ACL permission granularity for the Payplug admin section (MAG-575)
- Fix OAuth2 login redirection blank page during Unified Auth process (MAG-578)
- Anonymize personal data logged by Payplug module (MAG-581)
- Enable REDIRECT mode for integrated payment 3DS validation (MAG-584)
- Fix unclear error message in Legacy connection mode (MAG-585)
- Fix PayPlug payment status mismatch in Authorization-only mode (MAG-593)
- Fix module 4.6.0 incompatibility with Magento 2.4.8-p3 (MAG-598)
- Fix forced captures attempted 10 minutes after authorization expiration (MAG-599)

**[View diff](https://github.com/payplug/payplug-magento2/compare/v4.6.0...v4.6.1)**

### Changed

- Improve ACL permission granularity for the Payplug admin section (MAG-575) [#330](https://github.com/payplug/payplug-magento2/pull/330)
- Anonymize personal data logged by Payplug module (MAG-581) [#329](https://github.com/payplug/payplug-magento2/pull/329)
- Enable REDIRECT mode for integrated payment 3DS validation (MAG-584) [#327](https://github.com/payplug/payplug-magento2/pull/327)

### Fixed

- Fix Cron auto-capture failing on carts with missing info [#335](https://github.com/payplug/payplug-magento2/pull/335)
- Fix OAUTH2 login UI with Legacy panel causing confusion [#334](https://github.com/payplug/payplug-magento2/pull/334)
- Fix error when configuring Payplug on a specific website scope [#317](https://github.com/payplug/payplug-magento2/pull/317)
- Fix OAuth2 login redirection blank page during Unified Auth process [#328](https://github.com/payplug/payplug-magento2/pull/328)
- Fix unclear error message in Legacy connection mode [#326](https://github.com/payplug/payplug-magento2/pull/326)
- Fix PayPlug payment status mismatch in Authorization-only mode (MAG-593) [#337](https://github.com/payplug/payplug-magento2/pull/337)
- Fix module 4.6.0 incompatibility with Magento 2.4.8-p3 [#340](https://github.com/payplug/payplug-magento2/pull/340)
- Fix forced captures attempted 10 minutes after authorization expiration [#341](https://github.com/payplug/payplug-magento2/pull/341)

## [4.6.0](https://github.com/payplug/payplug-magento2/releases/tag/v4.6.0) - 2025-11-17

> **WARNING**
Expand Down
2 changes: 2 additions & 0 deletions Controller/Adminhtml/Config/Logout.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

class Logout extends Action
{
public const ADMIN_RESOURCE = 'Payplug_Payments::general';

public function __construct(
Context $context,
private Config $helper,
Expand Down
7 changes: 6 additions & 1 deletion Controller/Adminhtml/Config/Oauth2FetchAuthCode.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Payplug\Payments\Controller\Adminhtml\Config;

use Laminas\Http\Response;
use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Backend\Model\Auth\Session as AdminAuthSession;
Expand All @@ -19,6 +20,7 @@

class Oauth2FetchAuthCode extends Action implements HttpGetActionInterface
{
public const ADMIN_RESOURCE = 'Payplug_Payments::general';
public const OAUTH_CONFIG_FETCH_DATA = 'payplug_payments_admin/config/oauth2FetchClientData';
public const OAUTH_CONFIG_FETCH_AUTH = 'payplug_payments_admin/config/oauth2FetchAuthCode';

Expand Down Expand Up @@ -56,7 +58,10 @@ public function execute(): ResultInterface
try {
PayplugAuthentication::initiateOAuth($clientId, $callbackUrl, $codeVerifier);

return $this->rawFactory->create();
$result = $this->rawFactory->create();
$result->setHttpResponseCode(Response::STATUS_CODE_302);

return $result;
} catch (ConfigurationException $e) {
$this->logger->error($e->getMessage());
$this->messageManager->addErrorMessage(__('Could not retrieve Auth Code from Payplug Portal'));
Expand Down
1 change: 1 addition & 0 deletions Controller/Adminhtml/Config/Oauth2FetchClientData.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

class Oauth2FetchClientData extends Action implements HttpGetActionInterface
{
public const ADMIN_RESOURCE = 'Payplug_Payments::general';
public const PAYPLUG_OAUTH2_AUTHENTICATION_CONTEXT_DATA = 'payplug_oauth2_params';
public const PAYPLUG_OAUTH2_BASE_ENVIRONMENT_MODE = 'test';
public const PAYPLUG_OAUTH2_BASE_PAYMENT_PAGE_MODE = 'integrated';
Expand Down
2 changes: 2 additions & 0 deletions Controller/Adminhtml/Config/Oauth2Login.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

class Oauth2Login extends Action implements HttpGetActionInterface
{
public const ADMIN_RESOURCE = 'Payplug_Payments::general';

public function __construct(
private readonly RedirectFactory $redirectFactory,
private readonly UrlInterface $urlBuilder,
Expand Down
2 changes: 2 additions & 0 deletions Controller/Adminhtml/Config/Oauth2Logout.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

class Oauth2Logout extends Action implements HttpGetActionInterface
{
public const ADMIN_RESOURCE = 'Payplug_Payments::general';

public function __construct(
private readonly RedirectFactory $redirectFactory,
private readonly RequestInterface $request,
Expand Down
6 changes: 5 additions & 1 deletion Controller/Payment/Ipn.php
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,12 @@ private function processPayment(Raw $response, Payment $resource): void
$this->fetchTransactionInformationHandler->saveCustomerCard($payment, $standardDeferredQuote->getCustomerId(), $standardDeferredQuote->getStoreId());
}

$anomymizedPaymentObject = clone $payment;
$anomymizedPaymentObject->__set('billing', null);
$anomymizedPaymentObject->__set('shipping', null);

$this->logger->info('Gathering payment details...', [
'details' => var_export($payment, true),
'details' => var_export($anomymizedPaymentObject, true),
]);
$this->logger->info('Order state current: ' . $order->getState());

Expand Down
22 changes: 16 additions & 6 deletions Cron/AutoCaptureDeferredPayments.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace Payplug\Payments\Cron;

use DateTime;
use DateMalformedStringException;
use Exception;
use Magento\Framework\Api\SearchCriteriaBuilder;
use Magento\Framework\App\Area;
Expand Down Expand Up @@ -48,6 +48,8 @@ public function __construct(
/**
* Loop through all pending deferred payments, and force to capture them
* if the time elapsed since the order creation exceed 6 days
*
* @throws DateMalformedStringException
*/
public function execute(): void
{
Expand All @@ -56,8 +58,6 @@ public function execute(): void
// All the invoiceable order will populate this array
$orderToInvoiceIds = [];

$currentDay = $this->timezone->date();

// Get all the order payment that are not paid and using the payplug standard deferred (sales_order_payment table)
$searchOrderPaymentCriteria = $this->searchCriteriaBuilder
->addFilter('method', Standard::METHOD_CODE)
Expand All @@ -83,13 +83,23 @@ public function execute(): void
->addFieldToFilter('additional_information', ['like' => '%is_authorized%'])
->getItems();

$deferredPaymentValidationDate = new DateTime();
/** Don't use timezone to perform UTC+0 comparison */
$currentDateTime = $this->timezone->date(null, null, false);
$authorizationValidationDateTime = $this->timezone->date(null, null, false);

// Using the quotePayment additionnal info we filter on the authorization date exceeding or equal to 6 days
foreach ($quotePayments as $quotePayment) {
// Unix timestamp
$authorizedAtTimestamp = $quotePayment->getAdditionalInformation('authorized_at');
$deferredPaymentValidationDate->setTimestamp($authorizedAtTimestamp);
$difference = $currentDay->diff($deferredPaymentValidationDate);

if ($authorizedAtTimestamp === null) {
continue;
}

$authorizationValidationDateTime->setTimestamp($authorizedAtTimestamp);
$authorizationValidationDateTime->modify('-2 hours'); // add tolerance for this time calculation
$difference = $currentDateTime->diff($authorizationValidationDateTime);

if ($difference->days >= AutoCaptureDeferredPayments::FORCED_CAPTURE_DELAY_IN_DAYS) {
// We add the order id to the array of the invoiceables ones
$orderId = $quotePaymentsToOrderPayments[$quotePayment->getQuoteId()];
Expand Down
5 changes: 0 additions & 5 deletions Gateway/Config/PayplugPayment.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@ class PayplugPayment extends Config
{
public function getValue($field, $storeId = null)
{
if ($field === 'order_place_redirect_url') {
// Prevent order email sending when placing the order
return true;
}

if ($field === 'payment_action'
&& parent::getValue($field, $storeId) === MethodInterface::ACTION_AUTHORIZE_CAPTURE
&& $this->getValue('invoice_on_payment', $storeId)
Expand Down
4 changes: 3 additions & 1 deletion Gateway/Response/InstallmentPlan/PaymentHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ public function handle(array $handlingSubject, array $response)

/** @var Payment $payment */
$payment = $paymentDO->getPayment();
$order = $payment->getOrder();
$order->setCanSendNewEmailFlag(false);

$payment->setTransactionId($installmentPlan->id);
$payment->setAdditionalInformation('payment_url', $installmentPlan->hosted_payment->payment_url);
Expand All @@ -65,7 +67,7 @@ public function handle(array $handlingSubject, array $response)

/** @var \Payplug\Payments\Model\Order\InstallmentPlan $orderInstallmentPlan */
$orderInstallmentPlan = $this->installmentPlanFactory->create();
$orderInstallmentPlan->setOrderId($payment->getOrder()->getIncrementId());
$orderInstallmentPlan->setOrderId($order->getIncrementId());
$orderInstallmentPlan->setInstallmentPlanId($installmentPlan->id);
$orderInstallmentPlan->setIsSandbox(!$installmentPlan->is_live);
$orderInstallmentPlan->setStatus(\Payplug\Payments\Model\Order\InstallmentPlan::STATUS_NEW);
Expand Down
7 changes: 5 additions & 2 deletions Gateway/Response/Standard/PaymentHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ public function handle(array $handlingSubject, array $response): void

/** @var Payment $payment */
$payment = $paymentDO->getPayment();
$order = $payment->getOrder();
$order->setCanSendNewEmailFlag(false);

$isPaid = 1;

if (!$payplugPayment->is_paid && $payplugPayment->failure === null) {
Expand All @@ -43,7 +46,7 @@ public function handle(array $handlingSubject, array $response): void

$payment->setAdditionalInformation('is_paid', $isPaid);
$payment->setAdditionalInformation('payplug_payment_id', $payplugPayment->id);
$payment->setAdditionalInformation('quote_id', $payment->getOrder()->getQuoteId());
$payment->setAdditionalInformation('quote_id', $order->getQuoteId());

if ($this->config->isStandardPaymentModeDeferred()) {
$payment->setAdditionalInformation('is_deferred_payment_standard', true);
Expand All @@ -59,7 +62,7 @@ public function handle(array $handlingSubject, array $response): void
$payment->setShouldCloseParentTransaction(false);

$orderPayment = $this->payplugPaymentFactory->create();
$orderPayment->setOrderId($payment->getOrder()->getIncrementId());
$orderPayment->setOrderId($order->getIncrementId());
$orderPayment->setPaymentId($payplugPayment->id);
$orderPayment->setIsSandbox(!$payplugPayment->is_live);

Expand Down
Loading
Loading