Automattic\WooCommerce\Internal\Fulfillments\Providers

FedExShippingProvider::try_parse_tracking_numberpublicWC 1.0

Validates and parses a FedEx tracking number.

Method of the class: FedExShippingProvider{}

No Hooks.

Returns

Array|null. Array with tracking URL and score, or null if invalid.

Usage

$FedExShippingProvider = new FedExShippingProvider();
$FedExShippingProvider->try_parse_tracking_number( $tracking_number, $shipping_from, $shipping_to ): ?array;
$tracking_number(string) (required)
The tracking number to validate.
$shipping_from(string) (required)
Origin country code.
$shipping_to(string) (required)
Destination country code.

FedExShippingProvider::try_parse_tracking_number() code WC 10.3.3

public function try_parse_tracking_number( string $tracking_number, string $shipping_from, string $shipping_to ): ?array {
	if ( empty( $tracking_number ) || ! $this->can_ship_from_to( $shipping_from, $shipping_to ) ) {
		return null;
	}

	$tracking_number  = strtoupper( preg_replace( '/\s+/', '', $tracking_number ) ); // Remove spaces and uppercase for consistency.
	$is_north_america = in_array( $shipping_from, array( 'US', 'CA' ), true ); // North America flag for scoring.
	$is_us_domestic   = 'US' === $shipping_from && 'US' === $shipping_to; // US domestic flag for scoring.

	// FedEx tracking number patterns with enhanced validation and comments.
	$patterns = array(
		// FedEx Door Tag: DT + 12 digits (US/CA only).
		'/^DT\d{12}$/'       => $is_north_america ? 90 : 0,

		// FedEx Custom Critical: 0 or 1 followed by 13-23 digits (very rare, highest confidence).
		'/^0[01]\d{13,23}$/' => 98,

		// FedEx SmartPost: 023 + 17 digits (US only, SmartPost).
		'/^023\d{17}$/'      => 97,

		// FedEx SmartPost: 58 + 17-19 digits (older SmartPost).
		'/^58\d{17,19}$/'    => 96,

		// FedEx Express: 12 digits (most common, with check digit validation).
		'/^\d{12}$/'         => function () use ( $tracking_number, $is_north_america, $is_us_domestic ) {
			if ( FulfillmentUtils::validate_fedex_check_digit( $tracking_number ) ) {
				return $is_north_america || $is_us_domestic ? 98 : 85; // High confidence if check digit valid.
			}
			return $is_north_america ? ( $is_us_domestic ? 98 : 85 ) : 70; // Lower if check digit invalid.
		},

		// FedEx Express: 15 digits (less common, with check digit validation).
		'/^\d{15}$/'         => function () use ( $tracking_number, $is_north_america ) {
			if ( FulfillmentUtils::validate_fedex_check_digit( $tracking_number ) ) {
				return $is_north_america ? 96 : 80; // High confidence if check digit valid.
			}
			return $is_north_america ? 80 : 65; // Lower if check digit invalid.
		},

		// FedEx Express: 14 digits (with check digit validation).
		'/^\d{14}$/'         => function () use ( $tracking_number, $is_north_america ) {
			if ( FulfillmentUtils::validate_fedex_check_digit( $tracking_number ) ) {
				return $is_north_america ? 95 : 78; // High confidence if check digit valid.
			}
			return $is_north_america ? 78 : 60; // Lower if check digit invalid.
		},

		// FedEx Express: 34 digits (rare, international bulk shipments).
		'/^\d{34}$/'         => 90,

		// FedEx Ground: 96 + 18-20 digits (US/CA only).
		'/^96\d{18,20}$/'    => $is_north_america ? 95 : 60,

		// FedEx Ground: 7 + 11-20 digits (US/CA only, legacy).
		'/^7\d{11,20}$/'     => $is_north_america ? 90 : 75,

		// FedEx Freight: 97 + 13-23 digits (Freight/LTL).
		'/^97\d{13,23}$/'    => 93,

		// FedEx Express International: 3 + 10-14 digits (Europe/Asia).
		'/^3\d{10,14}$/'     => 92,

		// FedEx International Priority: 8 + 8-14 digits (Europe/Asia).
		'/^8\d{8,14}$/'      => function () use ( $shipping_from ) {
			return in_array( $shipping_from, array( 'GB', 'DE', 'FR', 'IT', 'ES', 'NL' ), true ) ? 93 : 75;
		},

		// FedEx Express Next Flight Out: NFO + 10-15 digits.
		'/^NFO\d{10,15}$/'   => 92,

		// FedEx SameDay: SD + 10-15 digits.
		'/^SD\d{10,15}$/'    => 90,

		// Fallback: 20 digit numeric (used by some international and legacy services).
		'/^\d{20}$/'         => 70,

		// Fallback: 22 digit numeric (rare, legacy).
		'/^\d{22}$/'         => 65,
	);

	foreach ( $patterns as $pattern => $base_score ) {
		if ( preg_match( $pattern, $tracking_number ) ) {
			$score = is_callable( $base_score ) ? $base_score() : $base_score;
			if ( $score > 0 ) {
				return array(
					'url'             => $this->get_tracking_url( $tracking_number ),
					'ambiguity_score' => $score,
				);
			}
		}
	}

	return null; // No matching pattern found.
}