Feature: Moving Payment Methods to DB, adding fees, Transaction Updates, Refund Updates, General Updates to Payments
This commit is contained in:
@@ -284,35 +284,39 @@ class InstallLunarCommand extends Command
|
||||
}
|
||||
|
||||
/**
|
||||
* Per-type skip-if-exists, same idempotent convention as
|
||||
* seedStorefrontLabels() — a type already present (including one an
|
||||
* admin has since edited via the Filament Payment Methods resource) is
|
||||
* left untouched. Safe to re-run after a new payment type is added to
|
||||
* config('lunar.payments.types') (e.g. installing a Stripe/Nexi
|
||||
* package), which is the whole reason this isn't a one-time-only seed.
|
||||
* A single, deliberately opinionated starter row on fresh install —
|
||||
* `PaymentMethod` is now fully admin-creatable/deletable (see
|
||||
* docs/payments.md), so this is no longer "seed every config-defined
|
||||
* type," it's "give a fresh store one reasonable payment method to
|
||||
* start from instead of zero." Every value here is a plain literal in
|
||||
* THIS command, not sourced from config or PaymentDriverRegistry — a
|
||||
* driver has no business carrying opinions about what its captured
|
||||
* order status should be called; that's a merchant decision.
|
||||
*
|
||||
* Seeded disabled — a newly-seeded row (whether from this store's
|
||||
* initial install, or a payment provider package installed later)
|
||||
* shouldn't go live for shoppers before staff have actually reviewed
|
||||
* it (real credentials configured, a fee set, etc.) and turned it on
|
||||
* via the Payment Methods resource. See CheckoutService::
|
||||
* getPaymentMethods(), which only offers a type once both 'enabled'
|
||||
* here and its driver's own isConfigured() check pass.
|
||||
* Skip-if-exists on `type`, same idempotent convention as
|
||||
* seedStorefrontLabels() — an admin who has since edited or deleted
|
||||
* this row (via the Filament Payment Methods resource) is left alone;
|
||||
* re-running lunar:install never recreates a deleted starter row.
|
||||
*
|
||||
* Seeded disabled — shouldn't go live for shoppers before staff have
|
||||
* actually reviewed it and turned it on via the Payment Methods
|
||||
* resource. See CheckoutService::getPaymentMethods().
|
||||
*/
|
||||
private function seedPaymentMethods(): void
|
||||
{
|
||||
$existingTypes = PaymentMethod::pluck('type');
|
||||
|
||||
foreach (array_keys(config('lunar.payments.types', [])) as $type) {
|
||||
if ($existingTypes->contains($type)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
PaymentMethod::create([
|
||||
'type' => $type,
|
||||
'enabled' => false,
|
||||
'data' => [],
|
||||
]);
|
||||
if (PaymentMethod::where('type', 'cash-on-delivery')->exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PaymentMethod::create([
|
||||
'type' => 'cash-on-delivery',
|
||||
'name' => 'Cash on Delivery',
|
||||
'driver' => 'offline',
|
||||
'capture_mode' => 'pay',
|
||||
'captured_status' => 'payment-offline',
|
||||
'position' => 0,
|
||||
'enabled' => false,
|
||||
'data' => [],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Core\Command;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Modules\Core\Payment\Models\PaymentMethod;
|
||||
use Modules\Core\Payment\Services\PaymentDriverRegistry;
|
||||
|
||||
/**
|
||||
* Reconciles every Modules\Core\Payment\Models\PaymentMethod row's `driver`
|
||||
* column against PaymentDriverRegistry — the registry only knows "which
|
||||
* driver classes exist THIS deploy," and only at the moment something
|
||||
* calls resolve(); nothing else notices a driver disappearing (a package
|
||||
* removed, a custom Registry::register() call deleted) on its own. Meant
|
||||
* to run unconditionally on every container start/deploy (alongside
|
||||
* `migrate`), not on a schedule — "did the set of registered drivers
|
||||
* change" is a deploy-time event, cheap enough to check every single time
|
||||
* regardless of whether anything actually changed. See docs/payments.md.
|
||||
*
|
||||
* Sets/clears `driver_missing_at` — deliberately NOT the `enabled` column,
|
||||
* so an admin's own manual toggle is never confused with "the driver
|
||||
* vanished," and a driver that comes back in a later deploy auto-clears
|
||||
* this with no admin action needed.
|
||||
*/
|
||||
class SyncPaymentDriversCommand extends Command
|
||||
{
|
||||
protected $signature = 'boboko:payment:sync-drivers';
|
||||
|
||||
protected $description = 'Flag PaymentMethod rows whose driver no longer resolves via the registry, and clear the flag for ones that do again';
|
||||
|
||||
public function handle(PaymentDriverRegistry $registry): int
|
||||
{
|
||||
$missing = 0;
|
||||
$restored = 0;
|
||||
|
||||
PaymentMethod::query()->each(function (PaymentMethod $method) use ($registry, &$missing, &$restored) {
|
||||
$resolves = $method->driver !== null && $registry->resolve($method->driver) !== null;
|
||||
|
||||
if (! $resolves && $method->driver_missing_at === null) {
|
||||
$method->update(['driver_missing_at' => now()]);
|
||||
$missing++;
|
||||
} elseif ($resolves && $method->driver_missing_at !== null) {
|
||||
$method->update(['driver_missing_at' => null]);
|
||||
$restored++;
|
||||
}
|
||||
});
|
||||
|
||||
$this->components->info("Payment driver sync complete: {$missing} newly flagged, {$restored} restored.");
|
||||
|
||||
return self::SUCCESS;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user