Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions modules/ppcp-store-sync/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
use WooCommerce\PayPalCommerce\StoreSync\Inspector\InspectionFormHandler;
use WooCommerce\PayPalCommerce\StoreSync\Inspector\InspectionStatusPage;
use WooCommerce\PayPalCommerce\StoreSync\Helper\AgenticCheckoutProcessor;
use WooCommerce\PayPalCommerce\StoreSync\Helper\ShippingOptionsBuilder;
use WooCommerce\PayPalCommerce\StoreSync\Helper\PayPalOrderManager;
use WooCommerce\PayPalCommerce\StoreSync\Helper\AgenticCartBuilder;
use WooCommerce\PayPalCommerce\StoreSync\Helper\ProductManager;
Expand Down Expand Up @@ -142,7 +143,9 @@
$c->get( 'agentic.logger' )
);
},

'agentic.helper.shipping-options-builder' => static function (): ShippingOptionsBuilder {
return new ShippingOptionsBuilder();
},
'agentic.helper.checkout-processor' => static function ( ContainerInterface $c ): AgenticCheckoutProcessor {
return new AgenticCheckoutProcessor(
$c->get( 'agentic.helper.paypal-order-manager' ),
Expand Down Expand Up @@ -222,7 +225,8 @@
'agentic.response.factory' => static function ( ContainerInterface $c ): ResponseFactory {
return new ResponseFactory(
$c->get( 'agentic.helper.cart-builder' ),
$c->get( 'agentic.response.applied-coupons-builder' )
$c->get( 'agentic.response.applied-coupons-builder' ),
$c->get( 'agentic.helper.shipping-options-builder' )
);
},

Expand Down
79 changes: 79 additions & 0 deletions modules/ppcp-store-sync/src/Helper/ShippingOptionsBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php
/**
* Builds the available_shipping_options array for cart API responses.
*
* @package WooCommerce\PayPalCommerce\StoreSync\Helper
*/

declare( strict_types = 1 );

namespace WooCommerce\PayPalCommerce\StoreSync\Helper;

use WC_Cart;

class ShippingOptionsBuilder {

/**
* Build shipping options from the WC cart state post calculate_totals().
*
* Returns an empty array when no cart is available or no packages exist.
* Exactly one option in a non-empty result has is_selected = true.
*
* @param WC_Cart|null $wc_cart The WooCommerce cart.
* @return array
*/
public function build( ?WC_Cart $wc_cart ): array {
if ( null === $wc_cart ) {
return array();
}

$packages = WC()->shipping()->get_packages();

if ( empty( $packages ) ) {
return array();
}

$chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
$chosen_id = ( is_array( $chosen_methods ) && ! empty( $chosen_methods ) )
? $chosen_methods[0]
Comment thread
Narek13 marked this conversation as resolved.
Outdated
: null;

$currency = get_woocommerce_currency();
$options = array();
$first_rate_id = null;

foreach ( $packages as $package ) {
if ( empty( $package['rates'] ) ) {
continue;
}

foreach ( $package['rates'] as $rate ) {
$rate_id = $rate->get_id();

if ( null === $first_rate_id ) {
$first_rate_id = $rate_id;
}

$options[] = array(
'id' => $rate_id,
Comment thread
stracker-phil marked this conversation as resolved.
Outdated
'label' => $rate->get_label(),
'amount' => number_format( (float) $rate->get_cost(), 2, '.', '' ),
Comment thread
Narek13 marked this conversation as resolved.
Outdated
'currency' => $currency,
'is_selected' => false,
);
}
}

if ( empty( $options ) ) {
return array();
}

$selected_id = $chosen_id ?? $first_rate_id;
foreach ( $options as &$option ) {
$option['is_selected'] = ( $option['id'] === $selected_id );
}
unset( $option );

return $options;
}
}
141 changes: 117 additions & 24 deletions modules/ppcp-store-sync/src/Response/CartResponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
namespace WooCommerce\PayPalCommerce\StoreSync\Response;

use WC_Cart;
use WC_Order;

use WooCommerce\PayPalCommerce\StoreSync\Schema\PayPalCart;
use WooCommerce\PayPalCommerce\StoreSync\Validation\ValidationIssue;
Expand All @@ -30,16 +31,13 @@ class CartResponse {
'REQUIRES_ADDITIONAL_INFORMATION',
);

protected PayPalCart $cart;
private PayPalCart $cart;

protected ?WC_Cart $wc_cart;
private ?WC_Cart $wc_cart = null;

/**
* Applied coupons data.
*
* @var array
*/
protected array $applied_coupons = array();
private array $applied_coupons = array();

private array $shipping_options = array();

/**
* The cart ID used by the API to reference to an existing cart.
Expand All @@ -50,38 +48,118 @@ class CartResponse {
* Used to track cart lifecycle.
* Possible values: CREATED, INCOMPLETE, READY, COMPLETED
*/
protected string $status = 'INCOMPLETE';
private string $status = 'INCOMPLETE';

/**
* Used to determine the next step.
* Possible values: VALID, INVALID, REQUIRES_ADDITIONAL_INFORMATION
*/
protected string $validation_status = 'INVALID';
private string $validation_status = 'INVALID';

/**
* The payment method token, used to verify checkout.
* The payment method token, only set for newly created carts.
*/
protected string $token = '';
private string $token = '';

/**
* Constructor.
*
* @param PayPalCart $cart The PayPal cart.
* @param array $applied_coupons Applied coupons data.
* @param string $cart_id The cart ID.
* @param WC_Cart|null $wc_cart The WooCommerce cart.
* The WooCommerce order created during checkout, only set for completed carts.
*/
public function __construct( PayPalCart $cart, array $applied_coupons = array(), string $cart_id = '', ?WC_Cart $wc_cart = null ) {
$this->cart = $cart;
$this->applied_coupons = $applied_coupons;
$this->cart_id = $cart_id;
$this->wc_cart = $wc_cart;
private ?WC_Order $wc_order = null;

/**
* @param PayPalCart $cart The PayPal cart.
* @param string $cart_id The cart ID.
*/
private function __construct( PayPalCart $cart, string $cart_id = '' ) {
$this->cart = $cart;
$this->cart_id = $cart_id;

if ( ! $this->cart->issues() ) {
$this->validation_status = 'VALID';
}
}

/**
* Create a base cart response (status: INCOMPLETE).
*
* @param PayPalCart $cart The PayPal cart.
* @param string $cart_id The cart ID.
* @return self
*/
public static function create( PayPalCart $cart, string $cart_id = '' ): self {
return new self( $cart, $cart_id );
}

/**
* Create a new cart response (status: CREATED).
*
* @param PayPalCart $cart The PayPal cart.
* @param string $cart_id The cart ID.
* @param string $token The EC token.
* @return self
*/
public static function create_new( PayPalCart $cart, string $cart_id, string $token ): self {
$instance = new self( $cart, $cart_id );

$instance->status = 'CREATED';
$instance->token = $token;

return $instance;
}

/**
* Create a completed cart response (status: COMPLETED).
*
* @param PayPalCart $cart The PayPal cart.
* @param string $cart_id The cart ID.
* @param WC_Order $wc_order The WooCommerce order.
* @return self
*/
public static function create_completed( PayPalCart $cart, string $cart_id, WC_Order $wc_order ): self {
$instance = new self( $cart, $cart_id );

$instance->status = 'COMPLETED';
$instance->wc_order = $wc_order;

return $instance;
}

/**
* Configures the CartResponse instance - only used by the ResponseFactory.
*
* @param array $coupons Applied coupons data.
* @return $this
*/
public function applied_coupons( array $coupons ): self {
$this->applied_coupons = $coupons;

return $this;
}

/**
* Configures the CartResponse instance - only used by the ResponseFactory.
*
* @param array $options Available shipping options.
* @return $this
*/
public function shipping_options( array $options ): self {
$this->shipping_options = $options;

return $this;
}

/**
* Configures the CartResponse instance - only used by the ResponseFactory.
*
* @param WC_Cart|null $wc_cart The WooCommerce cart, used to calculate totals.
* @return $this
*/
public function wc_cart( ?WC_Cart $wc_cart ): self {
$this->wc_cart = $wc_cart;

return $this;
}

/**
* Convert to array for API response.
*
Expand All @@ -96,9 +174,9 @@ public function to_array(): array {
static fn( ValidationIssue $issue ) => $issue->to_array(),
$this->cart->issues()
),
'payment_method' => array( 'type' => 'paypal' ),
);

// Add applied_coupons if any coupons were successfully applied.
if ( ! empty( $this->applied_coupons ) ) {
$data['applied_coupons'] = $this->applied_coupons;
}
Expand All @@ -110,6 +188,21 @@ public function to_array(): array {
$data['totals'] = $totals;
}

if ( ! empty( $this->shipping_options ) ) {
$data['available_shipping_options'] = $this->shipping_options;
}

if ( $this->token ) {
$data['payment_method']['token'] = $this->token;
}

if ( $this->wc_order ) {
$data['payment_confirmation'] = array(
'merchant_order_number' => $this->wc_order->get_id(),
'order_review_page' => $this->wc_order->get_checkout_order_received_url(),
);
}

return $data;
}

Expand Down
56 changes: 0 additions & 56 deletions modules/ppcp-store-sync/src/Response/NewCartResponse.php

This file was deleted.

Loading
Loading