Merge pull request #215 from goteo/feat/update-gateway-api-resource-shape
feat: update gateway api resource shape
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
|
||||
final class Version20260709122602 extends AbstractMigration
|
||||
{
|
||||
public function getDescription(): string
|
||||
{
|
||||
return 'Change gateway_name to gateway_id';
|
||||
}
|
||||
|
||||
public function up(Schema $schema): void
|
||||
{
|
||||
$this->addSql('DROP INDEX IDX_AF382D4E3D4E91C8BF396750 ON checkout');
|
||||
$this->addSql('ALTER TABLE checkout CHANGE gateway_name gateway_id VARCHAR(255) NOT NULL');
|
||||
$this->addSql('CREATE INDEX IDX_AF382D4EBF396750 ON checkout (id)');
|
||||
}
|
||||
|
||||
public function down(Schema $schema): void
|
||||
{
|
||||
$this->addSql('DROP INDEX IDX_AF382D4EBF396750 ON checkout');
|
||||
$this->addSql('ALTER TABLE checkout CHANGE gateway_id gateway_name VARCHAR(255) NOT NULL');
|
||||
$this->addSql('CREATE INDEX IDX_AF382D4E3D4E91C8BF396750 ON checkout (gateway_name, id)');
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ use App\Gateway\CheckoutStatus;
|
||||
use App\Gateway\GatewayLink;
|
||||
use App\Gateway\RefundStrategy;
|
||||
use App\Gateway\Tracking;
|
||||
use App\Mapping\Transformer\GatewayNameMapTransformer;
|
||||
use App\Mapping\Transformer\GatewayIdMapTransformer;
|
||||
use App\State\ApiResourceStateProvider;
|
||||
use App\State\Gateway\CheckoutStateProcessor;
|
||||
use AutoMapper\Attribute\MapFrom;
|
||||
@@ -47,8 +47,8 @@ class CheckoutApiResource
|
||||
* The desired Gateway to checkout with.
|
||||
*/
|
||||
#[Assert\NotBlank()]
|
||||
#[MapFrom(property: 'gatewayName', transformer: GatewayNameMapTransformer::class)]
|
||||
#[MapTo(property: 'gatewayName', transformer: 'source.gateway.name')]
|
||||
#[MapFrom(property: 'gatewayId', transformer: GatewayIdMapTransformer::class)]
|
||||
#[MapTo(property: 'gatewayId', transformer: 'source.gateway.id')]
|
||||
public GatewayApiResource $gateway;
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,9 +21,16 @@ use App\State\Gateway\GatewayStateProvider;
|
||||
class GatewayApiResource
|
||||
{
|
||||
#[API\ApiProperty(identifier: true)]
|
||||
public string $id;
|
||||
|
||||
/**
|
||||
* The publicly known name of this payment method.
|
||||
*/
|
||||
public string $name;
|
||||
|
||||
/**
|
||||
* The types of GatewayCheckout this Gateway can process.
|
||||
*
|
||||
* @var array<int, \App\Gateway\ChargeType>
|
||||
*/
|
||||
public array $supports;
|
||||
|
||||
@@ -117,7 +117,7 @@ class InvestsPump implements PumpInterface
|
||||
|
||||
$checkout->setOrigin($user->getAccounting());
|
||||
$checkout->setStatus($this->getCheckoutStatus($record));
|
||||
$checkout->setGatewayName($this->getCheckoutGateway($record));
|
||||
$checkout->setGatewayId($this->getCheckoutGatewayId($record));
|
||||
$checkout->setReturnUrl(self::PLATFORM_RETURN_URL);
|
||||
|
||||
foreach ($this->getCheckoutTrackings($record) as $tracking) {
|
||||
@@ -396,21 +396,21 @@ class InvestsPump implements PumpInterface
|
||||
}
|
||||
}
|
||||
|
||||
private function getCheckoutGateway(array $record): string
|
||||
private function getCheckoutGatewayId(array $record): string
|
||||
{
|
||||
switch ($record['method']) {
|
||||
case 'tpv':
|
||||
return CecaGateway::getName();
|
||||
return CecaGateway::getId();
|
||||
case 'paypal':
|
||||
return PaypalGateway::getName();
|
||||
return PaypalGateway::getId();
|
||||
case 'pool':
|
||||
return WalletGateway::getName();
|
||||
return WalletGateway::getId();
|
||||
case 'cash':
|
||||
return CashGateway::getName();
|
||||
return CashGateway::getId();
|
||||
case 'drop':
|
||||
return DropGateway::getName();
|
||||
return DropGateway::getId();
|
||||
case 'stripe_subscription':
|
||||
return StripeGateway::getName();
|
||||
return StripeGateway::getId();
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ use App\ApiResource\Accounting\AccountingApiResource;
|
||||
use App\ApiResource\Gateway\GatewayApiResource;
|
||||
use App\Entity\Gateway\Checkout;
|
||||
use App\Gateway\RefundStrategy;
|
||||
use App\Mapping\Transformer\GatewayNameMapTransformer;
|
||||
use App\Mapping\Transformer\GatewayIdMapTransformer;
|
||||
use AutoMapper\Attribute\MapFrom;
|
||||
use AutoMapper\Attribute\MapTo;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
@@ -18,8 +18,8 @@ class CheckoutCreationDto
|
||||
* The desired Gateway to checkout with.
|
||||
*/
|
||||
#[Assert\NotBlank()]
|
||||
#[MapFrom(property: 'gatewayName', transformer: GatewayNameMapTransformer::class)]
|
||||
#[MapTo(property: 'gatewayName', transformer: 'source.gateway.name')]
|
||||
#[MapFrom(property: 'gatewayId', transformer: GatewayIdMapTransformer::class)]
|
||||
#[MapTo(property: 'gatewayId', transformer: 'source.gateway.id')]
|
||||
public GatewayApiResource $gateway;
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,7 +29,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||
#[MapProvider(EntityMapProvider::class)]
|
||||
#[Gedmo\Loggable()]
|
||||
#[ORM\Index(fields: ['migratedId'])]
|
||||
#[ORM\Index(fields: ['gatewayName', 'id'])]
|
||||
#[ORM\Index(fields: ['gateway', 'id'])]
|
||||
#[ORM\Entity(repositoryClass: CheckoutRepository::class)]
|
||||
class Checkout
|
||||
{
|
||||
@@ -43,11 +43,11 @@ class Checkout
|
||||
private ?int $id = null;
|
||||
|
||||
/**
|
||||
* The name of the Gateway implementation to checkout with.
|
||||
* The ID of the Gateway implementation to checkout with.
|
||||
*/
|
||||
#[Assert\NotBlank()]
|
||||
#[ORM\Column(length: 255)]
|
||||
private ?string $gatewayName = null;
|
||||
private ?string $gatewayId = null;
|
||||
|
||||
/**
|
||||
* The Accounting that will issue the Transactions of the GatewayCharges after a successful checkout.
|
||||
@@ -114,14 +114,14 @@ class Checkout
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getGatewayName(): ?string
|
||||
public function getGatewayId(): ?string
|
||||
{
|
||||
return $this->gatewayName;
|
||||
return $this->gatewayId;
|
||||
}
|
||||
|
||||
public function setGatewayName(string $gatewayName): static
|
||||
public function setGatewayId(string $id): static
|
||||
{
|
||||
$this->gatewayName = $gatewayName;
|
||||
$this->gatewayId = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -50,29 +50,29 @@ final class GatewayFilter extends AbstractFilter
|
||||
[$alias] = $this->addJoinsForNestedProperty($property, $rootAlias, $queryBuilder, $queryNameGenerator, $resourceClass, Join::LEFT_JOIN);
|
||||
}
|
||||
|
||||
$aliasedField = \sprintf('%s.gatewayName', $alias);
|
||||
$aliasedField = \sprintf('%s.gatewayId', $alias);
|
||||
|
||||
if (\count($values) > 1) {
|
||||
$queryBuilder
|
||||
->andWhere($queryBuilder->expr()->in($aliasedField, $parameterName))
|
||||
->setParameter($parameterName, array_map(fn($v) => $this->getGatewayName($v), $values));
|
||||
->setParameter($parameterName, array_map(fn($v) => $this->getGatewayId($v), $values));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$queryBuilder
|
||||
->andWhere($queryBuilder->expr()->eq($aliasedField, $parameterName))
|
||||
->setParameter($parameterName, $this->getGatewayName($values[0]));
|
||||
->setParameter($parameterName, $this->getGatewayId($values[0]));
|
||||
}
|
||||
|
||||
private function getGatewayName(mixed $value): string
|
||||
private function getGatewayId(mixed $value): string
|
||||
{
|
||||
$value = \array_slice(\explode('/', $value), -1)[0];
|
||||
|
||||
try {
|
||||
$gateway = $this->gatewayLocator->get($value);
|
||||
|
||||
return $gateway::getName();
|
||||
return $gateway::getId();
|
||||
} catch (MissingGatewayException $e) {
|
||||
throw new NotFoundHttpException($e->getMessage());
|
||||
}
|
||||
|
||||
@@ -11,11 +11,16 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class CashGateway implements GatewayInterface
|
||||
{
|
||||
public static function getName(): string
|
||||
public static function getId(): string
|
||||
{
|
||||
return 'cash';
|
||||
}
|
||||
|
||||
public static function getName(): string
|
||||
{
|
||||
return 'Cash';
|
||||
}
|
||||
|
||||
public static function getSupportedChargeTypes(): array
|
||||
{
|
||||
return [];
|
||||
|
||||
@@ -14,11 +14,16 @@ class CecaGateway implements GatewayInterface
|
||||
{
|
||||
public const LEGACY_MESSAGE = 'This Gateway implementation is only meant to give support to legacy-records. DO NOT USE. DO NOT IMPLEMENT.';
|
||||
|
||||
public static function getName(): string
|
||||
public static function getId(): string
|
||||
{
|
||||
return 'tpv';
|
||||
}
|
||||
|
||||
public static function getName(): string
|
||||
{
|
||||
return 'Credit Card';
|
||||
}
|
||||
|
||||
public static function getSupportedChargeTypes(): array
|
||||
{
|
||||
return [
|
||||
|
||||
@@ -27,6 +27,11 @@ interface GatewayInterface
|
||||
/**
|
||||
* @return string A short, unique, descriptive string for this Gateway
|
||||
*/
|
||||
public static function getId(): string;
|
||||
|
||||
/**
|
||||
* @return string the commercially-preferred displayable name of the Gateway platform
|
||||
*/
|
||||
public static function getName(): string;
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,7 +9,7 @@ use App\Gateway\Exception\MissingGatewayException;
|
||||
class GatewayLocator
|
||||
{
|
||||
/** @var GatewayInterface[] */
|
||||
private array $gatewaysByName = [];
|
||||
private array $gatewaysById = [];
|
||||
|
||||
/** @var GatewayInterface[] */
|
||||
private array $gatewaysByClass = [];
|
||||
@@ -20,10 +20,10 @@ class GatewayLocator
|
||||
$this->gatewaysByClass[$gateway::class] = $gateway;
|
||||
}
|
||||
|
||||
self::validateGatewayNames($this->gatewaysByClass);
|
||||
self::validateGatewayIDs($this->gatewaysByClass);
|
||||
|
||||
foreach ($this->gatewaysByClass as $class => $gateway) {
|
||||
$this->gatewaysByName[$gateway::getName()] = $gateway;
|
||||
$this->gatewaysById[$gateway::getId()] = $gateway;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,21 +32,21 @@ class GatewayLocator
|
||||
*/
|
||||
public function getAll(): array
|
||||
{
|
||||
return $this->gatewaysByName;
|
||||
return $this->gatewaysById;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name Name of the Gateway interface implementation
|
||||
* @param string $id ID of the Gateway interface implementation
|
||||
*
|
||||
* @throws \Exception When the `$name` does not match to that of an implemented Gateway
|
||||
* @throws \Exception When the `$id` does not match to that of an implemented Gateway
|
||||
*/
|
||||
public function get(string $name): GatewayInterface
|
||||
public function get(string $id): GatewayInterface
|
||||
{
|
||||
if (!\array_key_exists($name, $this->gatewaysByName)) {
|
||||
throw new MissingGatewayException($name);
|
||||
if (!\array_key_exists($id, $this->gatewaysById)) {
|
||||
throw new MissingGatewayException($id);
|
||||
}
|
||||
|
||||
return $this->gatewaysByName[$name];
|
||||
return $this->gatewaysById[$id];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -54,31 +54,31 @@ class GatewayLocator
|
||||
*/
|
||||
public function getForCheckout(Checkout $checkout): GatewayInterface
|
||||
{
|
||||
return $this->get($checkout->getGatewayName());
|
||||
return $this->get($checkout->getGatewayId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the gateway names are unique for each gateway.
|
||||
* Ensures the gateway IDs are unique for each gateway.
|
||||
*
|
||||
* @param array $gatewayClasses Fully-qualified Gateway class names
|
||||
*
|
||||
* @throws \Exception If there are two different Gateway classes that return the same name string
|
||||
*/
|
||||
private static function validateGatewayNames(array $gatewayClasses): void
|
||||
private static function validateGatewayIDs(array $gatewayClasses): void
|
||||
{
|
||||
$gatewaysValidated = [];
|
||||
foreach ($gatewayClasses as $gatewayClass) {
|
||||
$gatewayName = $gatewayClass::getName();
|
||||
$gatewayId = $gatewayClass::getId();
|
||||
|
||||
if (\array_key_exists($gatewayName, $gatewaysValidated)) {
|
||||
if (\array_key_exists($gatewayId, $gatewaysValidated)) {
|
||||
throw new DuplicateGatewayException(
|
||||
$gatewayName,
|
||||
$gatewayId,
|
||||
$gatewayClass::class,
|
||||
$gatewaysValidated[$gatewayName]::class
|
||||
$gatewaysValidated[$gatewayId]::class
|
||||
);
|
||||
}
|
||||
|
||||
$gatewaysValidated[$gatewayName] = $gatewayClass;
|
||||
$gatewaysValidated[$gatewayId] = $gatewayClass;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,11 +44,16 @@ class PaypalGateway extends AbstractGateway
|
||||
private PaypalService $paypal,
|
||||
) {}
|
||||
|
||||
public static function getName(): string
|
||||
public static function getId(): string
|
||||
{
|
||||
return 'paypal';
|
||||
}
|
||||
|
||||
public static function getName(): string
|
||||
{
|
||||
return 'PayPal';
|
||||
}
|
||||
|
||||
public static function getSupportedChargeTypes(): array
|
||||
{
|
||||
return [
|
||||
|
||||
@@ -37,11 +37,16 @@ class StripeGateway extends AbstractGateway
|
||||
$this->stripe = new StripeClient($stripeApiKey);
|
||||
}
|
||||
|
||||
public static function getName(): string
|
||||
public static function getId(): string
|
||||
{
|
||||
return 'stripe';
|
||||
}
|
||||
|
||||
public static function getName(): string
|
||||
{
|
||||
return 'Stripe';
|
||||
}
|
||||
|
||||
public static function getSupportedChargeTypes(): array
|
||||
{
|
||||
return [
|
||||
|
||||
@@ -18,11 +18,16 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class WalletGateway implements GatewayInterface
|
||||
{
|
||||
public static function getName(): string
|
||||
public static function getId(): string
|
||||
{
|
||||
return 'wallet';
|
||||
}
|
||||
|
||||
public static function getName(): string
|
||||
{
|
||||
return 'Wallet';
|
||||
}
|
||||
|
||||
public static function getSupportedChargeTypes(): array
|
||||
{
|
||||
return [
|
||||
|
||||
+2
-1
@@ -6,7 +6,7 @@ use App\ApiResource\Gateway\GatewayApiResource;
|
||||
use App\Gateway\GatewayLocator;
|
||||
use AutoMapper\Transformer\PropertyTransformer\PropertyTransformerInterface;
|
||||
|
||||
class GatewayNameMapTransformer implements PropertyTransformerInterface
|
||||
class GatewayIdMapTransformer implements PropertyTransformerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private GatewayLocator $gatewayLocator,
|
||||
@@ -17,6 +17,7 @@ class GatewayNameMapTransformer implements PropertyTransformerInterface
|
||||
$gateway = $this->gatewayLocator->get($value);
|
||||
|
||||
$resource = new GatewayApiResource();
|
||||
$resource->id = $gateway::getId();
|
||||
$resource->name = $gateway::getName();
|
||||
$resource->supports = $gateway::getSupportedChargeTypes();
|
||||
|
||||
@@ -34,7 +34,7 @@ class CheckoutService
|
||||
GatewaysController::REDIRECT,
|
||||
[
|
||||
'type' => $type,
|
||||
'gateway' => $checkout->getGatewayName(),
|
||||
'gateway' => $checkout->getGatewayId(),
|
||||
'checkoutId' => $checkout->getId(),
|
||||
...$parameters,
|
||||
],
|
||||
|
||||
@@ -24,7 +24,7 @@ class GatewayStateProvider implements ProviderInterface
|
||||
case API\GetCollection::class:
|
||||
return $this->getGateways();
|
||||
case API\Get::class:
|
||||
return $this->getGateway($uriVariables['name']);
|
||||
return $this->getGateway($uriVariables['id']);
|
||||
default:
|
||||
return $this->getGateways();
|
||||
}
|
||||
@@ -48,10 +48,10 @@ class GatewayStateProvider implements ProviderInterface
|
||||
return $gateways;
|
||||
}
|
||||
|
||||
private function getGateway(string $name): GatewayApiResource
|
||||
private function getGateway(string $id): GatewayApiResource
|
||||
{
|
||||
try {
|
||||
$gateway = $this->gateways->get($name);
|
||||
$gateway = $this->gateways->get($id);
|
||||
|
||||
foreach ($gateway::getAllowedRoles() as $role) {
|
||||
$isGranted = $this->security->isGranted($role, $this->security->getUser());
|
||||
@@ -70,6 +70,7 @@ class GatewayStateProvider implements ProviderInterface
|
||||
private function toResource(GatewayInterface $gateway): GatewayApiResource
|
||||
{
|
||||
$resource = new GatewayApiResource();
|
||||
$resource->id = $gateway::getId();
|
||||
$resource->name = $gateway::getName();
|
||||
$resource->supports = $gateway::getSupportedChargeTypes();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user