Automattic\WooCommerce\StoreApi\Routes\V1\Agentic

CheckoutSessionsComplete::get_route_post_responseprotectedWC 1.0

Handle the request and return a valid response for this endpoint.

Метод класса: CheckoutSessionsComplete{}

Хуков нет.

Возвращает

\WP_REST_Response|\WP_Error.

Использование

// protected - в коде основоного (родительского) или дочернего класса
$result = $this->get_route_post_response( $request );
$request(WP_REST_Request) (обязательный)
Request object.

Код CheckoutSessionsComplete::get_route_post_response() WC 10.5.0

protected function get_route_post_response( \WP_REST_Request $request ) {
	$checkout_session = new AgenticCheckoutSession( $this->cart_controller->get_cart_instance() );

	AgenticCheckoutUtils::validate( $checkout_session );

	/**
	 * Verify checkout session is ready for payment.
	 */
	$current_status = AgenticCheckoutUtils::calculate_status( $checkout_session );
	if ( CheckoutSessionStatus::READY_FOR_PAYMENT !== $current_status ) {
		$message = sprintf(
			/* translators: %s: current session status */
			__( 'Checkout session is not ready for payment. Current status: %s', 'woocommerce' ),
			$current_status
		);
		return Error::invalid_request( ErrorCode::INVALID, $message )->to_rest_response();
	}

	/**
	 * Set buyer data if exists.
	 */
	$buyer = $request->get_param( 'buyer' );
	if ( null !== $buyer ) {
		AgenticCheckoutUtils::set_buyer_data( $buyer, WC()->customer );
	}

	/**
	 * Set billing address from payment_data if provided.
	 */
	$payment_data = $request->get_param( 'payment_data' );
	if ( isset( $payment_data['billing_address'] ) ) {
		AgenticCheckoutUtils::set_billing_address( $payment_data['billing_address'], WC()->customer );
	}

	try {
		/**
		 * Before triggering validation, ensure totals are current and in turn, things such as shipping costs are present.
		 * This is so plugins that validate other cart data (e.g. conditional shipping and payments) can access this data.
		 */
		$this->cart_controller->calculate_totals();

		/**
		 * Validate that the cart is not empty.
		 */
		$this->cart_controller->validate_cart_not_empty();

		/**
		 * Validate items and fix violations before the order is processed.
		 */
		$this->cart_controller->validate_cart();
	} catch ( \Exception $e ) {
		$message = wp_specialchars_decode( $e->getMessage(), ENT_QUOTES );
		return Error::processing_error( ErrorCode::INVALID, $message )->to_rest_response();
	}

	/**
	 * Similar to Checkout::create_or_update_draft_order.
	 * Can move this to CheckoutTrait to share between Checkout.php and this controller.
	 */
	$this->order = $this->get_draft_order();
	if ( ! $this->order ) {
		$this->order = $this->order_controller->create_order_from_cart();
	} else {
		$this->order_controller->update_order_from_cart( $this->order, true );
	}

	/**
	 * Stores the checkout session ID to the order meta.
	 */
	$this->order->update_meta_data( OrderMetaKey::AGENTIC_CHECKOUT_SESSION_ID, $request->get_param( 'checkout_session_id' ) );
	$this->order->save_meta_data();

	/**
	 * Validate updated order before payment is attempted.
	 */
	try {
		$this->order_controller->validate_order_before_payment( $this->order );
	} catch ( \Exception $e ) {
		$message = wp_specialchars_decode( $e->getMessage(), ENT_QUOTES );
		return Error::invalid_request( ErrorCode::INVALID, $message )->to_rest_response();
	}

	try {
		wc_reserve_stock_for_order( $this->order );
	} catch ( \Exception $e ) {
		$message = wp_specialchars_decode( $e->getMessage(), ENT_QUOTES );
		return Error::invalid_request( ErrorCode::INVALID, $message )->to_rest_response();
	}

	// Set the order status to 'pending' as an initial step.
	$this->order->update_status( 'pending' );

	/**
	 * Process payment (reuse CheckoutTrait).
	 */
	$payment_result = new PaymentResult();

	try {
		/**
		 * Set IN_PROGRESS status to prevent concurrent payment attempts.
		 * Save this status right away so that any concurrent request will not be able to access the payment process.
		 */
		WC()->session->set( SessionKey::AGENTIC_CHECKOUT_PAYMENT_IN_PROGRESS, true );
		WC()->session->save_data();

		$this->process_payment( $request, $payment_result );
	} catch ( \Exception $e ) {
		$message = wp_specialchars_decode( $e->getMessage(), ENT_QUOTES );
		return Error::processing_error( ErrorCode::INVALID, $message )->to_rest_response();
	} finally {
		/**
		 * Clear IN_PROGRESS status after payment attempt.
		 * Do not save session here as it will be done after the shutdown.
		 */
		WC()->session->set( SessionKey::AGENTIC_CHECKOUT_PAYMENT_IN_PROGRESS, false );
	}

	/**
	 * If payment failed, return error.
	 */
	if ( 'failure' === $payment_result->status || 'error' === $payment_result->status ) {
		// Clear IN_PROGRESS status to allow retry.
		$message = $payment_result->message ?? __( 'Payment was declined.', 'woocommerce' );
		$message = wp_specialchars_decode( $message, ENT_QUOTES );
		return Error::processing_error( ErrorCode::PAYMENT_DECLINED, $message )->to_rest_response();
	}

	/**
	 * Store the completed order ID into the session. This will prevent new orders in this session.
	 */
	WC()->session->set( SessionKey::AGENTIC_CHECKOUT_COMPLETED_ORDER_ID, $this->order->get_id() );

	/**
	 * Build response from canonical cart schema.
	 */
	$response_data = $this->schema->get_item_response( $checkout_session );
	$response      = rest_ensure_response( $response_data );

	return AgenticCheckoutUtils::add_protocol_headers( $response, $request );
}