diff --git a/modules/ppcp-button/services.php b/modules/ppcp-button/services.php index 9464e0067..7c564d1ef 100644 --- a/modules/ppcp-button/services.php +++ b/modules/ppcp-button/services.php @@ -16,6 +16,7 @@ use WooCommerce\PayPalCommerce\Button\Helper\CartProductsHelper; use WooCommerce\PayPalCommerce\Button\Helper\CheckoutFormSaver; use WooCommerce\PayPalCommerce\Button\Endpoint\SaveCheckoutFormEndpoint; use WooCommerce\PayPalCommerce\Button\Helper\ContextTrait; +use WooCommerce\PayPalCommerce\Button\Helper\WooCommerceOrderCreator; use WooCommerce\PayPalCommerce\Button\Validation\CheckoutFormValidator; use WooCommerce\PayPalCommerce\Button\Endpoint\ValidateCheckoutEndpoint; use WooCommerce\PayPalCommerce\Session\SessionHandler; @@ -228,14 +229,17 @@ return array( return new EarlyOrderHandler( $state, $order_processor, $session_handler ); }, 'button.endpoint.approve-order' => static function ( ContainerInterface $container ): ApproveOrderEndpoint { - $request_data = $container->get( 'button.request-data' ); - $order_endpoint = $container->get( 'api.endpoint.order' ); - $session_handler = $container->get( 'session.handler' ); - $three_d_secure = $container->get( 'button.helper.three-d-secure' ); - $settings = $container->get( 'wcgateway.settings' ); - $dcc_applies = $container->get( 'api.helpers.dccapplies' ); - $order_helper = $container->get( 'api.order-helper' ); - $logger = $container->get( 'woocommerce.logger.woocommerce' ); + $request_data = $container->get( 'button.request-data' ); + $order_endpoint = $container->get( 'api.endpoint.order' ); + $session_handler = $container->get( 'session.handler' ); + $three_d_secure = $container->get( 'button.helper.three-d-secure' ); + $settings = $container->get( 'wcgateway.settings' ); + $dcc_applies = $container->get( 'api.helpers.dccapplies' ); + $order_helper = $container->get( 'api.order-helper' ); + $final_review_enabled = $container->get( 'blocks.settings.final_review_enabled' ); + $wc_order_creator = $container->get( 'button.helper.wc-order-creator' ); + $gateway = $container->get( 'wcgateway.paypal-gateway' ); + $logger = $container->get( 'woocommerce.logger.woocommerce' ); return new ApproveOrderEndpoint( $request_data, $order_endpoint, @@ -244,6 +248,9 @@ return array( $settings, $dcc_applies, $order_helper, + $final_review_enabled, + $gateway, + $wc_order_creator, $logger ); }, @@ -351,4 +358,8 @@ return array( 'button.handle-shipping-in-paypal' => static function ( ContainerInterface $container ): bool { return ! $container->get( 'blocks.settings.final_review_enabled' ); }, + + 'button.helper.wc-order-creator' => static function ( ContainerInterface $container ): WooCommerceOrderCreator { + return new WooCommerceOrderCreator( $container->get( 'wcgateway.funding-source.renderer' ), $container->get( 'session.handler' ) ); + }, ); diff --git a/modules/ppcp-button/src/Helper/WooCommerceOrderCreator.php b/modules/ppcp-button/src/Helper/WooCommerceOrderCreator.php new file mode 100644 index 000000000..7049c555b --- /dev/null +++ b/modules/ppcp-button/src/Helper/WooCommerceOrderCreator.php @@ -0,0 +1,173 @@ +funding_source_renderer = $funding_source_renderer; + $this->session_handler = $session_handler; + } + + /** + * Creates WC order based on given PayPal order. + * + * @param Order $order The PayPal order. + * @param array $line_items The list of line item IDs. + * @return WC_Order The WC order. + */ + public function create_from_paypal_order( Order $order, array $line_items ): WC_Order { + $wc_order = wc_create_order(); + + $this->configure_line_items( $wc_order, $line_items ); + $this->configure_shipping( $wc_order, $order->payer(), $order->purchase_units()[0]->shipping() ); + $this->configure_payment_source( $wc_order ); + $this->configure_customer( $wc_order ); + + $wc_order->calculate_totals(); + $wc_order->save(); + + return $wc_order; + } + + /** + * Configures the line items. + * + * @param WC_Order $wc_order The WC order. + * @param array $line_items The list of line item IDs. + * @return void + */ + protected function configure_line_items( WC_Order $wc_order, array $line_items ): void { + foreach ( $line_items as $line_item ) { + $product_id = $line_item['product_id'] ?? 0; + $variation_id = $line_item['variation_id'] ?? 0; + $args = $variation_id > 0 ? array( 'variation_id' => $variation_id ) : array(); + $quantity = $line_item['quantity'] ?? 0; + + $wc_order->add_product( wc_get_product( $product_id ), $quantity, $args ); + } + } + + /** + * Configures the shipping & billing addresses for WC order from given payer. + * + * @param WC_Order $wc_order The WC order. + * @param Payer $payer The payer. + * @param Shipping|null $shipping The shipping. + * @return void + */ + protected function configure_shipping( WC_Order $wc_order, Payer $payer, ?Shipping $shipping ): void { + $shipping_address = null; + + $address = $payer->address(); + + $billing_address = array( + 'first_name' => $payer->name()->given_name() ?? '', + 'last_name' => $payer->name()->surname() ?? '', + 'address_1' => $address->address_line_1() ?? '', + 'address_2' => $address->address_line_2() ?? '', + 'city' => $address->admin_area_2() ?? '', + 'state' => $address->admin_area_1() ?? '', + 'postcode' => $address->postal_code() ?? '', + 'country' => $address->country_code() ?? '', + ); + + if ( $shipping ) { + $address = $shipping->address(); + + $shipping_address = array( + 'first_name' => $shipping->name() ?? '', + 'last_name' => '', + 'address_1' => $address->address_line_1() ?? '', + 'address_2' => $address->address_line_2() ?? '', + 'city' => $address->admin_area_2() ?? '', + 'state' => $address->admin_area_1() ?? '', + 'postcode' => $address->postal_code() ?? '', + 'country' => $address->country_code() ?? '', + ); + } + + $wc_order->set_shipping_address( $shipping_address ?? $billing_address ); + $wc_order->set_billing_address( $billing_address ); + + $shipping_options = $shipping->options()[0] ?? ''; + + if ( $shipping_options ) { + $shipping = new WC_Order_Item_Shipping(); + $shipping->set_method_title( $shipping_options->label() ); + $shipping->set_method_id( $shipping_options->id() ); + $shipping->set_total( $shipping_options->amount()->value() ); + + $wc_order->add_item( $shipping ); + } + } + + /** + * Configures the payment source. + * + * @param WC_Order $wc_order The WC order. + * @return void + */ + protected function configure_payment_source( WC_Order $wc_order ): void { + $funding_source = $this->session_handler->funding_source(); + $wc_order->set_payment_method( PayPalGateway::ID ); + $wc_order->set_payment_method_title( $this->funding_source_renderer->render_name( $funding_source ) ); + } + + /** + * Configures the customer ID. + * + * @param WC_Order $wc_order The WC order. + * @return void + */ + protected function configure_customer( WC_Order $wc_order ): void { + $current_user = wp_get_current_user(); + + if ( $current_user->ID !== 0 ) { + $wc_order->set_customer_id( $current_user->ID ); + } + } + +}