Feat: Payment Restructuring to be fully event-driven

This commit is contained in:
2026-09-03 17:00:24 +03:00
parent a987a2d57c
commit 35c3334690
13 changed files with 698 additions and 185 deletions
+22
View File
@@ -0,0 +1,22 @@
<?php
namespace Modules\Core\Payment\Contracts;
/**
* Every driver implements this, orthogonal to which payment operations
* (SupportsPay, SupportsAuthorization, ...) it supports — whether a driver
* can actually be used right now is a separate question from what it's
* capable of when it can be. An offline driver has no external dependency
* to be missing and always returns true; a gateway driver checks its own
* credentials/API key.
*/
interface Configurable
{
/**
* Independent of any admin-facing enabled/disabled toggle a caller
* might also apply on top — this is only about whether the driver
* itself is usable right now (e.g. Stripe with no API key configured
* is never usable, regardless of any such toggle).
*/
public function isConfigured(): bool;
}
@@ -2,6 +2,7 @@
namespace Modules\Core\Payment\Contracts;
use Lunar\DataTypes\Price;
use Modules\Core\Payment\DTOs\PaymentResult;
/**
@@ -27,10 +28,10 @@ use Modules\Core\Payment\DTOs\PaymentResult;
interface SupportsAuthorization
{
/**
* Same $type/$data/$context reasoning as SupportsPay::pay().
* Same $type/$amount/$data/$context reasoning as SupportsPay::pay().
*
* @param array<string, mixed> $data
* @param array<string, mixed> $context
*/
public function authorize(string $type, array $data, array $context = []): PaymentResult;
}
public function authorize(string $type, Price $amount, array $data = [], array $context = []): PaymentResult;
}
+10 -5
View File
@@ -2,6 +2,7 @@
namespace Modules\Core\Payment\Contracts;
use Lunar\DataTypes\Price;
use Modules\Core\Payment\DTOs\PaymentResult;
/**
@@ -23,12 +24,16 @@ interface SupportsCaptures
* $reference is the identifier SupportsAuthorization::authorize()
* returned (PaymentResult::$reference) for the hold being settled.
*
* $amount lets a driver capture less than the full authorized amount
* (e.g. shipping less than ordered) — up to the driver/gateway
* whether a partial capture also releases the remainder or leaves it
* capturable again later (multicapture-style gateways).
* $amount is Lunar's own Price (never a gateway's own minor-unit
* scale — see PaymentResult's docblock), and lets a driver capture
* less than the full authorized amount (e.g. shipping less than
* ordered) — up to the driver/gateway whether a partial capture also
* releases the remainder or leaves it capturable again later
* (multicapture-style gateways). Required explicitly, not derived by
* the driver from a live gateway lookup — the caller (whatever placed
* the original authorize() call) already knows it.
*
* @param array<string, mixed> $context
*/
public function capture(string $reference, int $amount, array $context = []): PaymentResult;
public function capture(string $reference, Price $amount, array $context = []): PaymentResult;
}
+13 -6
View File
@@ -2,6 +2,7 @@
namespace Modules\Core\Payment\Contracts;
use Lunar\DataTypes\Price;
use Modules\Core\Payment\DTOs\PaymentResult;
/**
@@ -27,10 +28,16 @@ interface SupportsPay
* one type, because a driver shared across several types needs it to
* look up that type's own config.
*
* $data carries whatever the gateway needs (amount, currency, customer
* details, a payment method token) — the caller's responsibility to
* assemble, since a driver has no notion of a cart or order to pull
* them from itself.
* $amount is required, not optional data a caller might omit — there
* is no way to process a payment without knowing what to charge.
* Lunar's own Price (bundling its own currency) — the same money
* representation every other Payment contract method takes/returns,
* see PaymentResult's own docblock.
*
* $data carries whatever ELSE the gateway needs (customer details, a
* payment method token) — the caller's responsibility to assemble,
* since a driver has no notion of a cart or order to pull them from
* itself.
*
* $context is opaque to the driver — carried through untouched into
* whichever Payment event this call (or a later handleCallback()
@@ -41,5 +48,5 @@ interface SupportsPay
* @param array<string, mixed> $data
* @param array<string, mixed> $context
*/
public function pay(string $type, array $data, array $context = []): PaymentResult;
}
public function pay(string $type, Price $amount, array $data = [], array $context = []): PaymentResult;
}
+7 -3
View File
@@ -2,6 +2,7 @@
namespace Modules\Core\Payment\Contracts;
use Lunar\DataTypes\Price;
use Modules\Core\Payment\DTOs\PaymentResult;
/**
@@ -22,10 +23,13 @@ interface SupportsRefunds
* SupportsCaptures::capture() call returned for the settled funds
* being refunded.
*
* $amount allows a partial refund; a gateway may allow multiple
* partial refunds against one settlement, up to its own total.
* $amount is Lunar's own Price (never a gateway's own minor-unit
* scale — see PaymentResult's docblock), allowing a partial refund; a
* gateway may allow multiple partial refunds against one settlement,
* up to its own total. Required explicitly, same reasoning as
* SupportsCaptures::capture()'s own $amount.
*
* @param array<string, mixed> $context
*/
public function refund(string $reference, int $amount, array $context = []): PaymentResult;
public function refund(string $reference, Price $amount, array $context = []): PaymentResult;
}
+11 -2
View File
@@ -2,6 +2,7 @@
namespace Modules\Core\Payment\Contracts;
use Lunar\DataTypes\Price;
use Modules\Core\Payment\DTOs\PaymentResult;
/**
@@ -20,7 +21,15 @@ interface SupportsVoids
* $reference is the identifier SupportsAuthorization::authorize()
* returned for the hold being released.
*
* $amount is the authorized amount being released — Lunar's own
* Price, same as every other Payment contract method (see
* PaymentResult's own docblock). Required explicitly: the caller
* (whatever placed the original authorize() call) already knows it,
* same reasoning as SupportsCaptures::capture()'s own $amount — a
* driver shouldn't need a live gateway lookup just to know what it's
* releasing.
*
* @param array<string, mixed> $context
*/
public function void(string $reference, array $context = []): PaymentResult;
}
public function void(string $reference, Price $amount, array $context = []): PaymentResult;
}