Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
b6aab12
Merge pull request #326 from paytrail/master
bartoszkaluzny-solteq Aug 29, 2025
cf7b1d2
Merge pull request #325 from Solteq/SQMAGOPC-658
bartoszkaluzny-solteq Aug 29, 2025
82dc334
SQMAGOPC-618-2025: Disable checkout agreements and admin form key usa…
konrad-konieczny Sep 9, 2025
5223fbe
Merge pull request #327 from Solteq/SQMAGOPC-618-2025
konrad-konieczny Sep 15, 2025
b452274
mftf-automation (#328)
konrad-konieczny Sep 16, 2025
7de704b
mftf-automation (#329)
konrad-konieczny Sep 16, 2025
0233b64
staging: Add workflow_dispatch trigger for MFTF tests in Paytrail con…
konrad-konieczny Sep 25, 2025
56cd00f
staging: Update MFTF workflow to include scheduled cron job
konrad-konieczny Oct 9, 2025
2b0ccf1
staging: Update cron schedule for MFTF tests to run at 20 minutes pas…
konrad-konieczny Oct 9, 2025
b72f323
staging:
konrad-konieczny Oct 9, 2025
287feb9
Merge pull request #331 from Solteq/SQMAGOPC-658
bartoszkaluzny-solteq Nov 4, 2025
3fb0e4e
Merge pull request #332 from Solteq/SQMAGOPC-668
bartoszkaluzny-solteq Nov 6, 2025
013938e
Merge pull request #333 from Solteq/RC_v2.2.12
bartoszkaluzny-solteq Jan 7, 2026
139f319
SQMAGOPC: add code-validation
bartoszkaluzny-solteq Jan 7, 2026
0f5ca32
SQMAGOPC: update composer.json
bartoszkaluzny-solteq Jan 7, 2026
0d49771
Merge pull request #334 from Solteq/SQMAGOPC-672
bartoszkaluzny-solteq Jan 7, 2026
49c5d27
SQMAGOPC: revert v2.2.12 from staging
bartoszkaluzny-solteq Jan 8, 2026
87788c7
Merge branch 'staging' into RC_v2.2.12
bartoszkaluzny-solteq Jan 20, 2026
e61a0d1
Merge pull request #336 from Solteq/RC_v2.2.12
bartoszkaluzny-solteq Jan 20, 2026
49478e3
Merge pull request #337 from Solteq/SQMAGOPC-674
bartoszkaluzny-solteq Jan 20, 2026
d7217b4
Merge pull request #338 from Solteq/SQMAGOPC-675
konrad-konieczny Jan 30, 2026
bae5dc5
Merge pull request #339 from Solteq/SQMAGOPC-675
konrad-konieczny Feb 6, 2026
2c011b2
Merge pull request #340 from Solteq/SQMAGOPC-646
bartoszkaluzny-solteq Feb 24, 2026
9c92ed2
Merge branch 'upstream_master' into staging
bartoszkaluzny-solteq Mar 12, 2026
f70ef28
SQMAGOPC-678: fix deprecated functionality
bartoszkaluzny-solteq Mar 12, 2026
b9cec49
SQMAGOPC-678: fix deprecated string parsing
bartoszkaluzny-solteq Mar 12, 2026
fba3bb9
SQMAGOPC-678: fix code-validation comments
bartoszkaluzny-solteq Mar 12, 2026
bcf396c
SQMAGOPC-677: create observer for order cancellation event
bartoszkaluzny-solteq Mar 18, 2026
970de5a
SQMAGOPC-677: create gatewayCommand for invoice cancellation
bartoszkaluzny-solteq Mar 18, 2026
981be26
SQMAGOPC-677: fix PHPDoc comment
bartoszkaluzny-solteq Mar 18, 2026
b1b0f25
SQMAGOPC-677: add validation for klarna payment method only
bartoszkaluzny-solteq Mar 18, 2026
16da2f8
SQMAGOPC-677: fix code validation comments
bartoszkaluzny-solteq Mar 18, 2026
0b6ee85
Merge pull request #342 from Solteq/SQMAGOPC-678
bartoszkaluzny-solteq Mar 18, 2026
41b2ba8
Merge pull request #343 from Solteq/SQMAGOPC-677
bartoszkaluzny-solteq Mar 19, 2026
3049f63
SQMAGOPC-677: improve observer
bartoszkaluzny-solteq Mar 19, 2026
964cf5f
Merge pull request #344 from Solteq/SQMAGOPC-677
bartoszkaluzny-solteq Mar 19, 2026
eb45a8c
Merge branch 'SQMAGOPC-677' into RC_v2.2.16
bartoszkaluzny-solteq Mar 24, 2026
1ca7259
SQMAGOPC: update versions to 2.2.16
bartoszkaluzny-solteq Mar 24, 2026
01f6ced
SQMAGOPC-679: remove unnecessary DI configuration
bartoszkaluzny-solteq Mar 26, 2026
7a419c1
Merge branch 'SQMAGOPC-679' into RC_v2.2.16
bartoszkaluzny-solteq Apr 7, 2026
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
Binary file added .DS_Store
Binary file not shown.
84 changes: 84 additions & 0 deletions .github/workflows/code-validation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
name: Run code validation checks
on:
pull_request:
jobs:
changed-files:
runs-on: ubuntu-latest
name: Gather Changelist
strategy:
matrix:
fetch-depth:
- 0
base-branch:
- "staging"
outputs:
all: ${{ steps.changes.outputs.all }}
php: ${{ steps.changes.outputs.php }}
steps:
- name: Check out code
uses: actions/checkout@v4
with:
fetch-depth: ${{ matrix.fetch-depth }}
- name: Get changed files
id: changes
run: |
BASE_SHA="${{ github.event.before }}"
if [ "$BASE_SHA" = "0000000000000000000000000000000000000000" ]; then
BASE_SHA="${{ matrix.base-branch }}"
fi
if [[ ! -z "${{ github.event.pull_request.base.sha }}" ]]; then
BASE_SHA="${{ github.event.pull_request.base.sha }}"
fi
echo "all=$(git diff --name-only --diff-filter=ACMRT $BASE_SHA ${{ github.sha }} | xargs)" >> $GITHUB_OUTPUT
echo "php=$(git diff --name-only --diff-filter=ACMRT $BASE_SHA ${{ github.sha }} | grep -E '.ph(p|tml)$' | xargs)" >> $GITHUB_OUTPUT
validate-php:
runs-on: ubuntu-latest
name: Run php code validation and Unit tests
needs: changed-files
if: ${{needs.changed-files.outputs.php}}
strategy:
matrix:
node-version:
- 20
php-version: ["8.1", "8.2", "8.3", "8.4"]
dependencies:
- "highest"
composer-options:
- "--no-plugins --no-progress"
steps:
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node_version }}
- name: Check out code
uses: actions/checkout@v4
- name: Setup Php
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php-version }}
ini-file: development
tools: composer:2.2, cs2pr
env:
COMPOSER_AUTH_JSON: |
{
"http-basic": {
"repo.magento.com": {
"username": "${{ secrets.REPO_MAGENTO_USER }}",
"password": "${{ secrets.REPO_MAGENTO_PASSWORD }}"
}
}
}
- name: Validate Composer Files
run: composer validate
- name: Run Composer install
uses: "ramsey/composer-install@v1"
with:
dependency-versions: "${{ matrix.dependencies }}"
composer-options: "${{ matrix.composer-options }}"
- name: Detect PhpCs violations
run: |
vendor/bin/phpcs --config-set installed_paths ../../magento/magento-coding-standard/,../../phpcompatibility/php-compatibility,../../magento/php-compatibility-fork
vendor/bin/phpcs --standard=Magento2 -q --report=checkstyle ${{needs.changed-files.outputs.php}} | cs2pr --graceful-warnings
- name: Run Unit test
run: |
vendor/bin/phpunit Test/Unit/Model/
104 changes: 104 additions & 0 deletions .github/workflows/mftf.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
name: Run MFTF Tests

on:
schedule:
- cron: "00 6 * * 1"

jobs:
mftf:
runs-on: ubuntu-latest

services:
selenium:
image: selenium/standalone-chromium:latest # For AMD64
options: --shm-size=2gb
ports:
- "4444:4444"

steps:
- name: validate selenium
run: |
curl -s http://localhost:4444/wd/hub/status | jq .
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up PHP 8.2
uses: shivammathur/setup-php@v2
with:
php-version: "8.2"
extensions: mbstring, intl, soap, mysqli, dom, simplexml, xsl, zip, bcmath, gd
ini-values: memory_limit=2G

- name: Install Composer
run: sudo apt-get update && sudo apt-get install -y composer

- name: Install Magento 2.4.8
env:
COMPOSER_AUTH: |
{
"http-basic": {
"repo.magento.com": {
"username": "${{ secrets.REPO_MAGENTO_USER }}",
"password": "${{ secrets.REPO_MAGENTO_PASSWORD }}"
}
}
}
run: |
composer create-project --repository-url=https://repo.magento.com/ magento/project-community-edition magento
cd magento

- name: Install Paytrail module
run: |
cd magento
composer require paytrail/paytrail-php-sdk
mkdir -p app/code/Paytrail/PaymentService
rsync -av --exclude='.git' --exclude='vendor' --exclude='app/autoload.php' --exclude='magento' ../ ./app/code/Paytrail/PaymentService/

- name: Install MFTF
run: |
cd magento
chmod +x bin/magento
composer require --dev magento/magento2-functional-testing-framework
vendor/bin/mftf build:project
# configure MFTF env
cat <<EOF > dev/tests/acceptance/.env
MAGENTO_BASE_URL=${{ vars.BASE_URL }}
MAGENTO_BACKEND_NAME=admin
MAGENTO_ADMIN_USERNAME=${{ vars.ADMIN_USER }}
SELENIUM_HOST=localhost
SELENIUM_PATH=/
SELENIUM_PORT=4444
BROWSER=chrome
ENABLE_SELENIUM=1
EOF
# add .credential file
cat <<EOF > dev/tests/acceptance/.credentials
# Admin password
magento/MAGENTO_ADMIN_PASSWORD=${{ secrets.ADMIN_PASSWORD }}
magento/tfa/OTP_SHARED_SECRET=MFRGGZDF

# Paytrail test credentials:
paytrail/payment_paytrail_merchant_id=375917
paytrail/payment_paytrail_merchant_secret=SAIPPUAKAUPPIAS
EOF

echo '--- .env file ---'
cat dev/tests/acceptance/.env || echo '.env not found'
echo '--- .credentials file ---'
cat dev/tests/acceptance/.credentials || echo '.credentials not found'

- name: Run MFTF Tests
run: |
cd magento
php vendor/bin/codecept bootstrap
vendor/bin/mftf build:project
vendor/bin/mftf generate:suite PaytrailSuite

vendor/bin/mftf run:group PaytrailSuite

- name: Upload MFTF Logs
if: failure()
uses: actions/upload-artifact@v4
with:
name: mftf-logs
path: magento/dev/tests/acceptance/tests/_output
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ 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).

## [2.2.16] - 2026-03-24

- change 'No recurring payment' in admin to empty value.
- Add support for Klarna invoice cancellation.

## [2.2.15] - 2026-03-02

- Improve error handling for adding credit card.
Expand Down
55 changes: 55 additions & 0 deletions Gateway/Command/InvoiceCancellation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

namespace Paytrail\PaymentService\Gateway\Command;

use Magento\Payment\Gateway\CommandInterface;
use Magento\Payment\Gateway\Http\ClientException;
use Magento\Payment\Gateway\Http\ClientInterface;
use Magento\Payment\Gateway\Http\ConverterException;
use Magento\Payment\Gateway\Http\TransferFactoryInterface;
use Magento\Payment\Gateway\Request\BuilderInterface;
use Magento\Payment\Gateway\Response\HandlerInterface;

class InvoiceCancellation implements CommandInterface
{
/**
* InvoiceCancellation constructor.
*
* @param TransferFactoryInterface $transferFactory
* @param BuilderInterface $requestBuilder
* @param ClientInterface $client
* @param HandlerInterface $handler
*/
public function __construct(
private readonly TransferFactoryInterface $transferFactory,
private readonly BuilderInterface $requestBuilder,
private readonly ClientInterface $client,
private readonly HandlerInterface $handler
) {
}

/**
* Executes command basing on business object
*
* @param array $commandSubject
* @return array
* @throws ClientException
* @throws ConverterException
*/
public function execute(array $commandSubject): array
{
$transferO = $this->transferFactory->create(
$this->requestBuilder->build($commandSubject)
);

$response = $this->client->placeRequest($transferO);

if ($this->handler) {
$this->handler->handle(
$commandSubject,
$response
);
}
return $response;
}
}
103 changes: 103 additions & 0 deletions Gateway/Http/Client/InvoiceCancellation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<?php

namespace Paytrail\PaymentService\Gateway\Http\Client;

use GuzzleHttp\Exception\RequestException;
use Magento\Payment\Gateway\Http\ClientInterface;
use Paytrail\PaymentService\Logger\PaytrailLogger;
use Paytrail\PaymentService\Model\Adapter\Adapter;
use Magento\Payment\Gateway\Http\TransferInterface;

class InvoiceCancellation implements ClientInterface
{
/**
* InvoiceCancellation constructor.
*
* @param Adapter $paytrailAdapter
* @param PaytrailLogger $log
*/
public function __construct(
private readonly Adapter $paytrailAdapter,
private readonly PaytrailLogger $log
) {
}

/**
* @inheritdoc
*
* @param TransferInterface $transferObject
* @return array|void
*/
public function placeRequest(TransferInterface $transferObject)
{
$request = $transferObject->getBody();

$response = $this->invoiceCancellation(
$request['transaction_id']
);
$error = $response["error"];

if ($error) {
$this->log->error(
'Error occurred during invoice cancellation: '
. $error
);
}

return $response;
}

/**
* Invoice cancellation method.
*
* @param string $transactionId
* @return array
*/
public function invoiceCancellation($transactionId): array
{
$response["data"] = null;
$response["error"] = null;

try {
$paytrailClient = $this->paytrailAdapter->initPaytrailMerchantClient();

$this->log->debugLog(
'request',
\sprintf(
'Creating %s request to Paytrail API',
'invoice cancellation'
)
);

// handle token_request request
$response["data"] = $paytrailClient->cancelInvoice($transactionId);
$this->log->debugLog(
'response',
'Successful response for invoice cancellation'
);
} catch (RequestException $e) {
$this->log->error(\sprintf(
'Connection error to Paytrail Payment Service API: %s Error Code: %s',
$e->getMessage(),
$e->getCode()
));

if ($e->hasResponse()) {
$response["error"] = $e->getMessage();
return $response;
}
} catch (\Exception $e) {
$this->log->error(
\sprintf(
'A problem occurred during Paytrail Api connection: %s',
$e->getMessage()
),
$e->getTrace()
);
$response["error"] = $e->getMessage();
return $response;
}

return $response;
}
}
21 changes: 21 additions & 0 deletions Gateway/Request/InvoiceCancellationDataBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

namespace Paytrail\PaymentService\Gateway\Request;

use Magento\Payment\Gateway\Request\BuilderInterface;

class InvoiceCancellationDataBuilder implements BuilderInterface
{
/**
* @inheritdoc
*
* @param array $buildSubject
* @return array
*/
public function build(array $buildSubject): array
{
return [
'transaction_id' => $buildSubject['transaction_id']
];
}
}
Loading
Loading