diff --git a/modules/ppcp-api-client/services.php b/modules/ppcp-api-client/services.php index 199b14e78..bae6bc0fa 100644 --- a/modules/ppcp-api-client/services.php +++ b/modules/ppcp-api-client/services.php @@ -43,7 +43,6 @@ use WooCommerce\PayPalCommerce\ApiClient\Repository\PartnerReferralsData; use WooCommerce\PayPalCommerce\ApiClient\Repository\PayeeRepository; use WooCommerce\PayPalCommerce\ApiClient\Repository\PayPalRequestIdRepository; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; -use WpOop\TransientCache\CachePoolFactory; return array( 'api.host' => function( $container ) : string { diff --git a/modules/ppcp-api-client/src/Factory/class-payerfactory.php b/modules/ppcp-api-client/src/Factory/class-payerfactory.php index 3f9ee2755..9b9c57a8f 100644 --- a/modules/ppcp-api-client/src/Factory/class-payerfactory.php +++ b/modules/ppcp-api-client/src/Factory/class-payerfactory.php @@ -36,6 +36,42 @@ class PayerFactory { $this->address_factory = $address_factory; } + /** + * Returns a Payer entity from a WooCommerce order. + * + * @param \WC_Order $wc_order The WooCommerce order. + * + * @return Payer + */ + public function from_wc_order( \WC_Order $wc_order ): Payer { + $payer_id = ''; + $birthdate = null; + + $phone = null; + if ( $wc_order->get_billing_phone() ) { + // make sure the phone number contains only numbers and is max 14. chars long. + $national_number = $wc_order->get_billing_phone(); + $national_number = preg_replace( '/[^0-9]/', '', $national_number ); + $national_number = substr( $national_number, 0, 14 ); + + $phone = new PhoneWithType( + 'HOME', + new Phone( $national_number ) + ); + } + return new Payer( + new PayerName( + $wc_order->get_billing_first_name(), + $wc_order->get_billing_last_name() + ), + $wc_order->get_billing_email(), + $payer_id, + $this->address_factory->from_wc_order( $wc_order, 'billing' ), + $birthdate, + $phone + ); + } + /** * Returns a Payer object based off a WooCommerce customer. * diff --git a/modules/ppcp-button/resources/js/button.js b/modules/ppcp-button/resources/js/button.js index f52b8127d..e8ee26edd 100644 --- a/modules/ppcp-button/resources/js/button.js +++ b/modules/ppcp-button/resources/js/button.js @@ -2,6 +2,7 @@ import MiniCartBootstap from './modules/ContextBootstrap/MiniCartBootstap'; import SingleProductBootstap from './modules/ContextBootstrap/SingleProductBootstap'; import CartBootstrap from './modules/ContextBootstrap/CartBootstap'; import CheckoutBootstap from './modules/ContextBootstrap/CheckoutBootstap'; +import PayNowBootstrap from "./modules/ContextBootstrap/PayNowBootstrap"; import Renderer from './modules/Renderer/Renderer'; import ErrorHandler from './modules/ErrorHandler'; import CreditCardRenderer from "./modules/Renderer/CreditCardRenderer"; @@ -52,6 +53,15 @@ const bootstrap = () => { checkoutBootstap.init(); } + if (context === 'pay-now' ) { + const payNowBootstrap = new PayNowBootstrap( + PayPalCommerceGateway, + renderer, + messageRenderer + ); + payNowBootstrap.init(); + } + if (context !== 'checkout') { messageRenderer.render(); } diff --git a/modules/ppcp-button/resources/js/modules/ActionHandler/CheckoutActionHandler.js b/modules/ppcp-button/resources/js/modules/ActionHandler/CheckoutActionHandler.js index bd83ab1af..d0ceb882c 100644 --- a/modules/ppcp-button/resources/js/modules/ActionHandler/CheckoutActionHandler.js +++ b/modules/ppcp-button/resources/js/modules/ActionHandler/CheckoutActionHandler.js @@ -16,7 +16,8 @@ class CheckoutActionHandler { const errorHandler = this.errorHandler; - const formValues = jQuery('form.checkout').serialize(); + const formSelector = this.config.context === 'checkout' ? 'form.checkout' : 'form#order_review'; + const formValues = jQuery(formSelector).serialize(); return fetch(this.config.ajax.create_order.endpoint, { method: 'POST', @@ -25,6 +26,7 @@ class CheckoutActionHandler { payer, bn_code:bnCode, context:this.config.context, + order_id:this.config.order_id, form:formValues }) }).then(function (res) { @@ -38,7 +40,7 @@ class CheckoutActionHandler { input.setAttribute('type', 'hidden'); input.setAttribute('name', 'ppcp-resume-order'); input.setAttribute('value', data.data.purchase_units[0].custom_id); - document.querySelector('form.checkout').append(input); + document.querySelector(formSelector).append(input); return data.data.id; }); } diff --git a/modules/ppcp-button/resources/js/modules/ContextBootstrap/PayNowBootstrap.js b/modules/ppcp-button/resources/js/modules/ContextBootstrap/PayNowBootstrap.js new file mode 100644 index 000000000..b6b147802 --- /dev/null +++ b/modules/ppcp-button/resources/js/modules/ContextBootstrap/PayNowBootstrap.js @@ -0,0 +1,80 @@ +import ErrorHandler from '../ErrorHandler'; +import CheckoutActionHandler from '../ActionHandler/CheckoutActionHandler'; + +class PayNowBootstrap { + constructor(gateway, renderer, messages) { + this.gateway = gateway; + this.renderer = renderer; + this.messages = messages + } + + init() { + + this.render(); + + jQuery(document.body).on('updated_checkout', () => { + this.render(); + }); + + jQuery(document.body). + on('updated_checkout payment_method_selected', () => { + this.switchBetweenPayPalandOrderButton(); + }); + this.switchBetweenPayPalandOrderButton(); + } + + shouldRender() { + if (document.querySelector(this.gateway.button.cancel_wrapper)) { + return false; + } + + return document.querySelector(this.gateway.button.wrapper) !== null || document.querySelector(this.gateway.hosted_fields.wrapper) !== null; + } + + render() { + if (!this.shouldRender()) { + return; + } + if (document.querySelector(this.gateway.hosted_fields.wrapper + '>div')) { + document.querySelector(this.gateway.hosted_fields.wrapper + '>div').setAttribute('style', ''); + } + const actionHandler = new CheckoutActionHandler( + PayPalCommerceGateway, + new ErrorHandler(this.gateway.labels.error.generic), + ); + + this.renderer.render( + this.gateway.button.wrapper, + this.gateway.hosted_fields.wrapper, + actionHandler.configuration(), + ); + } + + switchBetweenPayPalandOrderButton() { + const currentPaymentMethod = jQuery( + 'input[name="payment_method"]:checked').val(); + + if (currentPaymentMethod !== 'ppcp-gateway' && currentPaymentMethod !== 'ppcp-credit-card-gateway') { + this.renderer.hideButtons(this.gateway.button.wrapper); + this.renderer.hideButtons(this.gateway.messages.wrapper); + this.renderer.hideButtons(this.gateway.hosted_fields.wrapper); + jQuery('#place_order').show(); + } + else { + jQuery('#place_order').hide(); + if (currentPaymentMethod === 'ppcp-gateway') { + this.renderer.showButtons(this.gateway.button.wrapper); + this.renderer.showButtons(this.gateway.messages.wrapper); + this.messages.render(); + this.renderer.hideButtons(this.gateway.hosted_fields.wrapper); + } + if (currentPaymentMethod === 'ppcp-credit-card-gateway') { + this.renderer.hideButtons(this.gateway.button.wrapper); + this.renderer.hideButtons(this.gateway.messages.wrapper); + this.renderer.showButtons(this.gateway.hosted_fields.wrapper); + } + } + } +} + +export default PayNowBootstrap; \ No newline at end of file diff --git a/modules/ppcp-button/resources/js/modules/OnApproveHandler/onApproveForPayNow.js b/modules/ppcp-button/resources/js/modules/OnApproveHandler/onApproveForPayNow.js index 61e9bcb9a..50431d83a 100644 --- a/modules/ppcp-button/resources/js/modules/OnApproveHandler/onApproveForPayNow.js +++ b/modules/ppcp-button/resources/js/modules/OnApproveHandler/onApproveForPayNow.js @@ -12,7 +12,7 @@ const onApprove = (context, errorHandler) => { if (!data.success) { errorHandler.genericError(); console.error(data); - if (typeof actions.restart !== 'undefined') { + if (typeof actions !== 'undefined' && typeof actions.restart !== 'undefined') { return actions.restart(); } throw new Error(data.data.message); diff --git a/modules/ppcp-button/resources/js/modules/Renderer/CreditCardRenderer.js b/modules/ppcp-button/resources/js/modules/Renderer/CreditCardRenderer.js index ec38441af..a423f26a3 100644 --- a/modules/ppcp-button/resources/js/modules/Renderer/CreditCardRenderer.js +++ b/modules/ppcp-button/resources/js/modules/Renderer/CreditCardRenderer.js @@ -10,7 +10,10 @@ class CreditCardRenderer { render(wrapper, contextConfig) { if ( - this.defaultConfig.context !== 'checkout' + ( + this.defaultConfig.context !== 'checkout' + && this.defaultConfig.context !== 'pay-now' + ) || wrapper === null || document.querySelector(wrapper) === null ) { diff --git a/modules/ppcp-button/services.php b/modules/ppcp-button/services.php index a4d288577..6b47c04a0 100644 --- a/modules/ppcp-button/services.php +++ b/modules/ppcp-button/services.php @@ -107,16 +107,18 @@ return array( return new ChangeCartEndpoint( $cart, $shipping, $request_data, $repository, $data_store ); }, 'button.endpoint.create-order' => static function ( $container ): CreateOrderEndpoint { - $request_data = $container->get( 'button.request-data' ); - $repository = $container->get( 'api.repository.cart' ); - $order_endpoint = $container->get( 'api.endpoint.order' ); - $payer_factory = $container->get( 'api.factory.payer' ); - $session_handler = $container->get( 'session.handler' ); - $settings = $container->get( 'wcgateway.settings' ); - $early_order_handler = $container->get( 'button.helper.early-order-handler' ); + $request_data = $container->get( 'button.request-data' ); + $cart_repository = $container->get( 'api.repository.cart' ); + $purchase_unit_factory = $container->get( 'api.factory.purchase-unit' ); + $order_endpoint = $container->get( 'api.endpoint.order' ); + $payer_factory = $container->get( 'api.factory.payer' ); + $session_handler = $container->get( 'session.handler' ); + $settings = $container->get( 'wcgateway.settings' ); + $early_order_handler = $container->get( 'button.helper.early-order-handler' ); return new CreateOrderEndpoint( $request_data, - $repository, + $cart_repository, + $purchase_unit_factory, $order_endpoint, $payer_factory, $session_handler, diff --git a/modules/ppcp-button/src/Assets/class-smartbutton.php b/modules/ppcp-button/src/Assets/class-smartbutton.php index 9e6ca8e99..03ebc806c 100644 --- a/modules/ppcp-button/src/Assets/class-smartbutton.php +++ b/modules/ppcp-button/src/Assets/class-smartbutton.php @@ -177,6 +177,15 @@ class SmartButton implements SmartButtonInterface { ), 11 ); + + add_action( + 'woocommerce_pay_order_after_submit', + array( + $this, + 'dcc_renderer', + ), + 11 + ); } return true; } @@ -232,6 +241,14 @@ class SmartButton implements SmartButtonInterface { ), 11 ); + add_action( + 'woocommerce_pay_order_after_submit', + array( + $this, + 'message_renderer', + ), + 11 + ); } return true; } @@ -294,6 +311,7 @@ class SmartButton implements SmartButtonInterface { } add_action( 'woocommerce_review_order_after_submit', array( $this, 'button_renderer' ), 10 ); + add_action( 'woocommerce_pay_order_after_submit', array( $this, 'button_renderer' ), 10 ); return true; } @@ -321,7 +339,7 @@ class SmartButton implements SmartButtonInterface { $load_script = true; } - if ( is_checkout() && $this->can_render_dcc() ) { + if ( in_array( $this->context(), array( 'pay-now', 'checkout' ), true ) && $this->can_render_dcc() ) { wp_enqueue_style( 'ppcp-hosted-fields', $this->module_url . '/assets/css/hosted-fields.css', @@ -474,7 +492,8 @@ class SmartButton implements SmartButtonInterface { */ private function can_render_dcc() : bool { - return $this->settings->has( 'dcc_enabled' ) && $this->settings->get( 'dcc_enabled' ) && $this->settings->has( 'client_id' ) && $this->settings->get( 'client_id' ) && $this->dcc_applies->for_country_currency(); + $can_render = $this->settings->has( 'dcc_enabled' ) && $this->settings->get( 'dcc_enabled' ) && $this->settings->has( 'client_id' ) && $this->settings->get( 'client_id' ) && $this->dcc_applies->for_country_currency(); + return $can_render; } /** @@ -502,6 +521,8 @@ class SmartButton implements SmartButtonInterface { esc_html__( 'Save your card', 'paypal-payments-for-woocommerce' ) ) : ''; + $label = 'checkout' === $this->context() ? __( 'Place order', 'paypal-payments-for-woocommerce' ) : __( 'Pay for order', 'paypal-payments-for-woocommerce' ); + printf( '