diff --git a/core/components/minishop3/src/Services/Order/ManagerOrderCostRecalculator.php b/core/components/minishop3/src/Services/Order/ManagerOrderCostRecalculator.php index 4a5f2b9c..c4229f64 100644 --- a/core/components/minishop3/src/Services/Order/ManagerOrderCostRecalculator.php +++ b/core/components/minishop3/src/Services/Order/ManagerOrderCostRecalculator.php @@ -87,7 +87,7 @@ public function recalculate(msOrder $order, array $options = []): array $deliveryCost = $deliveryResult['delivery_cost']; - $paymentBase = round($cartCost + $deliveryCost, 6); + $paymentBase = OrderService::paymentCommissionBase($cartCost); $paymentResult = $this->resolvePaymentFee($order, $paymentBase, $mode, $options); if (!$paymentResult['success']) { return $paymentResult; diff --git a/core/components/minishop3/src/Services/Order/OrderCostCalculator.php b/core/components/minishop3/src/Services/Order/OrderCostCalculator.php index 7e557394..a1379991 100644 --- a/core/components/minishop3/src/Services/Order/OrderCostCalculator.php +++ b/core/components/minishop3/src/Services/Order/OrderCostCalculator.php @@ -186,13 +186,14 @@ public function getPaymentCost(?msOrder $draft, array $orderData, string $token, return $this->success('ms3_order_getcost_success', ['cost' => $paymentCost]); } - // Get cart cost for payment calculation + // Get cart cost for payment calculation (MS2-compatible base: cart only) $cartCostResponse = $this->getCartCost($draft, $token, $ctx); $cartCost = $cartCostResponse['success'] ? $cartCostResponse['data']['cost'] : 0; + $paymentBase = OrderService::paymentCommissionBase((float) $cartCost); - // Payment getCost returns total with payment fee, so subtract cart cost - $costWithPayment = $msPayment->getCost($draft, $cartCost); - $paymentCost = $costWithPayment - $cartCost; + // Payment getCost returns total with payment fee, so subtract base + $costWithPayment = $msPayment->getCost($draft, $paymentBase); + $paymentCost = $costWithPayment - $paymentBase; $response = $this->ms3->utils->invokeEvent('msOnGetPaymentCost', [ 'calculator' => $this, diff --git a/core/components/minishop3/src/Services/Order/OrderService.php b/core/components/minishop3/src/Services/Order/OrderService.php index cc722446..c538b992 100644 --- a/core/components/minishop3/src/Services/Order/OrderService.php +++ b/core/components/minishop3/src/Services/Order/OrderService.php @@ -26,6 +26,14 @@ public function __construct(modX $modx) $this->modx = $modx; } + /** + * Base amount for payment commission (MS2-compatible: cart cost only, delivery excluded). + */ + public static function paymentCommissionBase(float $cartCost): float + { + return round($cartCost, 6); + } + /** * Clamp computed order total so it never goes negative (defence-in-depth vs misconfigured discounts). * diff --git a/core/components/minishop3/tests/PaymentCommissionBaseTest.php b/core/components/minishop3/tests/PaymentCommissionBaseTest.php new file mode 100644 index 00000000..5422af7a --- /dev/null +++ b/core/components/minishop3/tests/PaymentCommissionBaseTest.php @@ -0,0 +1,67 @@ + 0.000001) { + $fail('3% of cart 1000 must be 30, got ' . $fee); +} + +$wrongFee = PriceAdjustment::calculate($cartCost + $deliveryCost, $percent); +if (abs($wrongFee - 45.0) > 0.000001) { + $fail('sanity: 3% of cart+delivery 1500 must be 45'); +} + +if (abs($fee - $wrongFee) < 0.000001) { + $fail('cart-only and cart+delivery bases must differ for this repro'); +} + +$recalculatorSource = file_get_contents(__DIR__ . '/../src/Services/Order/ManagerOrderCostRecalculator.php'); +if ($recalculatorSource === false) { + $fail('cannot read ManagerOrderCostRecalculator.php'); +} + +if (!str_contains($recalculatorSource, 'OrderService::paymentCommissionBase($cartCost)')) { + $fail('ManagerOrderCostRecalculator must use OrderService::paymentCommissionBase($cartCost)'); +} + +if (preg_match('/paymentBase\s*=\s*round\s*\(\s*\$cartCost\s*\+\s*\$deliveryCost/s', $recalculatorSource) === 1) { + $fail('ManagerOrderCostRecalculator must not use cart+delivery as payment base'); +} + +$calculatorSource = file_get_contents(__DIR__ . '/../src/Services/Order/OrderCostCalculator.php'); +if ($calculatorSource === false) { + $fail('cannot read OrderCostCalculator.php'); +} + +if (!str_contains($calculatorSource, 'OrderService::paymentCommissionBase')) { + $fail('OrderCostCalculator must use OrderService::paymentCommissionBase'); +} + +fwrite(STDOUT, "OK PaymentCommissionBaseTest\n"); +exit(0);