0 ? $postId : 0; $payload = self::VERSION . ':' . $productId . ':' . $issuedAt . ':' . $targetHash . ':' . $postId; return $payload . ':' . self::signature( $payload ); } /** * Verify a token for the supplied product id, target URL, and post id. * * Tokens issued without a post id carry `0` and remain valid for any post. * * @param string $token Token candidate. * @param int $productId Persisted product id. * @param string $targetUrl Target URL reported by the click payload. * @param int|null $postId WordPress post id reported by the click payload. * @param int|null $now Unix timestamp, or null for current time. */ public static function verify( string $token, int $productId, string $targetUrl, ?int $postId = null, ?int $now = null ): bool { $parts = explode( ':', $token ); if ( count( $parts ) !== 6 ) { return false; } if ( $parts[0] !== self::VERSION || $parts[1] !== (string) $productId ) { return false; } if ( preg_match( '/\A\d+\z/', $parts[2] ) !== 1 || preg_match( '/\A\d+\z/', $parts[4] ) !== 1 ) { return false; } if ( ! hash_equals( self::targetHash( $targetUrl ), $parts[3] ) ) { return false; } $tokenPostId = (int) $parts[4]; if ( $tokenPostId > 0 && $tokenPostId !== (int) $postId ) { return false; } $issuedAt = (int) $parts[2]; $now = $now ?? time(); if ( $issuedAt > $now + 300 || $issuedAt + self::DEFAULT_TTL_SECONDS < $now ) { return false; } $payload = self::VERSION . ':' . $productId . ':' . $issuedAt . ':' . $parts[3] . ':' . $parts[4]; $expected = self::signature( $payload ); return hash_equals( $expected, $parts[5] ); } /** * Hash a target URL for compact token payloads. * * @param string $targetUrl Target URL. */ private static function targetHash( string $targetUrl ): string { return hash( 'sha256', trim( $targetUrl ) ); } /** * Compute the token HMAC. * * @param string $payload Token payload. */ private static function signature( string $payload ): string { return hash_hmac( 'sha256', $payload, self::secret() ); } /** * Resolve the best available WordPress secret material. */ private static function secret(): string { if ( function_exists( 'wp_salt' ) ) { $salt = (string) wp_salt( 'auth' ); if ( $salt !== '' ) { return $salt; } } foreach ( array( 'AUTH_SALT', 'SECURE_AUTH_SALT', 'NONCE_SALT', 'LOGGED_IN_SALT' ) as $constant ) { if ( defined( $constant ) ) { $value = (string) constant( $constant ); if ( $value !== '' ) { return $value; } } } return 'affilun-click-token-development-secret'; } }