PluginProbe ʕ •ᴥ•ʔ
WooCommerce / 10.9.4
WooCommerce v10.9.4
10.9.4 10.9.3 10.9.2 10.9.1 10.9.0 10.9.0-rc.1 10.9.0-beta.2 10.9.0-beta.1 10.8.1 10.8.0 10.8.0-rc.1 10.8.0-beta.2 10.8.0-beta.1 7.8.0-beta.1 7.8.0-beta.2 7.8.0-rc.1 7.8.0-rc.2 7.8.1 7.8.2 7.8.3 7.8.4 7.9.0 7.9.0-beta.1 7.9.0-beta.2 7.9.0-rc.2 7.9.0-rc.3 7.9.1 7.9.2 8.0.0 8.0.0-beta.1 8.0.0-beta.2 8.0.0-rc.1 8.0.0-rc.2 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.1.0 8.1.0-beta.1 8.1.0-rc.1 8.1.0-rc.2 8.1.1 8.1.2 8.1.3 8.1.4 8.2.0 8.2.0-beta.1 8.2.0-rc.1 8.2.0-rc.2 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.3.0 8.3.0-beta.1 8.3.0-rc.1 8.3.0-rc.2 8.3.1 8.3.2 8.3.3 8.3.4 8.4.0 8.4.0-beta.1 8.4.0-rc.1 8.4.1 8.4.2 8.4.3 8.5.0 8.5.0-beta.1 8.5.0-rc.1 8.5.1 8.5.2 8.5.3 8.5.4 8.5.5 8.6.0 8.6.0-beta.1 8.6.0-rc.1 8.6.1 8.6.2 8.6.3 8.6.4 8.7.0 8.7.0-beta.1 8.7.0-beta.2 8.7.0-rc.1 8.7.1 8.7.2 8.7.3 8.8.0 8.8.0-beta.1 8.8.0-rc.1 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.8.6 8.8.7 8.9.0 8.9.0-beta.1 8.9.0-rc.1 8.9.1 8.9.2 8.9.3 8.9.4 8.9.5 9.0.0 9.0.0-beta.1 9.0.0-beta.2 9.0.0-rc.1 9.0.1 9.0.2 9.0.3 9.0.4 9.1.0 9.1.0-beta.1 9.1.0-rc.1 9.1.1 9.1.2 9.1.3 9.1.4 9.1.5 9.1.6 9.2.0 9.2.0-beta.1 9.2.0-rc.1 9.2.1 9.2.2 9.2.3 9.2.4 9.2.5 9.3.0 9.3.0-beta.1 9.3.0-rc.1 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.3.6 9.4.0 9.4.0-beta.1 9.4.0-beta.2 9.4.0-rc.1 9.4.0-rc.2 9.4.0-rc.3 9.4.0-rc.4 9.4.1 9.4.2 9.4.3 9.4.4 9.4.5 9.5.0 9.5.0-beta.1 9.5.0-beta.2 9.5.0-rc.1 9.5.1 9.5.2 9.5.3 9.5.4 9.6.0 9.6.0-beta.1 9.6.0-beta.2 9.6.0-rc.1 9.6.1 9.6.2 9.6.3 9.6.4 9.7.0 9.7.0-beta.1 9.7.0-rc.1 9.7.1 9.7.2 9.7.3 9.8.0 9.8.0-beta.1 9.8.0-rc.1 9.8.1 9.8.2 9.8.3 9.8.4 9.8.5 9.8.6 9.8.7 9.9.0 9.9.0-beta.1 9.9.0-rc.1 9.9.1 9.9.2 9.9.3 9.9.4 9.9.5 9.9.6 9.9.7 3.7.3 7.1.2 3.8.0 7.2.0 3.8.0-beta.1 7.2.0-beta.1 3.8.0-rc.1 7.2.0-beta.2 3.8.0-rc.2 7.2.0-rc.1 3.8.1 7.2.0-rc.2 3.8.2 7.2.1 3.8.3 7.2.2 3.9.0 7.2.3 3.9.0-beta.1 7.2.4 3.9.0-beta.2 7.3.0 3.9.0-rc.1 7.3.0-beta.1 3.9.0-rc.2 7.3.0-beta.2 3.9.0-rc.3 7.3.0-rc.1 3.9.0-rc.4 7.3.0-rc.2 3.9.1 7.3.1 3.9.2 7.4.0 3.9.3 7.4.0-beta.1 3.9.4 7.4.0-beta.2 3.9.5 7.4.0-rc.1 4.0.0 7.4.0-rc.2 4.0.0-beta.1 7.4.1 4.0.0-rc.1 7.4.2 4.0.0-rc.2 7.5.0 4.0.1 7.5.0-beta.1 4.0.2 7.5.0-beta.2 4.0.3 7.5.0-rc.1 4.0.4 7.5.1 4.1.0 7.5.2 4.1.0-beta.1 7.6.0 4.1.0-beta.2 7.6.0-beta.1 4.1.0-rc.1 7.6.0-beta.2 4.1.0-rc.2 7.6.0-rc.1 4.1.1 7.6.0-rc.2 4.1.2 7.6.0-rc.3 4.1.3 7.6.1 4.1.4 7.6.2 4.2.0 7.7.0 4.2.0-RC.1 7.7.0-beta.1 4.2.0-RC.2 7.7.0-beta.2 4.2.0-beta.1 7.7.0-rc.1 4.2.1 7.7.1 4.2.2 7.7.2 4.2.3 7.7.3 4.2.4 7.8.0 4.2.5 4.3.0 4.3.0-beta.1 4.3.0-rc.1 4.3.0-rc.2 4.3.0-rc.3 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.4.0 4.4.0-beta.1 4.4.0-rc.1 4.4.1 4.4.2 4.4.3 4.4.4 4.5.0 4.5.0-beta.1 4.5.0-rc.1 4.5.0-rc.3 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6.0 4.6.0-beta.1 4.6.0-rc.1 4.6.1 4.6.2 4.6.3 4.6.4 4.6.5 4.7.0 4.7.0-beta.1 4.7.0-beta.2 4.7.0-rc.1 4.7.1 4.7.1-beta.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.0-beta.1 4.8.0-rc.1 4.8.0-rc.2 4.8.1 4.8.2 4.8.3 4.9.0 4.9.0-beta.1 4.9.0-rc.1 4.9.0-rc.2 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 5.0.0 5.0.0-beta.1 5.0.0-beta.2 5.0.0-rc.1 5.0.0-rc.2 5.0.0-rc.3 5.0.1 5.0.2 5.0.3 5.1.0 5.1.0-beta.1 5.1.0-rc.1 trunk 5.1.1 10.0.0 5.1.2 10.0.0-rc.1 5.1.3 10.0.0-rc.2 5.2.0 10.0.1 5.2.0-beta.1 10.0.2 5.2.0-rc.1 10.0.3 5.2.0-rc.2 10.0.4 5.2.1 10.0.5 5.2.2 10.0.6 5.2.3 10.1.0 5.2.4 10.1.0-rc.1 5.2.5 10.1.0-rc.2 5.3.0 10.1.0-rc.3 5.3.0-beta.1 10.1.0-rc.4 5.3.0-rc.1 10.1.1 5.3.0-rc.2 10.1.2 5.3.1 10.1.3 5.3.2 10.1.4 5.3.3 10.2.0 5.4.0 10.2.0-beta.1 5.4.0-beta.1 10.2.0-beta.2 5.4.0-rc.1 10.2.0-rc.1 5.4.1 10.2.1 5.4.2 10.2.2 5.4.3 10.2.3 5.4.4 10.2.4 5.4.5 10.3.0 5.5.0 10.3.0-beta.1 5.5.0-beta.1 10.3.0-beta.2 5.5.0-rc.1 10.3.0-rc.1 5.5.0-rc.2 10.3.0-rc.2 5.5.1 10.3.1 5.5.2 10.3.2 5.5.3 10.3.3 5.5.4 10.3.4 5.5.5 10.3.5 5.6.0 10.3.6 5.6.0-beta.1 10.3.7 5.6.0-rc.1 10.3.8 5.6.0-rc.2 10.4.0 5.6.1 10.4.0-beta.1 5.6.2 10.4.0-beta.2 5.6.3 10.4.0-rc.1 5.7.0 10.4.1 5.7.0-beta.1 10.4.2 5.7.0-rc.1 10.4.3 5.7.1 10.4.4 5.7.2 10.5.0 5.7.3 10.5.0-beta.1 5.8.0 10.5.0-beta.2 5.8.0-beta.1 10.5.0-rc.1 5.8.0-beta.2 10.5.0-rc.2 5.8.0-rc.1 10.5.0-rc.3 5.8.1 10.5.1 5.8.2 10.5.2 5.9.0 10.5.3 5.9.0-beta.1 10.6.0 5.9.0-rc.1 10.6.0-beta.1 5.9.0-rc.2 10.6.0-beta.2 5.9.1 10.6.0-rc.1 5.9.2 10.6.1 6.0.0 10.6.2 6.0.0-beta.1 10.7.0 6.0.0-rc.1 10.7.0-beta.1 6.0.1 10.7.0-beta.2 6.0.2 10.7.0-rc.1 6.1.0 3.0.0 6.1.0-beta.1 3.0.1 6.1.0-rc.1 3.0.2 6.1.0-rc.2 3.0.3 6.1.1 3.0.4 6.1.2 3.0.5 6.1.3 3.0.6 6.2.0 3.0.7 6.2.0-beta.1 3.0.8 6.2.0-rc.1 3.0.9 6.2.0-rc.2 3.1.0 6.2.1 3.1.1 6.2.2 3.1.2 6.2.3 3.2.0 6.3.0 3.2.1 6.3.0-beta.1 3.2.2 6.3.0-rc.1 3.2.3 6.3.0-rc.2 3.2.4 6.3.1 3.2.5 6.3.2 3.2.6 6.4.0 3.3.0 6.4.0-beta.1 3.3.1 6.4.0-rc.1 3.3.2 6.4.1 3.3.2-rc.1 6.4.2 3.3.3 6.5.0 3.3.4 6.5.0-beta.1 3.3.5 6.5.0-rc.1 3.3.6 6.5.0-rc.2 3.4.0 6.5.1 3.4.0-beta.1 6.5.2 3.4.0-rc.2 6.6.0 3.4.1 6.6.0-beta.1 3.4.2 6.6.0-rc.1 3.4.3 6.6.0-rc.2 3.4.4 6.6.1 3.4.5 6.6.2 3.4.6 6.7.0 3.4.7 6.7.0-beta.1 3.4.8 6.7.0-beta.2 3.5.0 6.7.0-rc.1 3.5.0-beta.1 6.7.1 3.5.0-rc.1 6.8.0 3.5.0-rc.2 6.8.0-beta.1 3.5.1 6.8.0-beta.2 3.5.10 6.8.0-rc.1 3.5.2 6.8.1 3.5.3 6.8.2 3.5.4 6.8.3 3.5.5 6.9.0 3.5.6 6.9.0-beta.1 3.5.7 6.9.0-beta.2 3.5.8 6.9.0-rc.1 3.5.9 6.9.1 3.6.0 6.9.2 3.6.0-beta.1 6.9.3 3.6.0-rc.1 6.9.4 3.6.0-rc.2 6.9.5 3.6.0-rc.3 7.0.0 3.6.1 7.0.0-beta.1 3.6.2 7.0.0-beta.2 3.6.3 7.0.0-beta.3 3.6.4 7.0.0-rc.1 3.6.5 7.0.0-rc.2 3.6.6 7.0.1 3.6.7 7.0.2 3.7.0 7.1.0 3.7.0-beta.1 7.1.0-beta.1 3.7.0-rc.1 7.1.0-beta.2 3.7.0-rc.2 7.1.0-rc.1 3.7.1 7.1.0-rc.2 3.7.2 7.1.1
woocommerce / src / Admin / Features / Fulfillments / Providers / AustraliaPostShippingProvider.php
woocommerce / src / Admin / Features / Fulfillments / Providers Last commit date
ACSCourierShippingProvider.php 3 months ago AbstractShippingProvider.php 3 months ago AmazonLogisticsShippingProvider.php 3 months ago AnPostShippingProvider.php 3 months ago ArasKargoShippingProvider.php 3 months ago AustraliaPostShippingProvider.php 3 months ago AzerpostShippingProvider.php 3 months ago BartoliniBRTShippingProvider.php 3 months ago BelpochtaShippingProvider.php 3 months ago BpostShippingProvider.php 3 months ago BulgarianPostsShippingProvider.php 3 months ago CDEKShippingProvider.php 3 months ago CTTShippingProvider.php 3 months ago CanadaPostShippingProvider.php 3 months ago CeskaPostaShippingProvider.php 3 months ago ChronopostShippingProvider.php 3 months ago CorreosShippingProvider.php 3 months ago CustomShippingProvider.php 3 months ago CyprusPostShippingProvider.php 3 months ago DHLShippingProvider.php 3 months ago DPDShippingProvider.php 3 months ago DeutschePostShippingProvider.php 3 months ago ELTAShippingProvider.php 3 months ago EcontShippingProvider.php 3 months ago EimskipShippingProvider.php 3 months ago EvriHermesShippingProvider.php 3 months ago FanCourierShippingProvider.php 3 months ago FastwayShippingProvider.php 3 months ago FedExShippingProvider.php 3 months ago GLSShippingProvider.php 3 months ago GenikiTaxydromikiShippingProvider.php 3 months ago HayPostShippingProvider.php 3 months ago HelthjemShippingProvider.php 3 months ago HrvatskaPostaShippingProvider.php 3 months ago InPostShippingProvider.php 3 months ago IslandsposturShippingProvider.php 3 months ago ItellaShippingProvider.php 3 months ago KazpostShippingProvider.php 3 months ago LaPosteColissimoShippingProvider.php 3 months ago LasershipOntracShippingProvider.php 3 months ago LatvijasPastsShippingProvider.php 3 months ago LiechtensteinischePostShippingProvider.php 3 months ago MPLShippingProvider.php 3 months ago MRWShippingProvider.php 3 months ago MagyarPostaShippingProvider.php 3 months ago MakedonskaPostaShippingProvider.php 3 months ago MaltaPostShippingProvider.php 3 months ago MatkahuoltoShippingProvider.php 3 months ago MondialRelayShippingProvider.php 3 months ago NewZealandPostShippingProvider.php 3 months ago NovaPoshtaShippingProvider.php 3 months ago OmnivaShippingProvider.php 3 months ago OsterreichischePostShippingProvider.php 3 months ago ParcelForceShippingProvider.php 3 months ago PocztaPolskaShippingProvider.php 3 months ago PostLuxembourgShippingProvider.php 3 months ago PostNLShippingProvider.php 3 months ago PostNordShippingProvider.php 3 months ago PostaMoldoveiShippingProvider.php 3 months ago PostaRomanaShippingProvider.php 3 months ago PosteItalianeShippingProvider.php 3 months ago PosteSanMarinoShippingProvider.php 3 months ago PostenNorgeBringShippingProvider.php 3 months ago PurolatorShippingProvider.php 3 months ago RoyalMailShippingProvider.php 3 months ago RussianPostShippingProvider.php 3 months ago SDAShippingProvider.php 3 months ago SeurShippingProvider.php 3 months ago SlovenskaPostaShippingProvider.php 3 months ago SpeeDeeDeliveryShippingProvider.php 3 months ago StarTrackShippingProvider.php 3 months ago SwissPostShippingProvider.php 3 months ago TollShippingProvider.php 3 months ago UPSShippingProvider.php 3 months ago USPSShippingProvider.php 3 months ago UkrposhtaShippingProvider.php 3 months ago UrgentCargusShippingProvider.php 3 months ago YurticiKargoShippingProvider.php 3 months ago ZasilkovnaShippingProvider.php 3 months ago
AustraliaPostShippingProvider.php
219 lines
1 <?php declare(strict_types=1);
2
3 namespace Automattic\WooCommerce\Admin\Features\Fulfillments\Providers;
4
5 use Automattic\WooCommerce\Admin\Features\Fulfillments\FulfillmentUtils;
6
7 /**
8 * Australia Post Shipping Provider class.
9 *
10 * Provides Australia Post tracking number validation, supported countries, and tracking URL generation.
11 */
12 class AustraliaPostShippingProvider extends AbstractShippingProvider {
13
14 /**
15 * Australia Post tracking number patterns with enhanced service detection.
16 *
17 * @var array<string, array{patterns: array<int, string>, confidence: int}>
18 */
19 private const TRACKING_PATTERNS = array(
20 'AU' => array( // Australia.
21 'patterns' => array(
22 // International UPU S10 format with validation.
23 '/^[A-Z]{2}\d{9}AU$/', // XX#########AU.
24 '/^[A-Z]{2}\d{7}AU$/', // Alternative international format: XX#######AU.
25
26 // Domestic numeric tracking formats.
27 '/^\d{13}$/', // 13-digit domestic tracking.
28 '/^\d{12}$/', // 12-digit domestic tracking.
29 '/^\d{11}$/', // 11-digit domestic tracking.
30
31 // Standard alphanumeric formats.
32 '/^[A-Z]{2}\d{8}[A-Z]{2}$/', // Standard format: XX########XX.
33 '/^[A-Z]{1}\d{10}[A-Z]{1}$/', // Domestic format: X##########X.
34
35 // Service-specific patterns.
36 '/^[A-Z]{4}\d{8}$/', // Express Post format: XXXX########.
37 '/^EP\d{10}$/', // Express Post specific.
38 '/^ST\d{10}$/', // StarTrack (freight).
39 '/^MB\d{10}$/', // MyPost Business.
40 '/^PO\d{10}$/', // Post Office Box.
41
42 // MyPost Digital formats.
43 '/^MP\d{10,12}$/', // MyPost tracking.
44 '/^DG\d{10,12}$/', // Digital tracking.
45
46 // Parcel numeric formats.
47 '/^7\d{15}$/', // 16-digit format starting with 7.
48 '/^3\d{15}$/', // 16-digit format starting with 3.
49 '/^8\d{15}$/', // 16-digit format starting with 8.
50
51 // eParcel formats.
52 '/^[A-Z]{3}\d{8,12}$/', // Three-letter prefix.
53 '/^33\d?[A-Z]{2}\d{18,20}$/', // StarTrack eParcel.
54 '/^AP\d{10,13}$/', // Australia Post eParcel.
55
56 // Legacy and alternative formats.
57 '/^[0-9]{10}[A-Z]{2}$/', // 10 digits + 2 letters.
58 '/^[A-Z]{1}\d{8}[A-Z]{3}$/', // Alternative format.
59 ),
60 'confidence' => 90,
61 ),
62 );
63
64 /**
65 * Get the unique key for this shipping provider.
66 *
67 * @return string Unique key.
68 */
69 public function get_key(): string {
70 return 'australia-post';
71 }
72
73 /**
74 * Get the name of this shipping provider.
75 *
76 * @return string Name of the shipping provider.
77 */
78 public function get_name(): string {
79 return 'Australia Post';
80 }
81
82 /**
83 * Get the icon URL for this shipping provider.
84 *
85 * @return string URL of the shipping provider icon.
86 */
87 public function get_icon(): string {
88 return esc_url( WC()->plugin_url() ) . '/assets/images/shipping_providers/australia-post.png';
89 }
90
91 /**
92 * Get the countries this shipping provider can ship from.
93 *
94 * @return array List of country codes.
95 */
96 public function get_shipping_from_countries(): array {
97 return array_keys( self::TRACKING_PATTERNS );
98 }
99
100 /**
101 * Get the countries this shipping provider can ship to.
102 *
103 * Australia Post ships internationally, so we return a comprehensive list.
104 *
105 * @return array List of country codes.
106 */
107 public function get_shipping_to_countries(): array {
108 return array( 'AD', 'AE', 'AF', 'AG', 'AI', 'AL', 'AM', 'AO', 'AR', 'AS', 'AT', 'AU', 'AW', 'AZ', 'BA', 'BB', 'BD', 'BE', 'BF', 'BG', 'BH', 'BI', 'BJ', 'BM', 'BN', 'BO', 'BR', 'BS', 'BT', 'BW', 'BY', 'BZ', 'CA', 'CC', 'CD', 'CF', 'CG', 'CH', 'CI', 'CK', 'CL', 'CM', 'CN', 'CO', 'CR', 'CU', 'CV', 'CW', 'CY', 'CZ', 'DE', 'DJ', 'DK', 'DM', 'DO', 'DZ', 'EC', 'EE', 'EG', 'ER', 'ES', 'ET', 'FI', 'FJ', 'FK', 'FM', 'FO', 'FR', 'GA', 'GB', 'GD', 'GE', 'GF', 'GG', 'GH', 'GI', 'GL', 'GM', 'GN', 'GP', 'GQ', 'GR', 'GS', 'GT', 'GU', 'GW', 'GY', 'HK', 'HN', 'HR', 'HT', 'HU', 'ID', 'IE', 'IL', 'IM', 'IN', 'IO', 'IQ', 'IR', 'IS', 'IT', 'JE', 'JM', 'JO', 'JP', 'KE', 'KG', 'KH', 'KI', 'KP', 'KR', 'KW', 'KY', 'KZ', 'LA', 'LB', 'LC', 'LI', 'LK', 'LR', 'LS', 'LT', 'LU', 'LV', 'LY', 'MA', 'MC', 'MD', 'ME', 'MF', 'MG', 'MH', 'MK', 'ML', 'MM', 'MN', 'MO', 'MP', 'MQ', 'MR', 'MS', 'MT', 'MU', 'MV', 'MW', 'MX', 'MY', 'MZ', 'NA', 'NC', 'NE', 'NF', 'NG', 'NI', 'NL', 'NO', 'NP', 'NR', 'NU', 'NZ', 'OM', 'PA', 'PE', 'PF', 'PG', 'PH', 'PK', 'PL', 'PM', 'PN', 'PR', 'PS', 'PT', 'PW', 'PY', 'QA', 'RE', 'RO', 'RS', 'RU', 'RW', 'SA', 'SB', 'SC', 'SD', 'SE', 'SG', 'SH', 'SI', 'SK', 'SL', 'SM', 'SN', 'SO', 'SR', 'SS', 'ST', 'SV', 'SX', 'SY', 'SZ', 'TC', 'TD', 'TF', 'TG', 'TH', 'TJ', 'TK', 'TL', 'TM', 'TN', 'TO', 'TR', 'TT', 'TV', 'TW', 'TZ', 'UA', 'UG', 'UM', 'US', 'UY', 'UZ', 'VA', 'VC', 'VE', 'VG', 'VI', 'VN', 'VU', 'WF', 'WS', 'YE', 'YT', 'ZA', 'ZM', 'ZW' );
109 }
110
111 /**
112 * Get the tracking URL for a given tracking number.
113 *
114 * @param string $tracking_number The tracking number to generate the URL for.
115 * @return string The tracking URL.
116 */
117 public function get_tracking_url( string $tracking_number ): string {
118 return 'https://auspost.com.au/mypost/track/details/' . rawurlencode( $tracking_number );
119 }
120
121 /**
122 * Validate tracking number against country-specific patterns.
123 *
124 * @param string $tracking_number The tracking number to validate.
125 * @param string $country_code The country code for the shipment.
126 * @return bool True if valid, false otherwise.
127 */
128 private function validate_country_pattern( string $tracking_number, string $country_code ): bool {
129 if ( ! isset( self::TRACKING_PATTERNS[ $country_code ] ) ) {
130 return false;
131 }
132
133 foreach ( self::TRACKING_PATTERNS[ $country_code ]['patterns'] as $pattern ) {
134 if ( preg_match( $pattern, $tracking_number ) ) {
135 return true;
136 }
137 }
138 return false;
139 }
140
141 /**
142 * Try to parse an Australia Post tracking number.
143 *
144 * @param string $tracking_number The tracking number to parse.
145 * @param string $shipping_from The country code of the shipping origin.
146 * @param string $shipping_to The country code of the shipping destination.
147 * @return array|null An array with 'url' and 'ambiguity_score' if valid, null otherwise.
148 */
149 public function try_parse_tracking_number(
150 string $tracking_number,
151 string $shipping_from,
152 string $shipping_to
153 ): ?array {
154 if ( empty( $tracking_number ) || empty( $shipping_from ) || empty( $shipping_to ) ) {
155 return null;
156 }
157
158 $normalized = strtoupper( preg_replace( '/\s+/', '', $tracking_number ) );
159 if ( empty( $normalized ) ) {
160 return null;
161 }
162
163 $shipping_from = strtoupper( $shipping_from );
164 $shipping_to = strtoupper( $shipping_to );
165
166 // Australia Post ships only from Australia.
167 if ( 'AU' !== $shipping_from ) {
168 return null;
169 }
170
171 if ( $this->validate_country_pattern( $normalized, $shipping_from ) ) {
172 $confidence = self::TRACKING_PATTERNS[ $shipping_from ]['confidence'];
173
174 // Check digit validation for numeric formats.
175 if ( preg_match( '/^\d{11,13}$/', $normalized ) ) {
176 if ( FulfillmentUtils::validate_mod10_check_digit( $normalized ) ) {
177 $confidence = min( 98, $confidence + 8 );
178 }
179 }
180
181 // UPU S10 validation for international formats.
182 if ( preg_match( '/^[A-Z]{2}\d{7,9}AU$/', $normalized ) ) {
183 if ( FulfillmentUtils::check_s10_upu_format( $normalized ) ) {
184 $confidence = min( 98, $confidence + 8 );
185 }
186 }
187
188 // Service-specific confidence boosts.
189 if ( preg_match( '/^(EP|ST|MB)\d+/', $normalized ) ) {
190 $confidence = min( 95, $confidence + 5 );
191 }
192
193 // Boost confidence for domestic shipments.
194 if ( 'AU' === $shipping_to ) {
195 $confidence = min( 98, $confidence + 5 );
196 }
197
198 // Boost confidence for Asia-Pacific destinations.
199 $apac_destinations = array( 'NZ', 'SG', 'HK', 'JP', 'KR', 'TH', 'MY', 'ID', 'PH', 'VN', 'IN' );
200 if ( in_array( $shipping_to, $apac_destinations, true ) ) {
201 $confidence = min( 95, $confidence + 3 );
202 }
203
204 // Boost confidence for common destinations.
205 $common_destinations = array( 'US', 'GB', 'CA', 'DE', 'FR' );
206 if ( in_array( $shipping_to, $common_destinations, true ) ) {
207 $confidence = min( 93, $confidence + 2 );
208 }
209
210 return array(
211 'url' => $this->get_tracking_url( $normalized ),
212 'ambiguity_score' => $confidence,
213 );
214 }
215
216 return null;
217 }
218 }
219