diff --git a/modules/ppcp-googlepay/resources/js/GooglepayButton.js b/modules/ppcp-googlepay/resources/js/GooglepayButton.js index 61b21a019..c70c67c01 100644 --- a/modules/ppcp-googlepay/resources/js/GooglepayButton.js +++ b/modules/ppcp-googlepay/resources/js/GooglepayButton.js @@ -104,7 +104,7 @@ class GooglepayButton { onPaymentAuthorized: this.onPaymentAuthorized.bind(this) } - if ( this.buttonConfig.enable_shipping ) { + if ( this.buttonConfig.shipping.enabled ) { callbacks['onPaymentDataChanged'] = this.onPaymentDataChanged.bind(this); } @@ -192,10 +192,10 @@ class GooglepayButton { paymentDataRequest.transactionInfo = await this.contextHandler.transactionInfo(); paymentDataRequest.merchantInfo = googlePayConfig.merchantInfo; - if ( this.buttonConfig.enable_shipping ) { + if ( this.buttonConfig.shipping.enabled ) { paymentDataRequest.callbackIntents = ["SHIPPING_ADDRESS", "SHIPPING_OPTION", "PAYMENT_AUTHORIZATION"]; paymentDataRequest.shippingAddressRequired = true; - paymentDataRequest.shippingAddressParameters = this.getGoogleShippingAddressParameters(); + paymentDataRequest.shippingAddressParameters = this.shippingAddressParameters(); paymentDataRequest.shippingOptionRequired = true; } else { paymentDataRequest.callbackIntents = ['PAYMENT_AUTHORIZATION']; @@ -204,22 +204,92 @@ class GooglepayButton { return paymentDataRequest; } - getGoogleShippingAddressParameters() { + //------------------------ + // Shipping processing + //------------------------ + + shippingAddressParameters() { return { - allowedCountryCodes: ['US'], + allowedCountryCodes: this.buttonConfig.shipping.countries, phoneNumberRequired: true }; } + onPaymentDataChanged(paymentData) { + console.log('[GooglePayButton] onPaymentDataChanged', this.context); + console.log('[GooglePayButton] paymentData', paymentData); + + return new Promise(async (resolve, reject) => { + let paymentDataRequestUpdate = {}; + + // TODO : update shipping in cart and get price + + if(false) { // TODO : on error + paymentDataRequestUpdate.error = this.unserviceableShippingAddressError(); + resolve(paymentDataRequestUpdate); + } + + switch (paymentData.callbackTrigger) { + case 'INITIALIZE': + case 'SHIPPING_ADDRESS': + paymentDataRequestUpdate.newShippingOptionParameters = this.shippingOptions(); + let selectedShippingOptionId = paymentDataRequestUpdate.newShippingOptionParameters.defaultSelectedOptionId; + paymentDataRequestUpdate.newTransactionInfo = await this.calculateNewTransactionInfo(selectedShippingOptionId); + break; + case 'SHIPPING_OPTION': + paymentDataRequestUpdate.newTransactionInfo = await this.calculateNewTransactionInfo(paymentData.shippingOptionData.id); + break; + } + + resolve(paymentDataRequestUpdate); + }); + } + + unserviceableShippingAddressError() { + return { + reason: "SHIPPING_ADDRESS_UNSERVICEABLE", + message: "Cannot ship to the selected address", + intent: "SHIPPING_ADDRESS" + }; + } + + async calculateNewTransactionInfo(shippingOptionId) { + let newTransactionInfo = await this.contextHandler.transactionInfo(); + + // TODO : update shipping in cart + + newTransactionInfo.totalPrice = Math.floor(10 + Math.random() * 100).toString(); // TODO : testing only + + return newTransactionInfo; + } + + shippingOptions() { + return { + defaultSelectedOptionId: "shipping-001", + shippingOptions: [ + { + "id": "shipping-001", + "label": "Free: Standard shipping", + "description": "Free Shipping delivered in 5 business days." + }, + { + "id": "shipping-002", + "label": "$1.99: Standard shipping", + "description": "Standard shipping delivered in 3 business days." + }, + { + "id": "shipping-003", + "label": "$10: Express shipping", + "description": "Express shipping delivered in 1 business day." + }, + ] + }; + } + //------------------------ // Payment process //------------------------ - onPaymentDataChanged(paymentData) { - console.log('[GooglePayButton] onPaymentDataChanged', this.context); - console.log('[GooglePayButton] paymentData', paymentData); - } - onPaymentAuthorized(paymentData) { console.log('[GooglePayButton] onPaymentAuthorized', this.context); return this.processPayment(paymentData); diff --git a/modules/ppcp-googlepay/src/Assets/Button.php b/modules/ppcp-googlepay/src/Assets/Button.php index 6524d611f..e23bf88de 100644 --- a/modules/ppcp-googlepay/src/Assets/Button.php +++ b/modules/ppcp-googlepay/src/Assets/Button.php @@ -11,6 +11,7 @@ namespace WooCommerce\PayPalCommerce\Googlepay\Assets; use Exception; use Psr\Log\LoggerInterface; +use WC_Countries; use WooCommerce\PayPalCommerce\Button\Assets\ButtonInterface; use WooCommerce\PayPalCommerce\Onboarding\Environment; use WooCommerce\PayPalCommerce\Session\SessionHandler; @@ -406,18 +407,26 @@ class Button implements ButtonInterface { * @return array */ public function script_data(): array { + $shipping = array( + 'enabled' => $this->settings->has( 'googlepay_button_shipping_enabled' ) + ? boolval( $this->settings->get( 'googlepay_button_shipping_enabled' ) ) + : false, + ); + + if ( $shipping['enabled'] ) { + $shipping['countries'] = array_keys( $this->wc_countries()->get_shipping_countries() ); + } + return array( - 'environment' => $this->environment->current_environment_is( Environment::SANDBOX ) ? 'TEST' : 'PRODUCTION', - 'sdk_url' => $this->sdk_url, - 'button' => array( + 'environment' => $this->environment->current_environment_is( Environment::SANDBOX ) ? 'TEST' : 'PRODUCTION', + 'sdk_url' => $this->sdk_url, + 'button' => array( 'wrapper' => '#ppc-button-googlepay-container', 'style' => $this->button_styles_for_context( 'cart' ), // For now use cart. Pass the context if necessary. 'mini_cart_wrapper' => '#ppc-button-googlepay-container-minicart', 'mini_cart_style' => $this->button_styles_for_context( 'mini-cart' ), ), - 'enable_shipping' => $this->settings->has( 'googlepay_button_shipping_enabled' ) - ? $this->settings->get( 'googlepay_button_shipping_enabled' ) - : false, + 'shipping' => $shipping, ); } @@ -449,4 +458,12 @@ class Button implements ButtonInterface { return $values; } + /** + * Returns a WC_Countries instance to check shipping + * + * @return WC_Countries + */ + private function wc_countries(): WC_Countries { + return new WC_Countries(); + } }