1111
1212namespace WooCommerce \PayPalCommerce \StoreSync \Endpoint ;
1313
14+ use WooCommerce \PayPalCommerce \StoreSync \Schema \PayPalCart ;
1415use WP_REST_Request ;
1516use WP_REST_Response ;
1617
@@ -56,13 +57,17 @@ public function register_routes(): void {
5657 /**
5758 * Replace an existing cart with new data.
5859 *
60+ * Per PayPal specs, the PUT endpoint may create a new PayPal order when:
61+ * - The cart doesn't have an ec_token yet (POST validation failed)
62+ * - The existing ec_token has expired
63+ *
5964 * @param WP_REST_Request $request The REST request.
6065 * @return WP_REST_Response The REST response.
6166 */
6267 public function replace_cart ( WP_REST_Request $ request ): WP_REST_Response {
6368 $ cart_id = $ request ->get_param ( 'cart_id ' );
6469
65- // Verify cart exists.
70+ // Verify cart exists and get current session data .
6671 $ session = $ this ->get_stored_cart ( $ cart_id );
6772
6873 if ( $ session instanceof AgenticError ) {
@@ -75,8 +80,26 @@ public function replace_cart( WP_REST_Request $request ): WP_REST_Response {
7580 return $ this ->error ( $ new_cart );
7681 }
7782
78- // Replace the cart session (preserving ec_token).
79- $ update_result = $ this ->store_local_cart ( $ cart_id , $ new_cart );
83+ // Determine if we need to create a new PayPal order.
84+ $ existing_token = $ session ['ec_token ' ] ?? '' ;
85+ $ new_token = null ;
86+
87+ if ( $ this ->needs_new_token ( $ existing_token , $ new_cart ) ) {
88+ // Create new PayPal order - may return empty string if cart is invalid.
89+ $ new_token = $ this ->order_manager ->create_order ( $ new_cart );
90+
91+ $ this ->logger ->info (
92+ '[REST] PUT created new PayPal order ' ,
93+ array (
94+ 'cart_id ' => $ cart_id ,
95+ 'new_token ' => $ new_token ?: '(none - order creation failed) ' ,
96+ 'reason ' => empty ( $ existing_token ) ? 'no_existing_token ' : 'token_expired ' ,
97+ )
98+ );
99+ }
100+
101+ // Update the cart session, passing new token if one was created.
102+ $ update_result = $ this ->store_local_cart ( $ cart_id , $ new_cart , $ new_token );
80103
81104 if ( ! $ update_result ) {
82105 return $ this ->error_not_found (
@@ -88,11 +111,48 @@ public function replace_cart( WP_REST_Request $request ): WP_REST_Response {
88111 );
89112 }
90113
91- $ response = $ this ->response_factory ->from_cart ( $ new_cart , $ cart_id );
114+ // Build response - include token only if a new one was created.
115+ if ( $ new_token ) {
116+ $ response = $ this ->response_factory ->cart_with_token ( $ new_cart , $ cart_id , $ new_token );
117+ } else {
118+ $ response = $ this ->response_factory ->from_cart ( $ new_cart , $ cart_id );
119+ }
92120
93121 return $ this ->cart_details ( $ response , 200 );
94122 }
95123
124+ /**
125+ * Determine if a new PayPal order/token needs to be created.
126+ *
127+ * A new token is needed when:
128+ * 1. No existing token (previous POST failed to create one)
129+ * 2. Existing token has expired (future: implement expiry check)
130+ *
131+ * @param string $existing_token The current ec_token from session.
132+ * @param PayPalCart $cart The new cart data.
133+ * @return bool True if a new token should be created.
134+ */
135+ private function needs_new_token ( string $ existing_token , $ cart ): bool {
136+ // Case 1: No existing token.
137+ if ( empty ( $ existing_token ) ) {
138+ // Only attempt to create if the cart is valid (no validation issues).
139+ return ! $ cart ->issues ();
140+ }
141+
142+ // Case 2: Token expired - could be implemented by checking PayPal order status.
143+ // For now, we preserve valid tokens and don't recreate them.
144+ // Future enhancement: call PayPal API to check if order is still valid.
145+
146+ return false ;
147+ }
148+
149+ /**
150+ * Create a not found error response.
151+ *
152+ * @param string $message Error message.
153+ * @param array $details Error details.
154+ * @return WP_REST_Response The error response.
155+ */
96156 private function error_not_found ( string $ message , array $ details ): WP_REST_Response {
97157 return $ this ->error ( new NotFoundError ( $ message , array ( $ details ) ) );
98158 }
0 commit comments