PluginProbe
Packeta / 1.2.3
Packeta v1.2.3
2.3.2 2.3.1 trunk 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.3.0 1.3.1 1.3.2 1.4 1.4.1 1.4.2 1.4.3 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 All 56 releases
packeta / src / Packetery / Module / Checkout.php

Checkout.php in Packeta 1.2.3, at src/Packetery/Module/Checkout.php

715 lines 19.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Packeta plugin class for checkout.
4 *
5 * @package Packetery
6 */
7
8 declare( strict_types=1 );
9
10 namespace Packetery\Module;
11
12 use Packetery\Core;
13 use Packetery\Module\Options\Provider;
14 use PacketeryLatte\Engine;
15 use PacketeryNette\Http\Request;
16
17 /**
18 * Class Checkout
19 *
20 * @package Packetery
21 */
22 class Checkout {
23
24 public const CARRIER_PREFIX = 'packetery_carrier_';
25 private const NONCE_ACTION = 'packetery_checkout';
26
27 const ATTR_POINT_ID = 'packetery_point_id';
28 const ATTR_POINT_NAME = 'packetery_point_name';
29 const ATTR_POINT_CITY = 'packetery_point_city';
30 const ATTR_POINT_ZIP = 'packetery_point_zip';
31 const ATTR_POINT_STREET = 'packetery_point_street';
32 const ATTR_CARRIER_ID = 'packetery_carrier_id';
33 const ATTR_POINT_URL = 'packetery_point_url';
34
35 /**
36 * Pickup point attributes configuration.
37 *
38 * @var array[]
39 */
40 public static $pickupPointAttrs = array(
41 'id' => array(
42 'name' => self::ATTR_POINT_ID,
43 'required' => true,
44 ),
45 'name' => array(
46 'name' => self::ATTR_POINT_NAME,
47 'required' => true,
48 ),
49 'city' => array(
50 'name' => self::ATTR_POINT_CITY,
51 'required' => true,
52 ),
53 'zip' => array(
54 'name' => self::ATTR_POINT_ZIP,
55 'required' => true,
56 ),
57 'street' => array(
58 'name' => self::ATTR_POINT_STREET,
59 'required' => true,
60 ),
61 'carrierId' => array(
62 'name' => self::ATTR_CARRIER_ID,
63 'required' => false,
64 ),
65 'url' => array(
66 'name' => self::ATTR_POINT_URL,
67 'required' => true,
68 ),
69 );
70
71 /**
72 * Home delivery attributes configuration.
73 *
74 * @var array[]
75 */
76 private static $homeDeliveryAttrs = [
77 'isValidated' => [
78 'name' => 'packetery_address_isValidated', // Name of checkout hidden form field. Must be unique in entire form.
79 'isWidgetResultField' => false, // Is attribute included in widget result address? By default it is.
80 ],
81 'houseNumber' => [ // post type address field called 'houseNumber'.
82 'name' => 'packetery_address_houseNumber',
83 ],
84 'street' => [
85 'name' => 'packetery_address_street',
86 ],
87 'city' => [
88 'name' => 'packetery_address_city',
89 ],
90 'postCode' => [
91 'name' => 'packetery_address_postCode',
92 'widgetResultField' => 'postcode', // Widget returns address object containing specified field. By default it is the array key 'postCode', but in this case it is 'postcode'.
93 ],
94 'county' => [
95 'name' => 'packetery_address_county',
96 ],
97 'country' => [
98 'name' => 'packetery_address_country',
99 ],
100 'latitude' => [
101 'name' => 'packetery_address_latitude',
102 ],
103 'longitude' => [
104 'name' => 'packetery_address_longitude',
105 ],
106 ];
107
108 /**
109 * PacketeryLatte engine
110 *
111 * @var Engine
112 */
113 private $latte_engine;
114
115 /**
116 * Options provider.
117 *
118 * @var Provider Options provider.
119 */
120 private $options_provider;
121
122 /**
123 * Carrier repository.
124 *
125 * @var Carrier\Repository Carrier repository.
126 */
127 private $carrierRepository;
128
129 /**
130 * Http request.
131 *
132 * @var Request Http request.
133 */
134 private $httpRequest;
135
136 /**
137 * Order repository.
138 *
139 * @var Order\Repository
140 */
141 private $orderRepository;
142
143 /**
144 * Checkout constructor.
145 *
146 * @param Engine $latte_engine PacketeryLatte engine.
147 * @param Provider $options_provider Options provider.
148 * @param Carrier\Repository $carrierRepository Carrier repository.
149 * @param Request $httpRequest Http request.
150 * @param Order\Repository $orderRepository Order repository.
151 */
152 public function __construct(
153 Engine $latte_engine,
154 Provider $options_provider,
155 Carrier\Repository $carrierRepository,
156 Request $httpRequest,
157 Order\Repository $orderRepository
158 ) {
159 $this->latte_engine = $latte_engine;
160 $this->options_provider = $options_provider;
161 $this->carrierRepository = $carrierRepository;
162 $this->httpRequest = $httpRequest;
163 $this->orderRepository = $orderRepository;
164 }
165
166 /**
167 * Check if chosen shipping rate is bound with Packeta pickup points
168 *
169 * @return bool
170 */
171 public function isPickupPointOrder(): bool {
172 $chosenMethod = $this->getChosenMethod();
173 $carrierId = $this->getCarrierId( $chosenMethod );
174
175 return $carrierId && $this->carrierRepository->isPickupPointCarrier( $carrierId );
176 }
177
178 /**
179 * Check if chosen shipping rate is bound with Packeta home delivery
180 *
181 * @return bool
182 */
183 public function isHomeDeliveryOrder(): bool {
184 $chosenMethod = $this->getChosenMethod();
185 $carrierId = $this->getCarrierId( $chosenMethod );
186
187 return $carrierId && $this->carrierRepository->isHomeDeliveryCarrier( $carrierId );
188 }
189
190 /**
191 * Renders widget button and information about chosen pickup point
192 */
193 public function renderWidgetButton(): void {
194 $this->latte_engine->render(
195 PACKETERY_PLUGIN_DIR . '/template/checkout/widget-button.latte',
196 [
197 'logo' => plugin_dir_url( PACKETERY_PLUGIN_DIR . '/packeta.php' ) . 'public/packeta-symbol.png',
198 ]
199 );
200 }
201
202 /**
203 * Gets widget carriers param.
204 *
205 * @param bool $isPickupPoints Is context pickup point related.
206 * @param string $carrierId Carrier id.
207 *
208 * @return string|null
209 */
210 public static function getWidgetCarriersParam( bool $isPickupPoints, string $carrierId ): ?string {
211 if ( $isPickupPoints ) {
212 return ( is_numeric( $carrierId ) ? $carrierId : Carrier\Repository::INTERNAL_PICKUP_POINTS_ID );
213 }
214
215 return null;
216 }
217
218 /**
219 * Renders main checkout script
220 */
221 public function render_after_checkout_form(): void {
222 $carrierConfig = [];
223 $carriers = $this->carrierRepository->getAllIncludingZpoints();
224
225 foreach ( $carriers as $carrier ) {
226 $optionId = self::CARRIER_PREFIX . $carrier['id'];
227 $carrierConfig[ $optionId ] = [
228 'id' => $carrier['id'],
229 'is_pickup_points' => $carrier['is_pickup_points'],
230 ];
231
232 if ( $carrier['is_pickup_points'] ) {
233 $carrierConfig[ $optionId ]['carriers'] = self::getWidgetCarriersParam( (bool) $carrier['is_pickup_points'], (string) $carrier['id'] );
234 }
235
236 if ( ! $carrier['is_pickup_points'] ) {
237 $carrierOption = get_option( $optionId );
238
239 $addressValidation = 'none';
240 if ( $carrierOption ) {
241 $addressValidation = ( $carrierOption['address_validation'] ?? $addressValidation );
242 }
243
244 $carrierConfig[ $optionId ]['address_validation'] = $addressValidation;
245 }
246 }
247
248 $this->latte_engine->render(
249 PACKETERY_PLUGIN_DIR . '/template/checkout/init.latte',
250 [
251 'settings' => [
252 'language' => substr( get_locale(), 0, 2 ),
253 'country' => $this->getCustomerCountry(),
254 'weight' => $this->getCartWeightKg(),
255 'carrierConfig' => $carrierConfig,
256 'pickupPointAttrs' => self::$pickupPointAttrs,
257 'homeDeliveryAttrs' => self::$homeDeliveryAttrs,
258 'appIdentity' => Plugin::getAppIdentity(),
259 'packeteryApiKey' => $this->options_provider->get_api_key(),
260 'translations' => [
261 'choosePickupPoint' => __( 'choosePickupPoint', 'packetery' ),
262 'chooseAddress' => __( 'checkShippingAddress', 'packetery' ),
263 'addressValidationIsOutOfOrder' => __( 'addressValidationIsOutOfOrder', 'packetery' ),
264 'invalidAddressCountrySelected' => __( 'invalidAddressCountrySelected', 'packetery' ),
265 'selectedShippingAddress' => __( 'selectedShippingAddress', 'packetery' ),
266 'addressIsValidated' => __( 'addressIsValidated', 'packetery' ),
267 'addressIsNotValidated' => __( 'addressIsNotValidated', 'packetery' ),
268 'addressIsNotValidatedAndRequiredByCarrier' => __( 'addressIsNotValidatedAndRequiredByCarrier', 'packetery' ),
269 ],
270 ],
271 ]
272 );
273 }
274
275 /**
276 * Adds fields to checkout page to save the values later
277 */
278 public function addPickupPointFields(): void {
279 $this->latte_engine->render(
280 PACKETERY_PLUGIN_DIR . '/template/checkout/input_fields.latte',
281 [ 'fields' => array_merge( array_column( self::$pickupPointAttrs, 'name' ), array_column( self::$homeDeliveryAttrs, 'name' ) ) ]
282 );
283
284 wp_nonce_field( self::NONCE_ACTION );
285 }
286
287 /**
288 * Checks if all pickup point attributes are set, sets an error otherwise.
289 */
290 public function validateCheckoutData(): void {
291 $post = $this->httpRequest->getPost();
292 if ( ! wp_verify_nonce( $post['_wpnonce'], self::NONCE_ACTION ) ) {
293 wp_nonce_ays( '' );
294 }
295
296 if ( $this->isPickupPointOrder() ) {
297 $error = false;
298 $required_attrs = array_filter(
299 array_combine(
300 array_column( self::$pickupPointAttrs, 'name' ),
301 array_column( self::$pickupPointAttrs, 'required' )
302 )
303 );
304 foreach ( $required_attrs as $attr => $required ) {
305 $attr_value = null;
306 if ( isset( $post[ $attr ] ) ) {
307 $attr_value = $post[ $attr ];
308 }
309 if ( ! $attr_value ) {
310 $error = true;
311 }
312 }
313 $carrierId = null;
314 if ( isset( $post['carrier_id'] ) ) {
315 $carrierId = $post['carrier_id'];
316 }
317 $pointCarrierId = null;
318 if ( isset( $post['point_carrier_id'] ) ) {
319 $pointCarrierId = $post['point_carrier_id'];
320 }
321 if ( $carrierId && ! $pointCarrierId ) {
322 $error = true;
323 }
324 if ( ! $carrierId && $pointCarrierId ) {
325 $error = true;
326 }
327 if ( $error ) {
328 wc_add_notice( __( 'Pick up point is not chosen.', 'packetery' ), 'error' );
329 }
330 }
331
332 if ( $this->isHomeDeliveryOrder() ) {
333 $chosenMethod = $this->getChosenMethod();
334 $carrierId = $this->getCarrierId( $chosenMethod );
335 $optionId = self::CARRIER_PREFIX . $carrierId;
336 $carrierOption = get_option( $optionId );
337
338 $addressValidation = 'none';
339 if ( $carrierOption ) {
340 $addressValidation = ( $carrierOption['address_validation'] ?? $addressValidation );
341 }
342
343 if (
344 'required' === $addressValidation &&
345 (
346 ! isset( $post[ self::$homeDeliveryAttrs['isValidated']['name'] ] ) ||
347 '1' !== $post[ self::$homeDeliveryAttrs['isValidated']['name'] ]
348 )
349 ) {
350 wc_add_notice( __( 'shippingAddressIsNotValidated', 'packetery' ), 'error' );
351
352 return;
353 }
354 }
355 }
356
357 /**
358 * Saves pickup point and other Packeta information to order.
359 *
360 * @param int $orderId Order id.
361 */
362 public function updateOrderMeta( int $orderId ): void {
363 $chosenMethod = $this->getChosenMethod();
364 if ( false === $this->isPacketeryOrder( $chosenMethod ) ) {
365 return;
366 }
367
368 $post = $this->httpRequest->getPost();
369
370 $propsToSave = [];
371 // Save carrier id for home delivery (we got no id from widget).
372 $carrierId = $this->getCarrierId( $chosenMethod );
373 if ( empty( $post[ self::ATTR_CARRIER_ID ] ) && $carrierId ) {
374 $propsToSave[ self::ATTR_CARRIER_ID ] = $carrierId;
375 }
376
377 if ( $this->isPickupPointOrder() ) {
378 foreach ( self::$pickupPointAttrs as $attr ) {
379 $attrName = $attr['name'];
380 if ( ! isset( $post[ $attrName ] ) ) {
381 continue;
382 }
383 $attrValue = $post[ $attrName ];
384
385 $saveMeta = true;
386 if (
387 ( self::ATTR_CARRIER_ID === $attrName && ! $attrValue ) ||
388 ( self::ATTR_POINT_URL === $attrName && ! filter_var( $attrValue, FILTER_VALIDATE_URL ) )
389 ) {
390 $saveMeta = false;
391 }
392 if ( $saveMeta ) {
393 $propsToSave[ $attrName ] = $attrValue;
394 }
395 }
396 }
397
398 $orderEntity = new Core\Entity\Order( (string) $orderId, $carrierId );
399 if ( $this->isHomeDeliveryOrder() ) {
400 if (
401 isset( $post[ self::$homeDeliveryAttrs['isValidated']['name'] ] ) &&
402 '1' === $post[ self::$homeDeliveryAttrs['isValidated']['name'] ]
403 ) {
404 $validatedAddress = new Core\Entity\Address(
405 $post[ self::$homeDeliveryAttrs['street']['name'] ],
406 $post[ self::$homeDeliveryAttrs['city']['name'] ],
407 $post[ self::$homeDeliveryAttrs['postCode']['name'] ]
408 );
409 $validatedAddress->setCounty( $post[ self::$homeDeliveryAttrs['county']['name'] ] );
410 $validatedAddress->setHouseNumber( $post[ self::$homeDeliveryAttrs['houseNumber']['name'] ] );
411 $validatedAddress->setLatitude( $post[ self::$homeDeliveryAttrs['latitude']['name'] ] );
412 $validatedAddress->setLongitude( $post[ self::$homeDeliveryAttrs['longitude']['name'] ] );
413
414 $orderEntity->setDeliveryAddress( $validatedAddress );
415 $orderEntity->setAddressValidated( true );
416 }
417 }
418
419 self::updateOrderEntityFromPropsToSave( $orderEntity, $propsToSave );
420 $this->orderRepository->save( $orderEntity );
421 }
422
423 /**
424 * Updates order entity from props to save-
425 *
426 * @param Core\Entity\Order $orderEntity Order entity.
427 * @param array $propsToSave Props to save.
428 *
429 * @return void
430 */
431 public static function updateOrderEntityFromPropsToSave( Core\Entity\Order $orderEntity, array $propsToSave ): void {
432 $orderEntityPickupPoint = $orderEntity->getPickupPoint();
433 if ( null === $orderEntityPickupPoint ) {
434 $orderEntityPickupPoint = new Core\Entity\PickupPoint();
435 }
436
437 foreach ( $propsToSave as $attrName => $attrValue ) {
438 switch ( $attrName ) {
439 case self::ATTR_CARRIER_ID:
440 $orderEntity->setCarrierId( $attrValue );
441 break;
442 case self::ATTR_POINT_ID:
443 $orderEntityPickupPoint->setId( $attrValue );
444 break;
445 case self::ATTR_POINT_NAME:
446 $orderEntityPickupPoint->setName( $attrValue );
447 break;
448 case self::ATTR_POINT_URL:
449 $orderEntityPickupPoint->setUrl( $attrValue );
450 break;
451 case self::ATTR_POINT_STREET:
452 $orderEntityPickupPoint->setStreet( $attrValue );
453 break;
454 case self::ATTR_POINT_ZIP:
455 $orderEntityPickupPoint->setZip( $attrValue );
456 break;
457 case self::ATTR_POINT_CITY:
458 $orderEntityPickupPoint->setCity( $attrValue );
459 break;
460 }
461 }
462
463 $orderEntity->setPickupPoint( $orderEntityPickupPoint );
464 }
465
466 /**
467 * Registers Packeta checkout hooks
468 */
469 public function register_hooks(): void {
470 add_action( 'woocommerce_review_order_before_payment', array( $this, 'renderWidgetButton' ) );
471 add_action( 'woocommerce_after_checkout_form', array( $this, 'render_after_checkout_form' ) );
472 add_action( 'woocommerce_after_order_notes', array( $this, 'addPickupPointFields' ) );
473 add_action( 'woocommerce_checkout_process', array( $this, 'validateCheckoutData' ) );
474 add_action( 'woocommerce_checkout_update_order_meta', array( $this, 'updateOrderMeta' ) );
475 add_action( 'woocommerce_review_order_before_shipping', array( $this, 'updateShippingRates' ), 10, 2 );
476 add_action( 'woocommerce_cart_calculate_fees', [ $this, 'calculateFees' ] );
477 }
478
479 /**
480 * Updates shipping rates cost based on cart properties.
481 */
482 public function updateShippingRates(): void {
483 $customRates = $this->getShippingRates();
484
485 $packages = WC()->shipping()->get_packages();
486 foreach ( $packages as $i => $package ) {
487 if ( ! empty( $package['rates'] ) ) {
488 foreach ( $package['rates'] as $key => $rate ) {
489 if ( isset( $customRates[ $rate->get_id() ] ) ) {
490 $rate->set_cost( $customRates[ $rate->get_id() ]['cost'] );
491 WC()->shipping->packages[ $i ]['rates'][ $key ] = $rate;
492 }
493 }
494 }
495 }
496 }
497
498 /**
499 * Gets customer country from WC cart.
500 *
501 * @return string
502 */
503 public function getCustomerCountry(): string {
504 $country = strtolower( WC()->customer->get_shipping_country() );
505 if ( ! $country ) {
506 $country = strtolower( WC()->customer->get_billing_country() );
507 }
508
509 return $country;
510 }
511
512 /**
513 * Gets cart contents weight in kg.
514 *
515 * @return float|int
516 */
517 public function getCartWeightKg() {
518 $weight = WC()->cart->cart_contents_weight;
519 $weightKg = wc_get_weight( $weight, 'kg' );
520 if ( $weightKg ) {
521 $weightKg += $this->options_provider->getPackagingWeight();
522 }
523
524 return $weightKg;
525 }
526
527 /**
528 * Calculates fees.
529 *
530 * @return void
531 */
532 public function calculateFees(): void {
533 $chosenShippingMethod = $this->getChosenMethod();
534 if ( false === $this->isPacketeryOrder( $chosenShippingMethod ) ) {
535 return;
536 }
537
538 $carrierOptions = get_option( $chosenShippingMethod );
539 if ( ! $carrierOptions ) {
540 return;
541 }
542
543 $isCod = false;
544 $codPaymentMethod = $this->options_provider->getCodPaymentMethod();
545 $chosenPaymentMethod = WC()->session->get( 'chosen_payment_method' );
546 if ( null !== $codPaymentMethod && ! empty( $chosenPaymentMethod ) && $chosenPaymentMethod === $codPaymentMethod ) {
547 $isCod = true;
548 }
549
550 if ( false === $isCod ) {
551 return;
552 }
553
554 $applicableSurcharge = $this->getCODSurcharge( $carrierOptions, $this->getCartPrice() );
555 if ( 0 >= $applicableSurcharge ) {
556 return;
557 }
558
559 $fee = [
560 'id' => 'packetery-cod-surcharge',
561 'name' => __( 'codSurcharge', 'packetery' ),
562 'amount' => $applicableSurcharge,
563 ];
564
565 WC()->cart->fees_api()->add_fee( $fee );
566 }
567
568 /**
569 * Gets cart price. Value is casted to float because PHPDoc is not reliable.
570 *
571 * @return float
572 */
573 private function getCartPrice(): float {
574 return (float) WC()->cart->get_subtotal();
575 }
576
577 /**
578 * Prepare shipping rates based on cart properties.
579 *
580 * @return array
581 */
582 public function getShippingRates(): array {
583 $customerCountry = $this->getCustomerCountry();
584 $availableCarriers = $this->carrierRepository->getByCountryIncludingZpoints( $customerCountry );
585 $carrierOptions = [];
586 foreach ( $availableCarriers as $carrier ) {
587 $optionId = self::CARRIER_PREFIX . $carrier->getId();
588 $carrierOptions[ $optionId ] = get_option( $optionId );
589 }
590
591 $cartPrice = $this->getCartPrice();
592 $cartWeight = $this->getCartWeightKg();
593
594 $customRates = [];
595 foreach ( $carrierOptions as $optionId => $options ) {
596 if ( is_array( $options ) && true === $options['active'] ) {
597 $cost = $this->getRateCost( $options, $cartPrice, $cartWeight );
598 if ( null !== $cost ) {
599 $customRates[ $optionId ] = [
600 'label' => $options['name'],
601 'id' => $optionId,
602 'cost' => $cost,
603 'taxes' => '',
604 'calc_tax' => 'per_order',
605 ];
606 }
607 }
608 }
609
610 return $customRates;
611 }
612
613 /**
614 * Computes custom rate cost for carrier using cart contents.
615 *
616 * @param array $carrierOptions Carrier options.
617 * @param float $cartPrice Price.
618 * @param float|int $cartWeight Weight.
619 *
620 * @return int|float|null
621 */
622 private function getRateCost( array $carrierOptions, float $cartPrice, $cartWeight ) {
623 $cost = null;
624
625 foreach ( $carrierOptions['weight_limits'] as $weightLimit ) {
626 if ( $cartWeight <= $weightLimit['weight'] ) {
627 $cost = $weightLimit['price'];
628 break;
629 }
630 }
631
632 if ( null === $cost ) {
633 return null;
634 }
635
636 if ( $carrierOptions['free_shipping_limit'] && $cartPrice >= $carrierOptions['free_shipping_limit'] ) {
637 $cost = 0;
638 }
639
640 return $cost;
641 }
642
643 /**
644 * Gets applicable COD surcharge.
645 *
646 * @param array $carrierOptions Carrier options.
647 * @param float $cartPrice Cart price.
648 *
649 * @return float
650 */
651 private function getCODSurcharge( array $carrierOptions, float $cartPrice ): float {
652 if ( isset( $carrierOptions['surcharge_limits'] ) ) {
653 foreach ( $carrierOptions['surcharge_limits'] as $weightLimit ) {
654 if ( $cartPrice <= $weightLimit['order_price'] ) {
655 return (float) $weightLimit['surcharge'];
656 }
657 }
658 }
659
660 if ( isset( $carrierOptions['default_COD_surcharge'] ) && is_numeric( $carrierOptions['default_COD_surcharge'] ) ) {
661 return (float) $carrierOptions['default_COD_surcharge'];
662 }
663
664 return 0.0;
665 }
666
667 /**
668 * Get chosen shipping rate id.
669 *
670 * @return string
671 */
672 private function getChosenMethod(): string {
673 $chosenShippingRates = WC()->cart->calculate_shipping();
674 $chosenShippingRate = ( $chosenShippingRates[0] ?? null );
675
676 if ( $chosenShippingRate instanceof \WC_Shipping_Rate ) {
677 return $chosenShippingRate->get_id();
678 }
679
680 return '';
681 }
682
683 /**
684 * Gets carrier id from chosen shipping method.
685 *
686 * @param string $chosenMethod Chosen shipping method.
687 *
688 * @return string|null
689 */
690 public function getCarrierId( string $chosenMethod ): ?string {
691 if ( ! $this->isPacketeryOrder( $chosenMethod ) ) {
692 return null;
693 }
694
695 $carrierId = str_replace( self::CARRIER_PREFIX, '', $chosenMethod );
696 if ( strpos( $carrierId, 'zpoint' ) === 0 ) {
697 return Carrier\Repository::INTERNAL_PICKUP_POINTS_ID;
698 }
699
700 return $carrierId;
701 }
702
703
704 /**
705 * Checks if chosen shipping method is one of packetery.
706 *
707 * @param string $chosenMethod Chosen shipping method.
708 *
709 * @return bool
710 */
711 private function isPacketeryOrder( string $chosenMethod ): bool {
712 return ( strpos( $chosenMethod, self::CARRIER_PREFIX ) === 0 );
713 }
714 }
715