Skip to content

Commit 9ce835b

Browse files
committed
[0007917] Fix tracking carrier country not restored on page reload.
1 parent 129b1ff commit 9ce835b

4 files changed

Lines changed: 69 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1111
- [0007914](https://bugs.oxid-esales.com/view.php?id=7914): Fix Pay upon Invoice (PUI) broken after 2.8.1 security patch. The `_executePayment()` reject guard blocked PUI because it matched `isPayPalPayment()` but was not handled by any prior flow (not a button/proxy/UAPM/checkout payment). Added `gatewaypayment` flag to `PayPalDefinitions` and `isGatewayPayment()` method so PUI correctly falls through to OXID's core `PaymentGateway`.
1212
- [0007915](https://bugs.oxid-esales.com/view.php?id=7915): Fix fatal error "Call to a member function getId() on null" on product detail page when an out-of-stock variant is in the basket. `hasProductVariantInBasket()` delegated to `Basket::getArtStockInBasket()` which calls `getArticle(true)` (buyable-check). For out-of-stock variants this returns null. Replaced with direct basket iteration using `getArticle(false)` to skip the buyable check.
1313
- [0007916](https://bugs.oxid-esales.com/view.php?id=7916): Fix orphaned oscpaypal_order rows with OSCPAYPALSTATUS=COMPLETED and empty OXORDERID. When `sess_challenge` was cleared before `captureOrder()` completed (e.g. by a concurrent cancel request), the capture flow proceeded and created tracking records that could not be matched by webhook processing. Added defense-in-depth validation at four levels: `AjaxPaymentController::captureOrder()` now aborts if the shop order cannot be resolved, `PayPalOrderCompletedSubscriber` rejects events with empty shopOrderId, `Payment::trackPayPalOrder()` throws on empty shopOrderId, and `OrderRepository::paypalOrderByOrderIdAndPayPalId()` refuses to create new records with empty shopOrderId.
14+
- [0007917](https://bugs.oxid-esales.com/view.php?id=7917): Fix tracking carrier country not restored on page reload. When a carrier from the "global" country group was saved, the country dropdown was reset to the order's shipping/billing country instead. Added `getCountryCodeByCarrierKey()` to `PayPalTrackingCarrierList` and `getEffectiveTrackingCountryCode()` to `OrderMain` to resolve the saved carrier's country and pre-select it in the dropdown.
1415

1516
## [2.8.1] - 2026-03-19
1617

metadata.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@
6969
'en' => 'Use of the online payment service from PayPal. Documentation: <a href="https://docs.oxid-esales.com/modules/paypal-checkout/en/latest/" target="_blank">PayPal Checkout</a>'
7070
],
7171
'thumbnail' => 'out/img/paypal.png',
72-
'version' => '2.8.2-rc.1',
72+
'version' => '2.8.2-rc.2',
7373
'author' => 'OXID eSales AG',
7474
'url' => 'https://www.oxid-esales.com',
7575
'email' => 'info@oxid-esales.com',

src/Controller/Admin/OrderMain.php

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ class OrderMain extends OrderMain_parent
2828
/** @var array|null */
2929
protected $trackingCarrierCountries = null;
3030

31+
/** @var string|null */
32+
protected $effectiveTrackingCountryCode = null;
33+
3134
/**
3235
* @throws ApiException
3336
* @throws StandardException
@@ -90,7 +93,7 @@ public function getPayPalTrackingCarrierCountries(): array
9093
$this->trackingCarrierCountries[$allowedCountry] = [
9194
'id' => $allowedCountry,
9295
'title' => $countryTitle,
93-
'selected' => ($this->getPayPalOrderCountryCode() === $allowedCountry)
96+
'selected' => ($this->getEffectiveTrackingCountryCode() === $allowedCountry)
9497
];
9598
}
9699
}
@@ -103,7 +106,7 @@ public function getPayPalTrackingCarrierProvider($countryCode = ''): array
103106
$order = $this->getOrder();
104107
$savedTrackingCarrierId = $order->getPayPalTrackingCarrier();
105108

106-
$countryCode = $countryCode ?: $this->getPayPalOrderCountryCode();
109+
$countryCode = $countryCode ?: $this->getEffectiveTrackingCountryCode();
107110

108111
if ($countryCode) {
109112
$trackingCarrierList = oxNew(PayPalTrackingCarrierList::class);
@@ -155,4 +158,30 @@ public function getPayPalOrderCountryCode(): string
155158

156159
return $countryCode;
157160
}
161+
162+
/**
163+
* Returns the country code that should be pre-selected in the tracking carrier country dropdown.
164+
* If a carrier is already saved, returns the country the carrier belongs to.
165+
* Otherwise falls back to the order's country.
166+
*
167+
* @throws StandardException
168+
*/
169+
protected function getEffectiveTrackingCountryCode(): string
170+
{
171+
if (is_null($this->effectiveTrackingCountryCode)) {
172+
$savedCarrierKey = $this->getOrder()->getPayPalTrackingCarrier();
173+
$this->effectiveTrackingCountryCode = '';
174+
175+
if ($savedCarrierKey) {
176+
$trackingCarrierList = oxNew(PayPalTrackingCarrierList::class);
177+
$this->effectiveTrackingCountryCode = $trackingCarrierList->getCountryCodeByCarrierKey($savedCarrierKey);
178+
}
179+
180+
if (!$this->effectiveTrackingCountryCode) {
181+
$this->effectiveTrackingCountryCode = $this->getPayPalOrderCountryCode();
182+
}
183+
}
184+
185+
return $this->effectiveTrackingCountryCode;
186+
}
158187
}

src/Model/PayPalTrackingCarrierList.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,42 @@ public function loadTrackingCarriers(string $countryCode = '')
4747
* Load allowed Tracking-Carrier Country-Codes
4848
*
4949
*/
50+
/**
51+
* Find the country code for a given carrier key
52+
*
53+
* @param string $carrierKey
54+
* @return string empty string if not found
55+
*/
56+
public function getCountryCodeByCarrierKey(string $carrierKey): string
57+
{
58+
if (!$carrierKey) {
59+
return '';
60+
}
61+
62+
$baseObject = $this->getBaseObject();
63+
$viewName = $baseObject->getViewName();
64+
$queryBuilderFactory = $this->getServiceFromContainer(QueryBuilderFactoryInterface::class);
65+
/** @var QueryBuilder $queryBuilder */
66+
$queryBuilder = $queryBuilderFactory->create();
67+
68+
/** @var Result $resultDB */
69+
$resultDB = $queryBuilder->select('oxcountrycode')
70+
->from($viewName)
71+
->where('oxkey = :oxkey')
72+
->setParameter(':oxkey', $carrierKey)
73+
->setMaxResults(1)
74+
->execute();
75+
76+
if (is_a($resultDB, Result::class)) {
77+
$row = $resultDB->fetchAssociative();
78+
if ($row) {
79+
return (string) $row['oxcountrycode'];
80+
}
81+
}
82+
83+
return '';
84+
}
85+
5086
public function getAllowedTrackingCarrierCountryCodes(): array
5187
{
5288
$result = [];

0 commit comments

Comments
 (0)