50 lines
1.8 KiB
PHP
50 lines
1.8 KiB
PHP
<?php
|
|
|
|
namespace Modules\Core\Payment\Pipelines\Cart;
|
|
|
|
use Closure;
|
|
use Lunar\Base\ValueObjects\Cart\ShippingBreakdownItem;
|
|
use Lunar\DataTypes\Price;
|
|
use Lunar\Models\Contracts\Cart as CartContract;
|
|
use Modules\Core\Payment\Models\PaymentMethod;
|
|
|
|
final class ApplyPaymentMethodFee
|
|
{
|
|
/**
|
|
* Called just before cart totals are calculated, right after
|
|
* Lunar\Pipelines\Cart\ApplyShipping. Generic across every
|
|
* Modules\Core\Payment\Models\PaymentMethod row, not just cash on
|
|
* delivery — whichever type the shopper picked (Cart::meta
|
|
* ['payment_method']), its own `data.fee` (set via the Filament "Edit
|
|
* fee" action) is applied if present, no matter its slug/name/driver.
|
|
*
|
|
* Must add the fee as its own Lunar\Base\ValueObjects\Cart\
|
|
* ShippingBreakdownItem on $cart->shippingBreakdown rather than
|
|
* bumping $cart->shippingTotal directly — the later Lunar\Pipelines\
|
|
* Cart\CalculateTax step unconditionally recomputes shippingTotal
|
|
* (and shipping tax) from shippingBreakdown's item sum, so a value
|
|
* set only on the plain property is silently discarded before the
|
|
* cart finishes calculating.
|
|
*
|
|
* @param Closure(CartContract): mixed $next
|
|
*/
|
|
public function handle(CartContract $cart, Closure $next): mixed
|
|
{
|
|
$type = $cart->meta['payment_method'] ?? null;
|
|
|
|
if ($type) {
|
|
$fee = (int) (PaymentMethod::where('type', $type)->first()?->data['fee'] ?? 0);
|
|
|
|
if ($fee > 0) {
|
|
$cart->shippingBreakdown->items->put('payment-method-fee', new ShippingBreakdownItem(
|
|
name: 'Payment method fee',
|
|
identifier: 'payment-method-fee',
|
|
price: new Price($fee, $cart->currency, 1),
|
|
));
|
|
}
|
|
}
|
|
|
|
return $next($cart);
|
|
}
|
|
}
|