Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
c2d50ac
PayPal agent commerce (cherry-pick)
lernhart Aug 4, 2025
150464a
Creating sdk structs
En0Ma1259 Oct 28, 2025
998bed2
ecs-fix & phpstan
En0Ma1259 Oct 29, 2025
926125b
fix test for <6.6.2
En0Ma1259 Nov 3, 2025
3231fee
Merge branch '6.6.x' into feat/backport-agent-commerce
En0Ma1259 Nov 7, 2025
6f30753
Update composer.json
En0Ma1259 Nov 11, 2025
4adf2a8
feat: tax status net (#466)
En0Ma1259 Nov 18, 2025
15a202b
fix: finalize transaction (#483)
En0Ma1259 Dec 4, 2025
a814086
Merge branch '6.6.x' into feat/backport-agent-commerce
En0Ma1259 Dec 16, 2025
933f2c9
Update openapi.d.ts
En0Ma1259 Dec 16, 2025
464c1db
open api generate
En0Ma1259 Dec 16, 2025
1105b81
feat: format country state (#517)
En0Ma1259 Jan 8, 2026
c92f445
fix: external id validation
lernhart Jan 21, 2026
61c9983
Merge remote-tracking branch 'origin/6.6.x' into feat/backport-agent-…
mstegmeyer Jan 22, 2026
744aed7
fix pipeline
En0Ma1259 Jan 22, 2026
256ddb3
ecs-fix
En0Ma1259 Jan 22, 2026
88208de
fix violation code
En0Ma1259 Jan 22, 2026
5f3d67c
fix: array contains violation (#526)
En0Ma1259 Jan 22, 2026
ffbeaaa
fix: public key mismatch
lernhart Jan 23, 2026
b747389
fix: bearer auth header + update cart route scope
lernhart Jan 26, 2026
d9b3136
fix: array contains violation
lernhart Jan 26, 2026
c62f664
fix: remove available shipping methods which do not have calculated p…
lernhart Jan 27, 2026
c5aef5e
fix: route scope + shipping address response format
lernhart Jan 28, 2026
5e1307e
fix: address line and admin area normalization
lernhart Jan 28, 2026
dc6b458
Merge branch '6.6.x' into feat/backport-agent-commerce
En0Ma1259 Feb 6, 2026
a915b69
chore: fix pipeline (#539)
En0Ma1259 Feb 6, 2026
c6b0aac
Merge branch '6.6.x' into feat/backport-agent-commerce
En0Ma1259 Feb 17, 2026
d0df425
Update IntrospectionProcessorTest.php
En0Ma1259 Feb 17, 2026
51f744d
Merge branch '6.6.x' into feat/backport-agent-commerce
En0Ma1259 Mar 9, 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
1 change: 0 additions & 1 deletion .php-cs-fixer.dist.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
'general_phpdoc_annotation_remove' => ['annotations' => ['copyright', 'category']],
'linebreak_after_opening_tag' => false,
'method_argument_space' => ['on_multiline' => 'ensure_fully_multiline'],
'method_chaining_indentation' => true,
'multiline_comment_opening_closing' => true,
'multiline_whitespace_before_semicolons' => true,
'native_function_invocation' => ['scope' => 'namespaced', 'strict' => false, 'exclude' => ['ini_get']],
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "swag/paypal",
"description": "PayPal integration for Shopware 6",
"version": "9.10.2",
"version": "9.10.62",
"type": "shopware-platform-plugin",
"license": "MIT",
"authors": [
Expand Down
68 changes: 68 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -396,3 +396,71 @@ parameters:
message: '#^Call to static method getContainer\(\) of internal class ShopwarePluginClassTest\.$#'
count: 2
path: tests/ShopwarePluginClassTest.php

-
message: '#^Parameter \$contextService of method Swag\\PayPal\\AgentCommerce\\Routing\\AgentRequestContextResolver\:\:__construct\(\) has typehint with internal interface Shopware\\Core\\System\\SalesChannel\\Context\\SalesChannelContextServiceInterface\.$#'
count: 1
path: src/AgentCommerce/Routing/AgentRequestContextResolver.php

-
message: '#^Property \$contextService references internal interface Shopware\\Core\\System\\SalesChannel\\Context\\SalesChannelContextServiceInterface in its type\.$#'
count: 1
path: src/AgentCommerce/Routing/AgentRequestContextResolver.php

-
message: '#^Call to method get\(\) of internal interface Shopware\\Core\\System\\SalesChannel\\Context\\SalesChannelContextServiceInterface from outside its root namespace Shopware\.$#'
count: 1
path: src/AgentCommerce/Routing/AgentRequestContextResolver.php

-
message: '#^Parameter \$contextService of method Swag\\PayPal\\AgentCommerce\\Util\\FaviconLoader\:\:__construct\(\) has typehint with internal interface Shopware\\Core\\System\\SalesChannel\\Context\\SalesChannelContextServiceInterface\.$#'
count: 1
path: src/AgentCommerce/Util/FaviconLoader.php

-
message: '#^Property \$contextService references internal interface Shopware\\Core\\System\\SalesChannel\\Context\\SalesChannelContextServiceInterface in its type\.$#'
count: 1
path: src/AgentCommerce/Util/FaviconLoader.php

-
message: '#^Call to method get\(\) of internal interface Shopware\\Core\\System\\SalesChannel\\Context\\SalesChannelContextServiceInterface from outside its root namespace Shopware\.$#'
count: 1
path: src/AgentCommerce/Util/FaviconLoader.php

-
message: '#^Property \$contextService references internal interface Shopware\\Core\\System\\SalesChannel\\Context\\SalesChannelContextServiceInterface in its type\.$#'
count: 1
path: src/AgentCommerce/SalesChannel/AbstractAgentCommerceRoute.php

-
message: '#^Call to method get\(\) of internal interface Shopware\\Core\\System\\SalesChannel\\Context\\SalesChannelContextServiceInterface from outside its root namespace Shopware\.$#'
count: 1
path: src/AgentCommerce/SalesChannel/AbstractAgentCommerceRoute.php

-
message: '#^Parameter \$contextService of method Swag\\PayPal\\AgentCommerce\\SalesChannel\\UpdateCartRoute\:\:__construct\(\) has typehint with internal interface Shopware\\Core\\System\\SalesChannel\\Context\\SalesChannelContextServiceInterface\.$#'
count: 1
path: src/AgentCommerce/SalesChannel/UpdateCartRoute.php

-
message: '#^Property \$contextService references internal interface Shopware\\Core\\System\\SalesChannel\\Context\\SalesChannelContextServiceInterface in its type\.$#'
count: 1
path: src/AgentCommerce/SalesChannel/UpdateCartRoute.php

-
message: '#^Parameter \$contextService of method Swag\\PayPal\\AgentCommerce\\SalesChannel\\CreateCartRoute\:\:__construct\(\) has typehint with internal interface Shopware\\Core\\System\\SalesChannel\\Context\\SalesChannelContextServiceInterface\.$#'
count: 1
path: src/AgentCommerce/SalesChannel/CreateCartRoute.php

-
message: '#^Property \$contextService references internal interface Shopware\\Core\\System\\SalesChannel\\Context\\SalesChannelContextServiceInterface in its type\.$#'
count: 1
path: src/AgentCommerce/SalesChannel/CreateCartRoute.php

-
message: '''
#^Call to deprecated method getDefaults\(\) of class Symfony\\Component\\Routing\\Attribute\\Route\:
Use the \"defaults\" property instead$#
'''
count: 2
path: tests/AgentCommerce/SalesChannel/DefaultRouteScopeTest.php
172 changes: 172 additions & 0 deletions src/AgentCommerce/Exception/AgentException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
<?php declare(strict_types=1);
/*
* (c) shopware AG <info@shopware.com>
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Swag\PayPal\AgentCommerce\Exception;

use Shopware\Core\Framework\Log\Package;
use Swag\PayPal\AgentCommerce\Struct\V1\AgentErrorDetail;
use Swag\PayPal\AgentCommerce\Struct\V1\AgentErrorDetailCollection;
use Symfony\Component\HttpFoundation\Response;

#[Package('checkout')]
class AgentException extends AgentHttpException
{
public const INVALID_REQUEST = 'INVALID_REQUEST';
public const INVALID_CART_ID = 'INVALID_CART_ID';
public const CART_NOT_FOUND = 'CART_NOT_FOUND';
public const INTERNAL_SERVER_ERROR = 'INTERNAL_SERVER_ERROR';
public const SERVICE_UNAVAILABLE = 'SERVICE_UNAVAILABLE';
public const PAYMENT_PROCESSOR_UNAVAILABLE = 'PAYMENT_PROCESSOR_UNAVAILABLE';
public const PAYMENT_CAPTURE_FAILED = 'PAYMENT_CAPTURE_FAILED';
public const INVENTORY_SYSTEM_ERROR = 'INVENTORY_SYSTEM_ERROR';
public const ORDER_SYSTEM_ERROR = 'ORDER_SYSTEM_ERROR';

public static function requiredFieldsMissing(string ...$fields): self
{
$message = 'Required field \'{{ fields }}\' is missing';
$parameters = ['fields' => implode(', ', $fields)];
$details = new AgentErrorDetailCollection();

foreach ($fields as $field) {
$detail = (new AgentErrorDetail());
$detail->setField($field);
$detail->setIssue('MISSING_REQUIRED_FIELD');
$detail->setDescription(\sprintf('The field \'%s\' is required and cannot be empty', $field));

$details->add($detail);
}

return new self(
Response::HTTP_BAD_REQUEST,
self::INVALID_REQUEST,
$message,
$parameters,
$details
);
}

public static function requiredFieldInvalid(string $field, string $reason): self
{
$message = 'Required field \'{{ field }}\' is invalid: \'{{ reason }}\'';
$parameters = ['field' => $field, 'reason' => $reason];

$detail = new AgentErrorDetail();
$detail->setField($field);
$detail->setIssue('MISSING_REQUIRED_FIELD');
$detail->setDescription(\sprintf('The field \'%s\' is invalid: %s', $field, $reason));

return new self(
Response::HTTP_BAD_REQUEST,
self::INVALID_REQUEST,
$message,
$parameters,
new AgentErrorDetailCollection([$detail])
);
}

public static function invalidJSONFormat(): self
{
return new self(
Response::HTTP_BAD_REQUEST,
self::INVALID_REQUEST,
'Request body contains invalid JSON'
);
}

public static function unauthorized(string $message, ?\Throwable $previous = null): self
{
return new self(
Response::HTTP_UNAUTHORIZED,
self::INVALID_REQUEST,
$message,
previous: $previous,
);
}

public static function invalidCartId(): self
{
return new self(
Response::HTTP_BAD_REQUEST,
self::INVALID_CART_ID,
'Cart ID format is invalid. Expected format: CART-[a-zA-Z0-9]{32}'
);
}

public static function cartNotFound(string $token): self
{
return new self(
Response::HTTP_NOT_FOUND,
self::CART_NOT_FOUND,
'Cart with ID \'{{ token }}\' does not exist',
['token' => $token]
);
}

public static function databaseConnectionFailure(): self
{
return new self(
Response::HTTP_INTERNAL_SERVER_ERROR,
self::INTERNAL_SERVER_ERROR,
'A temporary system error occurred. Please try again later.'
);
}

public static function externalServiceFailure(): self
{
return new self(
Response::HTTP_INTERNAL_SERVER_ERROR,
self::SERVICE_UNAVAILABLE,
'The payment processor is currently unavailable. Please try again later.'
);
}

public static function paymentProcessorUnavailable(): self
{
return new self(
Response::HTTP_INTERNAL_SERVER_ERROR,
self::PAYMENT_PROCESSOR_UNAVAILABLE,
'Payment processing is temporarily unavailable'
);
}

public static function paymentCaptureFailed(string $message): self
{
$detail = (new AgentErrorDetail());
$detail->setField('payment_method');
$detail->setIssue('CAPTURE_FAILED');
$detail->setDescription($message);

$details = new AgentErrorDetailCollection([$detail]);

return new self(
Response::HTTP_INTERNAL_SERVER_ERROR,
self::PAYMENT_CAPTURE_FAILED,
'Unable to capture payment at this time',
[],
$details
);
}

public static function inventorySystemError(): self
{
return new self(
Response::HTTP_INTERNAL_SERVER_ERROR,
self::INVENTORY_SYSTEM_ERROR,
'Unable to reserve inventory for checkout'
);
}

public static function orderSystemError(?\Throwable $previous = null): self
{
return new self(
Response::HTTP_INTERNAL_SERVER_ERROR,
self::ORDER_SYSTEM_ERROR,
'Order could not be created due to system error',
previous: $previous,
);
}
}
32 changes: 32 additions & 0 deletions src/AgentCommerce/Exception/AgentHttpException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php declare(strict_types=1);
/*
* (c) shopware AG <info@shopware.com>
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Swag\PayPal\AgentCommerce\Exception;

use Shopware\Core\Framework\HttpException;
use Shopware\Core\Framework\Log\Package;
use Swag\PayPal\AgentCommerce\Struct\V1\AgentErrorDetailCollection;

#[Package('checkout')]
abstract class AgentHttpException extends HttpException
{
public function __construct(
int $statusCode,
string $errorCode,
string $message,
array $parameters = [],
protected AgentErrorDetailCollection $details = new AgentErrorDetailCollection(),
?\Throwable $previous = null
) {
parent::__construct($statusCode, $errorCode, $message, $parameters, $previous);
}

public function getDetails(): AgentErrorDetailCollection
{
return $this->details;
}
}
82 changes: 82 additions & 0 deletions src/AgentCommerce/Exception/HoneyWebhookException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php declare(strict_types=1);
/*
* (c) shopware AG <info@shopware.com>
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Swag\PayPal\AgentCommerce\Exception;

use Shopware\Core\Framework\HttpException;
use Shopware\Core\Framework\Log\Package;
use Swag\PayPal\AgentCommerce\HoneyWebhookResult;
use Symfony\Component\HttpFoundation\Response;

/**
* @internal
*/
#[Package('checkout')]
class HoneyWebhookException extends HttpException
{
public const API_ERROR = 'API_ERROR';
public const NOT_REGISTERED = 'NOT_REGISTERED';
public const SALES_CHANNEL_NOT_FOUND = 'SALES_CHANNEL_NOT_FOUND';
public const PRODUCT_EXPORT_NOT_FOUND = 'PRODUCT_EXPORT_NOT_FOUND';
public const STOREFRONT_SALES_CHANNEL_NOT_FOUND = 'STOREFRONT_SALES_CHANNEL_NOT_FOUND';
public const INVALID_PRODUCT_EXPORT_ROUTE = 'INVALID_PRODUCT_EXPORT_ROUTE';

public static function salesChannelNotRegistered(): self
{
return new self(
Response::HTTP_BAD_REQUEST,
self::NOT_REGISTERED,
'Sales channel is not registered and can\'t be deregistered'
);
}

public static function invalidSalesChannel(): self
{
return new self(
Response::HTTP_BAD_REQUEST,
self::SALES_CHANNEL_NOT_FOUND,
'Agent commerce sales channel not found'
);
}

public static function productExportNotFound(): self
{
return new self(
Response::HTTP_BAD_REQUEST,
self::PRODUCT_EXPORT_NOT_FOUND,
'Product export sales channel not found'
);
}

public static function storefrontSalesChannelNotFound(): self
{
return new self(
Response::HTTP_BAD_REQUEST,
self::STOREFRONT_SALES_CHANNEL_NOT_FOUND,
'Storefront sales channel not found'
);
}

public static function invalidProductExportRoute(): self
{
return new self(
Response::HTTP_BAD_REQUEST,
self::INVALID_PRODUCT_EXPORT_ROUTE,
'Invalid product export route'
);
}

public static function invalidRequest(HoneyWebhookResult $result): self
{
return new self(
Response::HTTP_BAD_REQUEST,
self::API_ERROR . '_' . $result->error,
$result->message,
previous: $result->exception,
);
}
}
Loading
Loading