Hello. I am experiencing a weird problem with shipping calculations.
I have a checkout page, where the shipping method and cost is calculated (by calling a ‘set-shipping’ route with fetch
) based on the selected shipping country. Upon visiting this checkout page, a default shipping product is added for the default country.
I am adding this default shipping product with this code:
// controllers/checkout.php
...
$cart = merx()->cart();
// I first remove all shipping products, because selecting another country adds a shipping product on top of the default one.
removeAllShippingMethods($cart);
$cart->add([
'id' => $defaultShippingMethod->id(),
'type' => 'shipping',
'price' => cartSumAboveFreeShipping($defaultShippingMethod) ? 0 : (float) $defaultShippingMethod->price()->value()
]);
...
Everything works so far. The problem presents itself when the payment is performed. No matter which shipping method is selected, the default shipping product is always passed to the payment method (Stripe). Curiously, the correct shipping method (the one selected by the user) is registered on the order page created by Merx.
Ι updated this post many times (10 so far!) to not flood the topic. Sorry!
I found out that by adding the shipping product via fetch
, the product seems to be added on the page, but is not passed to payment. Only if I refresh the checkout page this product is actually added.
My shipping route:
[
'pattern' => 'shop-api/set-shipping',
'method' => 'POST',
'action' => function() {
try {
$data = kirby()->request()->data();
$method = kirby()->page($data['method']);
$method_data = [
'name' => $method->title()->value(),
'from' => $method->from()->value(),
'to' => $method->to()->value(),
'price' => cartSumAboveFreeShipping($method) ? 0 : formatCurrency($method->price()->value())
];
$cart = merx()->cart();
removeAllShipping($cart);
$cart->add([
'id' => $method->id(),
'type' => 'shipping',
'price' => cartSumAboveFreeShipping($method) ? 0 : (float) $method->price()->value()
]);
return [
'status' => 200,
'method' => $method_data,
'itemsBuildTime' => allItemsBuildTime(),
'cart' => [
'subtotal' => formatCurrency($cart->filterBy('type', 'product')->getSum()),
'total' => formatCurrency($cart->getSum()),
]
];
} catch (Kirby\Exception\Exception $ex) {
return $ex->toArray();
}
},
],
Ο, I solved it. I was always using the same StripePaymentIntent that I set in the checkout controller. It needed to be created after all the peoduct changes.