From e70891d3591d6c229c0046a284147f98f66b7a77 Mon Sep 17 00:00:00 2001 From: Emili Castells Guasch Date: Tue, 16 Jul 2024 14:17:12 +0200 Subject: [PATCH] Add googlepay wc gateway --- .../ppcp-button/src/Assets/SmartButton.php | 1 + .../resources/js/GooglepayButton.js | 2 +- modules/ppcp-googlepay/services.php | 8 +- modules/ppcp-googlepay/src/Assets/Button.php | 1 + .../ppcp-googlepay/src/GooglePayGateway.php | 173 +++++++++++++++++- .../ppcp-googlepay/src/GooglepayModule.php | 4 +- 6 files changed, 184 insertions(+), 5 deletions(-) diff --git a/modules/ppcp-button/src/Assets/SmartButton.php b/modules/ppcp-button/src/Assets/SmartButton.php index 6b92a9084..1ce9804e2 100644 --- a/modules/ppcp-button/src/Assets/SmartButton.php +++ b/modules/ppcp-button/src/Assets/SmartButton.php @@ -34,6 +34,7 @@ use WooCommerce\PayPalCommerce\Button\Endpoint\ValidateCheckoutEndpoint; use WooCommerce\PayPalCommerce\Button\Helper\ContextTrait; use WooCommerce\PayPalCommerce\Button\Helper\DisabledFundingSources; use WooCommerce\PayPalCommerce\Button\Helper\MessagesApply; +use WooCommerce\PayPalCommerce\Googlepay\GooglePayGateway; use WooCommerce\PayPalCommerce\Onboarding\Environment; use WooCommerce\PayPalCommerce\PayLaterBlock\PayLaterBlockModule; use WooCommerce\PayPalCommerce\PayLaterWCBlocks\PayLaterWCBlocksModule; diff --git a/modules/ppcp-googlepay/resources/js/GooglepayButton.js b/modules/ppcp-googlepay/resources/js/GooglepayButton.js index 44daed173..5a6cac6a6 100644 --- a/modules/ppcp-googlepay/resources/js/GooglepayButton.js +++ b/modules/ppcp-googlepay/resources/js/GooglepayButton.js @@ -27,7 +27,7 @@ class GooglepayButton { this.log = function () { if ( this.buttonConfig.is_debug ) { - //console.log('[GooglePayButton]', ...arguments); + console.log( '[GooglePayButton]', ...arguments ); } }; } diff --git a/modules/ppcp-googlepay/services.php b/modules/ppcp-googlepay/services.php index 9d6cbd2a8..a566630e6 100644 --- a/modules/ppcp-googlepay/services.php +++ b/modules/ppcp-googlepay/services.php @@ -939,6 +939,12 @@ return array( ); }, 'googlepay.wc-gateway' => static function ( ContainerInterface $container ): GooglePayGateway { - return new GooglePayGateway(); + return new GooglePayGateway( + $container->get( 'wcgateway.order-processor' ), + $container->get( 'wc-subscriptions.helper' ), + $container->get( 'api.factory.paypal-checkout-url' ), + $container->get( 'wcgateway.processor.refunds' ), + $container->get( 'wcgateway.transaction-url-provider' ) + ); }, ); diff --git a/modules/ppcp-googlepay/src/Assets/Button.php b/modules/ppcp-googlepay/src/Assets/Button.php index 7e1d4962f..aa009b5b7 100644 --- a/modules/ppcp-googlepay/src/Assets/Button.php +++ b/modules/ppcp-googlepay/src/Assets/Button.php @@ -239,6 +239,7 @@ class Button implements ButtonInterface { $button_enabled_product = $this->settings_status->is_smart_button_enabled_for_location( 'product' ); $button_enabled_cart = $this->settings_status->is_smart_button_enabled_for_location( 'cart' ); $button_enabled_checkout = ! ( $this->context() === 'checkout' && $this->settings->has( 'googlepay_button_enabled' ) && $this->settings->get( 'googlepay_button_enabled' ) ); + $button_enabled_checkout = true; $button_enabled_payorder = true; $button_enabled_minicart = $this->settings_status->is_smart_button_enabled_for_location( 'mini-cart' ); diff --git a/modules/ppcp-googlepay/src/GooglePayGateway.php b/modules/ppcp-googlepay/src/GooglePayGateway.php index c2dc3effc..89c5f88a5 100644 --- a/modules/ppcp-googlepay/src/GooglePayGateway.php +++ b/modules/ppcp-googlepay/src/GooglePayGateway.php @@ -9,12 +9,78 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Googlepay; +use Exception; +use WC_Order; use WC_Payment_Gateway; +use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException; +use WooCommerce\PayPalCommerce\WcGateway\Exception\GatewayGenericException; +use WooCommerce\PayPalCommerce\WcGateway\Exception\PayPalOrderMissingException; +use WooCommerce\PayPalCommerce\WcGateway\Gateway\Messages; +use WooCommerce\PayPalCommerce\WcGateway\Gateway\ProcessPaymentTrait; +use WooCommerce\PayPalCommerce\WcGateway\Gateway\TransactionUrlProvider; +use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderProcessor; +use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor; +use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper; +/** + * Class GooglePayGateway + */ class GooglePayGateway extends WC_Payment_Gateway { + use ProcessPaymentTrait; + const ID = 'ppcp-googlepay'; - public function __construct() { + /** + * The processor for orders. + * + * @var OrderProcessor + */ + protected $order_processor; + + /** + * The subscription helper. + * + * @var SubscriptionHelper + */ + protected $subscription_helper; + + /** + * The function return the PayPal checkout URL for the given order ID. + * + * @var callable(string):string + */ + private $paypal_checkout_url_factory; + + /** + * The Refund Processor. + * + * @var RefundProcessor + */ + private $refund_processor; + + /** + * Service able to provide transaction url for an order. + * + * @var TransactionUrlProvider + */ + protected $transaction_url_provider; + + /** + * GooglePayGateway constructor. + * + * @param OrderProcessor $order_processor The Order Processor. + * @param SubscriptionHelper $subscription_helper The subscription helper. + * @param callable(string):string $paypal_checkout_url_factory The function return the PayPal checkout URL for the given order ID. + * @param RefundProcessor $refund_processor The Refund Processor. + * @param TransactionUrlProvider $transaction_url_provider Service providing transaction view URL based on order. + */ + public function __construct( + OrderProcessor $order_processor, + SubscriptionHelper $subscription_helper, + callable $paypal_checkout_url_factory, + RefundProcessor $refund_processor, + TransactionUrlProvider $transaction_url_provider + ) { $this->id = self::ID; $this->method_title = __( 'Google Pay', 'woocommerce-paypal-payments' ); @@ -25,6 +91,11 @@ class GooglePayGateway extends WC_Payment_Gateway { $this->init_form_fields(); $this->init_settings(); + $this->order_processor = $order_processor; + $this->subscription_helper = $subscription_helper; + $this->paypal_checkout_url_factory = $paypal_checkout_url_factory; + $this->refund_processor = $refund_processor; + $this->transaction_url_provider = $transaction_url_provider; } /** @@ -56,4 +127,104 @@ class GooglePayGateway extends WC_Payment_Gateway { ), ); } + + /** + * Process payment for a WooCommerce order. + * + * @param int $order_id The WooCommerce order id. + * + * @return array + */ + public function process_payment( $order_id ) { + $wc_order = wc_get_order( $order_id ); + if ( ! is_a( $wc_order, WC_Order::class ) ) { + return $this->handle_payment_failure( + null, + new GatewayGenericException( new Exception( 'WC order was not found.' ) ) + ); + } + + /** + * If customer has chosen change Subscription payment. + */ + if ( $this->subscription_helper->has_subscription( $order_id ) && $this->subscription_helper->is_subscription_change_payment() ) { + // phpcs:ignore WordPress.Security.NonceVerification.Missing + $saved_paypal_payment = wc_clean( wp_unslash( $_POST['saved_paypal_payment'] ?? '' ) ); + if ( $saved_paypal_payment ) { + $wc_order->update_meta_data( 'payment_token_id', $saved_paypal_payment ); + $wc_order->save(); + + return $this->handle_payment_success( $wc_order ); + } + } + + /** + * If the WC_Order is paid through the approved webhook. + */ + //phpcs:disable WordPress.Security.NonceVerification.Recommended + if ( isset( $_REQUEST['ppcp-resume-order'] ) && $wc_order->has_status( 'processing' ) ) { + return $this->handle_payment_success( $wc_order ); + } + //phpcs:enable WordPress.Security.NonceVerification.Recommended + + try { + try { + $this->order_processor->process( $wc_order ); + + do_action( 'woocommerce_paypal_payments_before_handle_payment_success', $wc_order ); + + return $this->handle_payment_success( $wc_order ); + } catch ( PayPalOrderMissingException $exc ) { + $order = $this->order_processor->create_order( $wc_order ); + + return array( + 'result' => 'success', + 'redirect' => ( $this->paypal_checkout_url_factory )( $order->id() ), + ); + } + } catch ( PayPalApiException $error ) { + return $this->handle_payment_failure( + $wc_order, + new Exception( + Messages::generic_payment_error_message() . ' ' . $error->getMessage(), + $error->getCode(), + $error + ) + ); + } catch ( Exception $error ) { + return $this->handle_payment_failure( $wc_order, $error ); + } + } + + /** + * Process refund. + * + * If the gateway declares 'refunds' support, this will allow it to refund. + * a passed in amount. + * + * @param int $order_id Order ID. + * @param float $amount Refund amount. + * @param string $reason Refund reason. + * @return boolean True or false based on success, or a WP_Error object. + */ + public function process_refund( $order_id, $amount = null, $reason = '' ) { + $order = wc_get_order( $order_id ); + if ( ! is_a( $order, \WC_Order::class ) ) { + return false; + } + return $this->refund_processor->process( $order, (float) $amount, (string) $reason ); + } + + /** + * Return transaction url for this gateway and given order. + * + * @param \WC_Order $order WC order to get transaction url by. + * + * @return string + */ + public function get_transaction_url( $order ): string { + $this->view_transaction_url = $this->transaction_url_provider->get_transaction_url_base( $order ); + + return parent::get_transaction_url( $order ); + } } diff --git a/modules/ppcp-googlepay/src/GooglepayModule.php b/modules/ppcp-googlepay/src/GooglepayModule.php index 03ad140bb..7c558c6a2 100644 --- a/modules/ppcp-googlepay/src/GooglepayModule.php +++ b/modules/ppcp-googlepay/src/GooglepayModule.php @@ -187,8 +187,8 @@ class GooglepayModule implements ModuleInterface { } ); - add_action('woocommerce_review_order_after_payment', function () { - echo '
'; + add_action('woocommerce_review_order_after_submit', function () { + echo '
Google Pay...
'; }); }