Feature: Abstraction on Payments based on their operations
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Core\Payment\Events;
|
||||
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Modules\Core\Payment\DTOs\PaymentResult;
|
||||
|
||||
/**
|
||||
* Dispatched when SupportsAuthorization::authorize() (or a
|
||||
* HandlesPaymentCallback::handleCallback() resolving it later) determines
|
||||
* the gateway did not grant the requested hold. $result->retriable is how
|
||||
* a listener knows whether "try again with the same method" is reasonable
|
||||
* — see PaymentResult's own docblock.
|
||||
*/
|
||||
class PaymentAuthorizationFailed
|
||||
{
|
||||
use Dispatchable;
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $context
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly string $type,
|
||||
public readonly PaymentResult $result,
|
||||
public readonly array $context = [],
|
||||
) {}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Core\Payment\Events;
|
||||
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Modules\Core\Payment\DTOs\PaymentResult;
|
||||
|
||||
/**
|
||||
* Dispatched by a driver's SupportsAuthorization::authorize() (or, for an
|
||||
* async gateway, HandlesPaymentCallback::handleCallback() resolving that
|
||||
* same authorize() call later) once a hold has been placed — no funds have
|
||||
* moved yet, see SupportsCaptures/SupportsVoids for what happens next.
|
||||
*
|
||||
* Carries $result (the full PaymentResult, not just a reference) plus
|
||||
* $type and $context — same reasoning throughout Payment's events: Payment
|
||||
* has no concept of a cart, an order, or a checkout fingerprint, so
|
||||
* whatever a listener needs to react travels through $context untouched,
|
||||
* opaque to Payment itself.
|
||||
*/
|
||||
class PaymentAuthorized
|
||||
{
|
||||
use Dispatchable;
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $context
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly string $type,
|
||||
public readonly PaymentResult $result,
|
||||
public readonly array $context = [],
|
||||
) {}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Core\Payment\Events;
|
||||
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Modules\Core\Payment\DTOs\PaymentResult;
|
||||
|
||||
/**
|
||||
* Dispatched when SupportsPay::pay() or SupportsCaptures::capture() (or a
|
||||
* HandlesPaymentCallback::handleCallback() resolving either later) fails
|
||||
* to take the money — whether that's a sale-mode gateway declining the
|
||||
* charge outright, or a capture call against an existing authorization
|
||||
* being rejected. Same terminal-event symmetry as PaymentCaptured: this is
|
||||
* the one "capture attempt failed" event regardless of which path
|
||||
* produced it.
|
||||
*/
|
||||
class PaymentCaptureFailed
|
||||
{
|
||||
use Dispatchable;
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $context
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly string $type,
|
||||
public readonly PaymentResult $result,
|
||||
public readonly array $context = [],
|
||||
) {}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Core\Payment\Events;
|
||||
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Modules\Core\Payment\DTOs\PaymentResult;
|
||||
|
||||
/**
|
||||
* The one "money has actually been taken" event, dispatched from either of
|
||||
* two different call paths that end at the same business fact:
|
||||
* - SupportsPay::pay() — an atomic authorize+capture gateway call
|
||||
* (Mastercard's "Pay", Stripe's capture_method=automatic, an offline
|
||||
* driver's immediate success).
|
||||
* - SupportsCaptures::capture() — settling a PRIOR authorize() hold.
|
||||
* Whether the money moved in one gateway call or two is a driver-internal
|
||||
* detail; a listener reacting to "a payment has been captured" never
|
||||
* needs to know or care which path produced this event.
|
||||
*/
|
||||
class PaymentCaptured
|
||||
{
|
||||
use Dispatchable;
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $context
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly string $type,
|
||||
public readonly PaymentResult $result,
|
||||
public readonly array $context = [],
|
||||
) {}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Core\Payment\Events;
|
||||
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Modules\Core\Payment\DTOs\PaymentResult;
|
||||
|
||||
/**
|
||||
* Dispatched when SupportsRefunds::refund() fails to return settled funds
|
||||
* — e.g. the gateway rejects refunding more than was originally captured.
|
||||
*/
|
||||
class PaymentRefundFailed
|
||||
{
|
||||
use Dispatchable;
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $context
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly string $type,
|
||||
public readonly PaymentResult $result,
|
||||
public readonly array $context = [],
|
||||
) {}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Core\Payment\Events;
|
||||
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Modules\Core\Payment\DTOs\PaymentResult;
|
||||
|
||||
/**
|
||||
* Dispatched by SupportsRefunds::refund() once settled funds (from a prior
|
||||
* pay() or capture()) have actually been returned — full or partial.
|
||||
* Independent of whether the original settlement was a sale or an
|
||||
* authorize-then-capture: a refund only ever targets money that was
|
||||
* genuinely taken, regardless of how it got taken.
|
||||
*/
|
||||
class PaymentRefunded
|
||||
{
|
||||
use Dispatchable;
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $context
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly string $type,
|
||||
public readonly PaymentResult $result,
|
||||
public readonly array $context = [],
|
||||
) {}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Core\Payment\Events;
|
||||
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
|
||||
/**
|
||||
* Dispatched by a PaymentDriver once it has independently decided (by
|
||||
* whatever mechanism is native to its gateway) that a payment succeeded.
|
||||
* Deliberately carries nothing but what a payment fundamentally is —
|
||||
* $type, $reference, $amount — plus $context, an opaque bag the driver
|
||||
* received from whoever called confirm() and hands back unchanged here.
|
||||
*
|
||||
* Payment has no concept of a cart, an order, or a checkout fingerprint —
|
||||
* those are Checkout's concepts, and Checkout is only one possible
|
||||
* consumer of a successful payment (a future Subscriptions module renewing
|
||||
* on a recurring charge is another). $context is how a caller like
|
||||
* CheckoutService::confirmPayment() smuggles what it needs to react
|
||||
* (cart_id, fingerprint) through Payment without Payment ever reading or
|
||||
* caring what's inside — each listener interprets $context on its own
|
||||
* terms, or ignores the event entirely if the keys it needs aren't there.
|
||||
*/
|
||||
class PaymentSucceeded
|
||||
{
|
||||
use Dispatchable;
|
||||
|
||||
/**
|
||||
* $amount is in the currency's minor unit, same convention as
|
||||
* Lunar\Base\Casts\Price.
|
||||
*
|
||||
* @param array<string, mixed> $context
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly string $type,
|
||||
public readonly string $reference,
|
||||
public readonly int $amount,
|
||||
public readonly array $context = [],
|
||||
) {}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Core\Payment\Events;
|
||||
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Modules\Core\Payment\DTOs\PaymentResult;
|
||||
|
||||
/**
|
||||
* Dispatched when SupportsVoids::void() fails to release a prior
|
||||
* authorization — e.g. the hold already expired or was already captured,
|
||||
* so there was nothing left to void.
|
||||
*/
|
||||
class PaymentVoidFailed
|
||||
{
|
||||
use Dispatchable;
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $context
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly string $type,
|
||||
public readonly PaymentResult $result,
|
||||
public readonly array $context = [],
|
||||
) {}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Core\Payment\Events;
|
||||
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Modules\Core\Payment\DTOs\PaymentResult;
|
||||
|
||||
/**
|
||||
* Dispatched by SupportsVoids::void() once a prior authorization hold has
|
||||
* been released without ever settling — the "actually, never mind" exit
|
||||
* from an authorize() that SupportsCaptures::capture() would otherwise
|
||||
* have settled. No funds ever moved, so this is distinct from
|
||||
* PaymentRefunded (which reverses money that was actually taken).
|
||||
*/
|
||||
class PaymentVoided
|
||||
{
|
||||
use Dispatchable;
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $context
|
||||
*/
|
||||
public function __construct(
|
||||
public readonly string $type,
|
||||
public readonly PaymentResult $result,
|
||||
public readonly array $context = [],
|
||||
) {}
|
||||
}
|
||||
Reference in New Issue
Block a user