diff --git a/changelog.txt b/changelog.txt index 1b680e746..3ca38e0e2 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,6 +1,6 @@ *** Changelog *** -= 2.7.1 - xxxx-xx-xx = += 2.7.1 - 2024-05-28 = * Fix - Ensure package tracking data is sent to original PayPal transaction #2180 * Fix - Set the 'Woo_PPCP' as a default value for data-partner-attribution-id #2188 * Fix - Allow PUI Gateway for refund processor #2192 @@ -9,6 +9,7 @@ * Fix - Allow shipping callback and skipping confirmation page from any express button #2236 * Fix - Pay Later messaging configurator sometimes displays old settings after saving #2249 * Fix - Update the apple-developer-merchantid-domain-association validation strings for Apple Pay #2251 +* Fix - Enable the Shipping Callback handlers #2266 * Enhancement - Use admin theme color #1602 = 2.7.0 - 2024-04-30 = diff --git a/modules/ppcp-axo/resources/js/AxoManager.js b/modules/ppcp-axo/resources/js/AxoManager.js index 5229573ae..960da7f26 100644 --- a/modules/ppcp-axo/resources/js/AxoManager.js +++ b/modules/ppcp-axo/resources/js/AxoManager.js @@ -60,7 +60,6 @@ class AxoManager { } document.axoDebugObject = () => { - console.log(this); return this; } @@ -166,9 +165,8 @@ class AxoManager { this.$('form.woocommerce-checkout input').on('keydown', async (ev) => { if(ev.key === 'Enter' && getCurrentPaymentMethod() === 'ppcp-axo-gateway' ) { ev.preventDefault(); - log('Enter key attempt'); - log('emailInput', this.emailInput.value); - log('this.lastEmailCheckedIdentity', this.lastEmailCheckedIdentity); + log(`Enter key attempt - emailInput: ${this.emailInput.value}`); + log(`this.lastEmailCheckedIdentity: ${this.lastEmailCheckedIdentity}`); if (this.emailInput && this.lastEmailCheckedIdentity !== this.emailInput.value) { await this.onChangeEmail(); } @@ -177,7 +175,7 @@ class AxoManager { // Clear last email checked identity when email field is focused. this.$('#billing_email_field input').on('focus', (ev) => { - log('Clear the last email checked:', this.lastEmailCheckedIdentity); + log(`Clear the last email checked: ${this.lastEmailCheckedIdentity}`); this.lastEmailCheckedIdentity = ''; }); @@ -214,7 +212,7 @@ class AxoManager { this.status.hasProfile ); - log('Scenario', scenario); + log(`Scenario: ${JSON.stringify(scenario)}`); // Reset some elements to a default status. this.el.watermarkContainer.hide(); @@ -376,7 +374,7 @@ class AxoManager { setStatus(key, value) { this.status[key] = value; - log('Status updated', JSON.parse(JSON.stringify(this.status))); + log(`Status updated: ${JSON.stringify(this.status)}`); document.dispatchEvent(new CustomEvent("axo_status_updated", {detail: this.status})); @@ -388,9 +386,8 @@ class AxoManager { this.initFastlane(); this.setStatus('active', true); - log('Attempt on activation'); - log('emailInput', this.emailInput.value); - log('this.lastEmailCheckedIdentity', this.lastEmailCheckedIdentity); + log(`Attempt on activation - emailInput: ${this.emailInput.value}`); + log(`this.lastEmailCheckedIdentity: ${this.lastEmailCheckedIdentity}`); if (this.emailInput && this.lastEmailCheckedIdentity !== this.emailInput.value) { this.onChangeEmail(); } @@ -512,17 +509,15 @@ class AxoManager { } else { this.emailInput.addEventListener('change', async ()=> { - log('Change event attempt'); - log('emailInput', this.emailInput.value); - log('this.lastEmailCheckedIdentity', this.lastEmailCheckedIdentity); + log(`Change event attempt - emailInput: ${this.emailInput.value}`); + log(`this.lastEmailCheckedIdentity: ${this.lastEmailCheckedIdentity}`); if (this.emailInput && this.lastEmailCheckedIdentity !== this.emailInput.value) { this.onChangeEmail(); } }); - log('Last, this.emailInput.value attempt'); - log('emailInput', this.emailInput.value); - log('this.lastEmailCheckedIdentity', this.lastEmailCheckedIdentity); + log(`Last, this.emailInput.value attempt - emailInput: ${this.emailInput.value}`); + log(`this.lastEmailCheckedIdentity: ${this.lastEmailCheckedIdentity}`); if (this.emailInput.value) { this.onChangeEmail(); } @@ -542,7 +537,7 @@ class AxoManager { return; } - log('Email changed: ' + (this.emailInput ? this.emailInput.value : '')); + log(`Email changed: ${this.emailInput ? this.emailInput.value : ''}`); this.$(this.el.paymentContainer.selector + '-detail').html(''); this.$(this.el.paymentContainer.selector + '-form').html(''); @@ -579,6 +574,8 @@ class AxoManager { async lookupCustomerByEmail() { const lookupResponse = await this.fastlane.identity.lookupCustomerByEmail(this.emailInput.value); + log(`lookupCustomerByEmail: ${JSON.stringify(lookupResponse)}`); + if (lookupResponse.customerContextId) { // Email is associated with a Connect profile or a PayPal member. // Authenticate the customer to get access to their profile. @@ -586,11 +583,9 @@ class AxoManager { const authResponse = await this.fastlane.identity.triggerAuthenticationFlow(lookupResponse.customerContextId); - log('AuthResponse', authResponse); + log(`AuthResponse - triggerAuthenticationFlow: ${JSON.stringify(authResponse)}`); if (authResponse.authenticationState === 'succeeded') { - log(JSON.stringify(authResponse)); - const shippingData = authResponse.profileData.shippingAddress; if (shippingData) { this.setShipping(shippingData); @@ -697,7 +692,7 @@ class AxoManager { // TODO: validate data. if (this.data.card) { // Ryan flow - log('Ryan flow.'); + log('Starting Ryan flow.'); this.$('#ship-to-different-address-checkbox').prop('checked', 'checked'); @@ -708,20 +703,23 @@ class AxoManager { this.ensureBillingPhoneNumber(data); + log(`Ryan flow - submitted nonce: ${this.data.card.id}` ) + this.submit(this.data.card.id, data); } else { // Gary flow - log('Gary flow.'); + log('Starting Gary flow.'); try { this.cardComponent.getPaymentToken( this.tokenizeData() ).then((response) => { + log(`Gary flow - submitted nonce: ${response.id}` ) this.submit(response.id); }); } catch (e) { - log('Error tokenizing.'); alert('Error tokenizing data.'); + log(`Error tokenizing data. ${e.message}`, 'error'); } } } @@ -801,7 +799,9 @@ class AxoManager { scrollTop: $notices.offset().top }, 500); } - console.error('Failure:', responseData); + + log(`Error sending checkout form. ${responseData}`, 'error'); + this.hideLoading(); return; } @@ -810,7 +810,8 @@ class AxoManager { } }) .catch(error => { - console.error('Error:', error); + log(`Error sending checkout form. ${error.message}`, 'error'); + this.hideLoading(); }); diff --git a/modules/ppcp-axo/resources/js/Helper/Debug.js b/modules/ppcp-axo/resources/js/Helper/Debug.js index e473d4a3b..c08fa8087 100644 --- a/modules/ppcp-axo/resources/js/Helper/Debug.js +++ b/modules/ppcp-axo/resources/js/Helper/Debug.js @@ -1,4 +1,26 @@ +export function log(message, level = 'info') { + const endpoint = window.wc_ppcp_axo?.ajax?.frontend_logger?.endpoint; + if(!endpoint) { + return; + } -export function log(...args) { - //console.log('[AXO] ', ...args); + fetch(endpoint, { + method: 'POST', + credentials: 'same-origin', + body: JSON.stringify({ + nonce: window.wc_ppcp_axo.ajax.frontend_logger.nonce, + log: { + message, + level, + } + }) + }).then(() => { + switch (level) { + case 'error': + console.error(`[AXO] ${message}`); + break; + default: + console.log(`[AXO] ${message}`); + } + }); } diff --git a/modules/ppcp-axo/services.php b/modules/ppcp-axo/services.php index ffed3f1e2..0020169a7 100644 --- a/modules/ppcp-axo/services.php +++ b/modules/ppcp-axo/services.php @@ -225,4 +225,10 @@ return array( return '

' . $notice_content . '

'; }, + 'axo.endpoint.frontend-logger' => static function ( ContainerInterface $container ): FrontendLoggerEndpoint { + return new FrontendLoggerEndpoint( + $container->get( 'button.request-data' ), + $container->get( 'woocommerce.logger.woocommerce' ) + ); + }, ); diff --git a/modules/ppcp-axo/src/Assets/AxoManager.php b/modules/ppcp-axo/src/Assets/AxoManager.php index 24b574975..4e75f56fa 100644 --- a/modules/ppcp-axo/src/Assets/AxoManager.php +++ b/modules/ppcp-axo/src/Assets/AxoManager.php @@ -10,6 +10,7 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Axo\Assets; use Psr\Log\LoggerInterface; +use WooCommerce\PayPalCommerce\Axo\FrontendLoggerEndpoint; use WooCommerce\PayPalCommerce\Onboarding\Environment; use WooCommerce\PayPalCommerce\Session\SessionHandler; use WooCommerce\PayPalCommerce\WcGateway\Helper\SettingsStatus; @@ -209,6 +210,12 @@ class AxoManager { ), 'icons_directory' => esc_url( $this->wcgateway_module_url ) . 'assets/images/axo/', 'module_url' => untrailingslashit( $this->module_url ), + 'ajax' => array( + 'frontend_logger' => array( + 'endpoint' => \WC_AJAX::get_endpoint( FrontendLoggerEndpoint::ENDPOINT ), + 'nonce' => wp_create_nonce( FrontendLoggerEndpoint::nonce() ), + ), + ), ); } diff --git a/modules/ppcp-axo/src/AxoModule.php b/modules/ppcp-axo/src/AxoModule.php index 3770117c6..7a10c34ad 100644 --- a/modules/ppcp-axo/src/AxoModule.php +++ b/modules/ppcp-axo/src/AxoModule.php @@ -239,6 +239,16 @@ class AxoModule implements ModuleInterface { 1 ); + add_action( + 'wc_ajax_' . FrontendLoggerEndpoint::ENDPOINT, + static function () use ( $c ) { + $endpoint = $c->get( 'axo.endpoint.frontend-logger' ); + assert( $endpoint instanceof FrontendLoggerEndpoint ); + + $endpoint->handle_request(); + } + ); + // Add the markup necessary for displaying overlays and loaders for Axo on the checkout page. $this->add_checkout_loader_markup( $c ); } diff --git a/modules/ppcp-axo/src/FrontendLoggerEndpoint.php b/modules/ppcp-axo/src/FrontendLoggerEndpoint.php new file mode 100644 index 000000000..e17a819e4 --- /dev/null +++ b/modules/ppcp-axo/src/FrontendLoggerEndpoint.php @@ -0,0 +1,80 @@ +request_data = $request_data; + $this->logger = $logger; + } + + /** + * Returns the nonce. + * + * @return string + */ + public static function nonce(): string { + return self::ENDPOINT; + } + + /** + * Handles the request. + * + * @return bool + * @throws Exception On Error. + */ + public function handle_request(): bool { + $data = $this->request_data->read_request( $this->nonce() ); + $level = $data['log']['level'] ?? 'info'; + + switch ( $level ) { + case 'error': + $this->logger->error( '[AXO] ' . $data['log']['message'] ); + break; + default: + $this->logger->info( '[AXO] ' . $data['log']['message'] ); + break; + } + + wp_send_json_success(); + return true; + } +} diff --git a/modules/ppcp-button/resources/js/modules/Renderer/Renderer.js b/modules/ppcp-button/resources/js/modules/Renderer/Renderer.js index d7de31ec8..895a7845b 100644 --- a/modules/ppcp-button/resources/js/modules/Renderer/Renderer.js +++ b/modules/ppcp-button/resources/js/modules/Renderer/Renderer.js @@ -102,10 +102,10 @@ class Renderer { }, }; - // Check the condition and add the onShippingOptionsChange handler if needed + // Check the condition and add the handler if needed if (this.shouldHandleShippingInPaypal(venmoButtonClicked)) { - options.onShippingOptionsChange = (data, actions) => null; - options.onShippingAddressChange = (data, actions) => null; + options.onShippingOptionsChange = (data, actions) => handleShippingOptionsChange(data, actions, this.defaultSettings); + options.onShippingAddressChange = (data, actions) => handleShippingAddressChange(data, actions, this.defaultSettings); } return options; diff --git a/modules/ppcp-paylater-configurator/services.php b/modules/ppcp-paylater-configurator/services.php index de282b4c1..8be798d24 100644 --- a/modules/ppcp-paylater-configurator/services.php +++ b/modules/ppcp-paylater-configurator/services.php @@ -17,12 +17,14 @@ use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; return array( 'paylater-configurator.url' => static function ( ContainerInterface $container ): string { /** + * The return value must not contain a trailing slash. + * * Cannot return false for this path. * * @psalm-suppress PossiblyFalseArgument */ return plugins_url( - '/modules/ppcp-paylater-configurator/', + '/modules/ppcp-paylater-configurator', dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php' ); }, diff --git a/modules/ppcp-wc-gateway/src/Processor/OrderProcessor.php b/modules/ppcp-wc-gateway/src/Processor/OrderProcessor.php index d2b145b0b..4d1363361 100644 --- a/modules/ppcp-wc-gateway/src/Processor/OrderProcessor.php +++ b/modules/ppcp-wc-gateway/src/Processor/OrderProcessor.php @@ -220,9 +220,14 @@ class OrderProcessor { ); throw new PayPalOrderMissingException( - __( - 'Could not retrieve order. Maybe it was already completed or this browser is not supported. Please check your email or try again with a different browser.', - 'woocommerce-paypal-payments' + sprintf( + // translators: %s: Order history URL on My Account section. + esc_attr__( + 'There was an error processing your order. Please check for any charges in your payment method and review your order history before placing the order again.', + // phpcs:ignore WordPress.WP.I18n.TextDomainMismatch -- Intentionally "woocommerce" to reflect the original message. + 'woocommerce' + ), + esc_url( wc_get_account_endpoint_url( 'orders' ) ) ) ); } diff --git a/readme.txt b/readme.txt index ff494fa80..0c6bdbb1a 100644 --- a/readme.txt +++ b/readme.txt @@ -179,7 +179,7 @@ If you encounter issues with the PayPal buttons not appearing after an update, p == Changelog == -= 2.7.1 - xxxx-xx-xx = += 2.7.1 - 2024-05-28 = * Fix - Ensure package tracking data is sent to original PayPal transaction #2180 * Fix - Set the 'Woo_PPCP' as a default value for data-partner-attribution-id #2188 * Fix - Allow PUI Gateway for refund processor #2192 @@ -188,6 +188,7 @@ If you encounter issues with the PayPal buttons not appearing after an update, p * Fix - Allow shipping callback and skipping confirmation page from any express button #2236 * Fix - Pay Later messaging configurator sometimes displays old settings after saving #2249 * Fix - Update the apple-developer-merchantid-domain-association validation strings for Apple Pay #2251 +* Fix - Enable the Shipping Callback handlers #2266 * Enhancement - Use admin theme color #1602 = 2.7.0 - 2024-04-30 = diff --git a/yarn.lock b/yarn.lock index 722df19c5..81af54726 100644 --- a/yarn.lock +++ b/yarn.lock @@ -598,6 +598,11 @@ unbox-primitive@^1.0.2: has-symbols "^1.0.3" which-boxed-primitive "^1.0.2" +uuid@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== + validate-npm-package-license@^3.0.1: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"