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 |