Skip to content

Commit

Permalink
Merge pull request #33 from shopware/brain-10/implement-logging
Browse files Browse the repository at this point in the history
BRAIN-10 - Implement logging
  • Loading branch information
lernhart authored Feb 6, 2024
2 parents 95684fa + 16c7bf9 commit df18314
Show file tree
Hide file tree
Showing 13 changed files with 161 additions and 47 deletions.
6 changes: 5 additions & 1 deletion .platform.app.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ crons:
cmd: |
# only run for the production environment, aka trunk
if [ "$PLATFORM_ENVIRONMENT_TYPE" = "production" ]; then
croncape bin/console report:turnover
bin/console report:turnover
code="$?"
if [ "$code" -ne "0" ]; then
printf 'Turnover report exited with %s\n' "$code"
fi
fi
# The hooks that will be performed when the package is deployed.
Expand Down
12 changes: 12 additions & 0 deletions config/packages/framework.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,15 @@ when@test:
test: true
session:
storage_factory_id: session.storage.factory.mock_file

when@prod:
framework:
exceptions:
App\SDK\Exception\SignatureInvalidException:
log_level: warning
App\SDK\Exception\MissingShopParameterException:
log_level: warning
App\SDK\Exception\ShopNotFoundException:
log_level: warning
Swag\Braintree\Braintree\Exception\BraintreeTransactionNotFoundException:
log_level: info
7 changes: 6 additions & 1 deletion src/Braintree/Exception/BraintreePaymentException.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,19 @@

namespace Swag\Braintree\Braintree\Exception;

use Shopware\App\SDK\Shop\ShopInterface;
use Swag\Braintree\Framework\Exception\BraintreeHttpException;

class BraintreePaymentException extends BraintreeHttpException
{
public const ERROR_CODE = 'SWAG_BRAINTREE__PAYMENT_EXCEPTION';

public function __construct(string $message, array $parameters = [], \Throwable $e = null)
public function __construct(string $message, array $parameters = [], \Throwable $e = null, ShopInterface $shop = null)
{
if ($shop) {
$parameters['shopId'] = $shop->getShopId();
}

parent::__construct(\sprintf('Braintree payment process failed: %s', $message), $parameters, $e);
}

Expand Down
36 changes: 36 additions & 0 deletions src/Braintree/Exception/BraintreeTransactionNotFoundException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php declare(strict_types=1);

namespace Swag\Braintree\Braintree\Exception;

use Shopware\App\SDK\Shop\ShopInterface;
use Swag\Braintree\Framework\Exception\BraintreeHttpException;
use Symfony\Component\HttpFoundation\Response;

class BraintreeTransactionNotFoundException extends BraintreeHttpException
{
public const ERROR_CODE = 'SWAG_BRAINTREE__TRANSACTION_NOT_FOUND';

/**
* @param string[] $orderTransactionIds
*/
public function __construct(array $orderTransactionIds, ShopInterface $shop, string $braintreeTransactionId = null, array $parameters = [])
{
$parameters['shopId'] = $shop->getShopId();
$parameters['orderTransactionIds'] = $orderTransactionIds;
if ($braintreeTransactionId) {
$parameters['braintreeTransactionId'] = $braintreeTransactionId;
}

parent::__construct('Braintree transaction not found', $parameters);
}

public function getErrorCode(): string
{
return self::ERROR_CODE;
}

public function getStatusCode(): int
{
return Response::HTTP_BAD_REQUEST;
}
}
11 changes: 7 additions & 4 deletions src/Braintree/Gateway/BraintreeConnectionService.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Braintree\Configuration;
use Braintree\Exception;
use Braintree\Exception\Authentication;
use Braintree\Gateway;
use Braintree\MerchantAccount;
use Swag\Braintree\Braintree\Gateway\Connection\BraintreeConnectionStatus;
Expand Down Expand Up @@ -53,7 +54,6 @@ public function getDefaultMerchantAccount(): ?MerchantAccount
}
}
} catch (Exception) {
return null;
}

return null;
Expand All @@ -66,9 +66,12 @@ public function getAllMerchantAccounts(): array
{
$accounts = [];

/** @var MerchantAccount $account */
foreach ($this->gateway->merchantAccount()->all() as $account) {
$accounts[] = $account;
try {
/** @var MerchantAccount $account */
foreach ($this->gateway->merchantAccount()->all() as $account) {
$accounts[] = $account;
}
} catch (Authentication) {
}

return $accounts;
Expand Down
51 changes: 26 additions & 25 deletions src/Braintree/Payment/BraintreePaymentService.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use Shopware\App\SDK\Context\Payment\PaymentPayAction;
use Shopware\App\SDK\Shop\ShopInterface;
use Swag\Braintree\Braintree\Exception\BraintreePaymentException;
use Swag\Braintree\Braintree\Exception\BraintreeTransactionNotFoundException;
use Swag\Braintree\Braintree\Util\SalesChannelConfigService;
use Swag\Braintree\Entity\TransactionEntity;
use Swag\Braintree\Entity\TransactionReportEntity;
Expand Down Expand Up @@ -66,11 +67,11 @@ public function handleTransaction(PaymentPayAction $payment): Transaction
if (!$response->success) {
// @infection-ignore-all - As if that line isn't painful enough
// @phpstan-ignore-next-line - Braintree SDK needs better typing
throw new BraintreePaymentException($response->errors->deepAll()[0]?->message ?? 'Unknown error occured');
throw new BraintreePaymentException($response->errors->deepAll()[0]?->message ?? 'Unknown error occured', shop: $payment->shop);
}

if (!isset($response->transaction)) {
throw new BraintreePaymentException('No transaction provided');
throw new BraintreePaymentException('No transaction provided', shop: $payment->shop);
}

$this->saveTransaction($payment, $response->transaction);
Expand All @@ -82,17 +83,17 @@ public function extractNonce(PaymentPayAction $payment): string
{
if (!$payment->requestData) {
/** @infection-ignore-all can not be tested */
throw new BraintreePaymentException('No nonce provided');
throw new BraintreePaymentException('No nonce provided', shop: $payment->shop);
}

if (!\array_key_exists(self::BRAINTREE_NONCE, $payment->requestData)) {
throw new BraintreePaymentException('No nonce provided');
throw new BraintreePaymentException('No nonce provided', shop: $payment->shop);
}

$nonce = $payment->requestData[self::BRAINTREE_NONCE];

if (!\is_string($nonce)) {
throw new BraintreePaymentException('No nonce provided');
throw new BraintreePaymentException('No nonce provided', shop: $payment->shop);
}

return $nonce;
Expand All @@ -115,26 +116,6 @@ private function validateThreeDSecure(string $nonce, bool $enforced): void
}
}

/**
* @param string[] $transactions
*/
public function getTransactionDetails(ShopInterface $shop, array $transactions): Transaction
{
$transaction = $this->transactionRepository->findNewestBraintreeTransaction($shop, $transactions);

if (!$transaction) {
throw new BraintreePaymentException('No braintree transaction found');
}

try {
$braintreeTransaction = $this->gateway->transaction()->find($transaction->getBraintreeTransactionId());
} catch (NotFound) {
throw new BraintreePaymentException('No braintree transaction found');
}

return $braintreeTransaction;
}

private function saveTransaction(PaymentPayAction $payment, Transaction $braintreeTransaction): void
{
$transaction = (new TransactionEntity())
Expand All @@ -152,4 +133,24 @@ private function saveTransaction(PaymentPayAction $payment, Transaction $braintr

$this->em->flush();
}

/**
* @param string[] $transactions
*/
public function getTransactionDetails(ShopInterface $shop, array $transactions): Transaction
{
$transaction = $this->transactionRepository->findNewestBraintreeTransaction($shop, $transactions);

if (!$transaction) {
throw new BraintreeTransactionNotFoundException($transactions, $shop);
}

try {
$braintreeTransaction = $this->gateway->transaction()->find($transaction->getBraintreeTransactionId());
} catch (NotFound) {
throw new BraintreeTransactionNotFoundException($transactions, $shop, $transaction->getBraintreeTransactionId());
}

return $braintreeTransaction;
}
}
1 change: 0 additions & 1 deletion src/Braintree/Payment/OrderInformationService.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ public function extractLineItems(PaymentPayAction $payment): array

// @infection-ignore-all - if 249 or 248, it really doesn't matter
if (\count($orderLineItems) > 249) {
// @todo - log warning -> only first 249 are selected
$orderLineItems = \array_slice($orderLineItems, 0, 249);
}

Expand Down
4 changes: 2 additions & 2 deletions src/Doctrine/RespectfulUuidGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

namespace Swag\Braintree\Doctrine;

use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Id\AbstractIdGenerator;
use Swag\Braintree\Entity\Contract\EntityInterface;
use Symfony\Component\Uid\Uuid;

class RespectfulUuidGenerator extends AbstractIdGenerator
{
public function generate(EntityManager $em, $entity): ?Uuid
public function generateId(EntityManagerInterface $em, $entity): ?Uuid
{
if (!$entity) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,22 @@
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\TestCase;
use Swag\Braintree\Braintree\Exception\BraintreePaymentException;
use Swag\Braintree\Entity\ShopEntity;
use Symfony\Component\HttpFoundation\Response;

#[CoversClass(BraintreePaymentException::class)]
class BraintreePaymentExceptionTest extends TestCase
{
public function testConstruct(): void
{
$shop = new ShopEntity('this-is-shop-id', '', '');
$previous = new \RuntimeException();
$exception = new BraintreePaymentException('this-is-message', e: $previous);
$exception = new BraintreePaymentException('this-is-message', e: $previous, shop: $shop);

static::assertSame('SWAG_BRAINTREE__PAYMENT_EXCEPTION', $exception->getErrorCode());
static::assertSame('Braintree payment process failed: this-is-message', $exception->getMessage());
static::assertSame(Response::HTTP_INTERNAL_SERVER_ERROR, $exception->getStatusCode());
static::assertSame($previous, $exception->getPrevious());
static::assertSame($shop->getShopId(), $exception->getParameters()['shopId']);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php declare(strict_types=1);

namespace Swag\Braintree\Tests\Unit\Braintree\Exception;

use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\TestCase;
use Swag\Braintree\Braintree\Exception\BraintreeTransactionNotFoundException;
use Swag\Braintree\Entity\ShopEntity;
use Symfony\Component\HttpFoundation\Response;

#[CoversClass(BraintreeTransactionNotFoundException::class)]
class BraintreeTransactionNotFoundExceptionTest extends TestCase
{
public function testConstruct(): void
{
$orderTransactionIds = ['this-is-order-transaction-id'];
$shop = new ShopEntity('this-is-shop-id', '', '');
$exception = new BraintreeTransactionNotFoundException($orderTransactionIds, $shop, 'this-is-braintree-transaction-id');

static::assertSame('SWAG_BRAINTREE__TRANSACTION_NOT_FOUND', $exception->getErrorCode());
static::assertSame('Braintree transaction not found', $exception->getMessage());
static::assertSame(Response::HTTP_BAD_REQUEST, $exception->getStatusCode());

$params = $exception->getParameters();
static::assertSame($shop->getShopId(), $params['shopId']);
static::assertSame($orderTransactionIds, $params['orderTransactionIds']);
static::assertSame('this-is-braintree-transaction-id', $params['braintreeTransactionId']);
}
}
21 changes: 21 additions & 0 deletions tests/unit/Braintree/Gateway/BraintreeConnectionServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace Swag\Braintree\Tests\Unit\Braintree\Gateway;

use Braintree\Exception as BraintreeException;
use Braintree\Exception\Authentication;
use Braintree\Gateway;
use Braintree\MerchantAccount;
use Braintree\MerchantAccountGateway;
Expand Down Expand Up @@ -243,6 +244,26 @@ public function testGetAllMerchantAccounts(): void
static::assertCount(3, $merchantAccounts);
}

public function testGetAllMerchantAccountsThrowsAuthenticationException(): void
{
$accountGateway = $this->createMock(MerchantAccountGateway::class);
$accountGateway
->expects(static::once())
->method('all')
->willThrowException(new Authentication());

$gateway = $this->createMock(Gateway::class);
$gateway
->expects(static::once())
->method('merchantAccount')
->willReturn($accountGateway);

$service = new BraintreeConnectionService($gateway);
$merchantAccounts = $service->getAllMerchantAccounts();

static::assertEmpty($merchantAccounts);
}

/**
* @param object[] $items
*/
Expand Down
9 changes: 5 additions & 4 deletions tests/unit/Braintree/Payment/BraintreePaymentServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Swag\Braintree\Braintree\Exception\BraintreePaymentException;
use Swag\Braintree\Braintree\Exception\BraintreeTransactionNotFoundException;
use Swag\Braintree\Braintree\Payment\BraintreePaymentService;
use Swag\Braintree\Braintree\Payment\OrderInformationService;
use Swag\Braintree\Braintree\Payment\Tax\TaxService;
Expand Down Expand Up @@ -403,8 +404,8 @@ public function testGetTransactionDetailsWithoutBraintreeTransaction(): void
->with('this-is-transaction-id')
->willThrowException(new NotFound());

static::expectException(BraintreePaymentException::class);
static::expectExceptionMessage('No braintree transaction found');
static::expectException(BraintreeTransactionNotFoundException::class);
static::expectExceptionMessage('Braintree transaction not found');

$this->paymentService->getTransactionDetails($this->shop, ['this-is-order-transaction-id']);
}
Expand All @@ -421,8 +422,8 @@ public function testGetTransactionDetailsWithoutTransactionEntity(): void
->expects(static::never())
->method('find');

static::expectException(BraintreePaymentException::class);
static::expectExceptionMessage('No braintree transaction found');
static::expectException(BraintreeTransactionNotFoundException::class);
static::expectExceptionMessage('Braintree transaction not found');

$this->paymentService->getTransactionDetails($this->shop, ['this-is-order-transaction-id']);
}
Expand Down
Loading

0 comments on commit df18314

Please sign in to comment.