Skip to content

Commit

Permalink
Merge branch 'develop' into add/pass-blocks-checkout-appearance-on-in…
Browse files Browse the repository at this point in the history
…it-woopay
  • Loading branch information
hsingyuc authored Jul 15, 2024
2 parents e9b19e7 + 5036be7 commit 2618344
Show file tree
Hide file tree
Showing 14 changed files with 224 additions and 35 deletions.
4 changes: 4 additions & 0 deletions changelog/2024-07-11-21-06-01-653423
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: fix

Fix payment method title for Express Checkout Element orders.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: fix

Disable ECE for non shipping products if Tax is calculated on billing address.
4 changes: 4 additions & 0 deletions changelog/dev-bump-wc-version-9-1-2
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: dev

Bump WC tested up to version to 9.1.2
4 changes: 4 additions & 0 deletions changelog/fix-9005-fix-ece-button-width
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: minor
Type: fix

Fix Express Checkout Element button width.
4 changes: 4 additions & 0 deletions changelog/fix-send-optional-fields-data-to-woopay
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Significance: patch
Type: fix

Send optional fields data to WooPay.
8 changes: 8 additions & 0 deletions client/checkout/express-checkout-buttons.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@
}
}

// This fixes width calculation issues inside the iframe for blocks and shortcode pages.
.wcpay-payment-request-wrapper,
.wc-block-components-express-payment__event-buttons {
.StripeElement iframe {
max-width: unset;
}
}

.woocommerce-checkout .wcpay-payment-request-wrapper {
margin-bottom: 1.5em;
}
Expand Down
1 change: 1 addition & 0 deletions client/express-checkout/utils/normalize.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ export const normalizePayForOrderData = ( event, paymentMethodId ) => {
payment_method: 'woocommerce_payments',
'wcpay-payment-method': paymentMethodId,
express_payment_type: event?.expressPaymentType,
'wcpay-fraud-prevention-token': window.wcpayFraudPreventionToken ?? '',
};
};

Expand Down
2 changes: 2 additions & 0 deletions client/express-checkout/utils/test/normalize.js
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ describe( 'Express checkout normalization', () => {
expect( normalizePayForOrderData( event, 'pm_123456' ) ).toEqual( {
payment_method: 'woocommerce_payments',
'wcpay-payment-method': 'pm_123456',
'wcpay-fraud-prevention-token': 'token123',
express_payment_type: 'express',
} );
} );
Expand All @@ -315,6 +316,7 @@ describe( 'Express checkout normalization', () => {
).toEqual( {
payment_method: 'woocommerce_payments',
'wcpay-payment-method': '',
'wcpay-fraud-prevention-token': 'token123',
express_payment_type: undefined,
} );
} );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public function ajax_pay_for_order() {
throw new Exception( __( 'This order does not require payment!', 'woocommerce-payments' ) );
}

$this->add_order_meta( $order_id );
$this->express_checkout_button_helper->add_order_payment_method_title( $order_id );

// Load the gateway.
$all_gateways = WC()->payment_gateways->get_available_payment_gateways();
Expand Down Expand Up @@ -431,35 +431,4 @@ public function ajax_empty_cart() {

wp_send_json( [ 'result' => 'success' ] );
}

/**
* Add needed order meta
*
* @param integer $order_id The order ID.
*
* @return void
*/
public function add_order_meta( $order_id ) {
if ( empty( $_POST['express_payment_type'] ) || ! isset( $_POST['payment_method'] ) || 'woocommerce_payments' !== $_POST['payment_method'] ) { // phpcs:ignore WordPress.Security.NonceVerification
return;
}

$order = wc_get_order( $order_id );

$express_payment_type = wc_clean( wp_unslash( $_POST['express_payment_type'] ) ); // phpcs:ignore WordPress.Security.NonceVerification

$express_payment_titles = [
'apple_pay' => 'Apple Pay',
'google_pay' => 'Google Pay',
];

$suffix = apply_filters( 'wcpay_payment_request_payment_method_title_suffix', 'WooPayments' );
if ( ! empty( $suffix ) ) {
$suffix = " ($suffix)";
}

$payment_method_title = isset( $express_payment_titles[ $express_payment_type ] ) ? $express_payment_titles[ $express_payment_type ] : 'Express Payment';
$order->set_payment_method_title( $payment_method_title . $suffix );
$order->save();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ public function init() {
add_filter( 'woocommerce_registration_redirect', [ $this, 'get_login_redirect_url' ], 10, 3 );
add_action( 'wp_enqueue_scripts', [ $this, 'scripts' ] );
add_action( 'before_woocommerce_pay_form', [ $this, 'display_pay_for_order_page_html' ], 1 );
add_filter( 'woocommerce_gateway_title', [ $this, 'filter_gateway_title' ], 10, 2 );
add_action( 'woocommerce_checkout_order_processed', [ $this->express_checkout_helper, 'add_order_payment_method_title' ], 10, 2 );

$this->express_checkout_ajax_handler->init();
}
Expand Down Expand Up @@ -402,4 +404,31 @@ public function get_login_redirect_url( $redirect ) {

return $url;
}

/**
* Filters the gateway title to reflect the button type used.
*
* @param string $title Gateway title.
* @param string $id Gateway ID.
*/
public function filter_gateway_title( $title, $id ) {
if ( 'woocommerce_payments' !== $id || ! is_admin() ) {
return $title;
}

$order = $this->express_checkout_helper->get_current_order();
$method_title = is_object( $order ) ? $order->get_payment_method_title() : '';

if ( ! empty( $method_title ) ) {
if (
strpos( $method_title, 'Apple Pay' ) === 0
|| strpos( $method_title, 'Google Pay' ) === 0
|| strpos( $method_title, 'Payment Request' ) === 0 // Legacy PRB title.
) {
return $method_title;
}
}

return $title;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,26 @@ public function get_product() {
return null;
}

/**
* Used to get the order in admin edit page.
*
* @return WC_Order|WC_Order_Refund|bool
*/
public function get_current_order() {
global $theorder;
global $post;

if ( is_object( $theorder ) ) {
return $theorder;
}

if ( is_object( $post ) ) {
return wc_get_order( $post->ID );
}

return false;
}

/**
* Returns true if the provided WC_Product is a subscription, false otherwise.
*
Expand Down Expand Up @@ -397,6 +417,23 @@ public function should_show_express_checkout_button() {
return true;
}

// Non-shipping product and billing is calculated based on shopper billing addres. Excludes Pay for Order page.
if (
// If the product doesn't needs shipping.
(
// on the product page.
( $this->is_product() && ! $this->product_needs_shipping( $this->get_product() ) ) ||

// on the cart or checkout page.
( ( $this->is_cart() || $this->is_checkout() ) && ! WC()->cart->needs_shipping() )
)

// ...and billing is calculated based on billing address.
&& 'billing' === get_option( 'woocommerce_tax_based_on' )
) {
return false;
}

// Cart total is 0 or is on product page and product price is 0.
// Exclude pay-for-order pages from this check.
if (
Expand All @@ -411,6 +448,21 @@ public function should_show_express_checkout_button() {
return true;
}

/**
* Check if the passed product needs to be shipped.
*
* @param WC_Product $product The product to check.
*
* @return bool Returns true if the product requires shipping; otherwise, returns false.
*/
public function product_needs_shipping( WC_Product $product ) {
if ( ! $product ) {
return false;
}

return wc_shipping_enabled() && 0 !== wc_get_shipping_method_count( true ) && $product->needs_shipping();
}

/**
* Checks to make sure product type is supported.
*
Expand Down Expand Up @@ -1033,6 +1085,39 @@ public function update_shipping_method( $shipping_methods ) {
WC()->session->set( 'chosen_shipping_methods', $chosen_shipping_methods );
}

/**
* Add express checkout payment method title to the order.
*
* @param integer $order_id The order ID.
*
* @return void
*/
public function add_order_payment_method_title( $order_id ) {
if ( empty( $_POST['express_payment_type'] ) || ! isset( $_POST['payment_method'] ) || 'woocommerce_payments' !== $_POST['payment_method'] ) { // phpcs:ignore WordPress.Security.NonceVerification
return;
}

$express_payment_type = wc_clean( wp_unslash( $_POST['express_payment_type'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
$express_payment_titles = [
'apple_pay' => 'Apple Pay',
'google_pay' => 'Google Pay',
];
$payment_method_title = $express_payment_titles[ $express_payment_type ] ?? false;

if ( ! $payment_method_title ) {
return;
}

$suffix = apply_filters( 'wcpay_payment_request_payment_method_title_suffix', 'WooPayments' );
if ( ! empty( $suffix ) ) {
$suffix = " ($suffix)";
}

$order = wc_get_order( $order_id );
$order->set_payment_method_title( $payment_method_title . $suffix );
$order->save();
}

/**
* Calculate and set shipping method.
*
Expand Down
13 changes: 11 additions & 2 deletions includes/fraud-prevention/class-fraud-prevention-service.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ public static function maybe_append_fraud_prevention_token() {
return;
}

// Don't add the token if the user isn't on the cart, checkout or product page.
// Don't add the token if the user isn't on the cart, checkout, product or pay for order page.
// Checking the product and cart page too because the user can pay quickly via the payment buttons on that page.
if ( ! is_checkout() && ! is_cart() && ! is_product() ) {
if ( ! is_checkout() && ! is_cart() && ! is_product() && ! $instance->is_pay_for_order_page() ) {
return;
}

Expand All @@ -103,6 +103,15 @@ public static function maybe_append_fraud_prevention_token() {
);
}

/**
* Checks if this is the Pay for Order page.
*
* @return bool
*/
public function is_pay_for_order_page() {
return is_checkout() && isset( $_GET['pay_for_order'] ); // phpcs:ignore WordPress.Security.NonceVerification
}

/**
* Sets a instance to be used in request cycle.
* Introduced primarily for supporting unit tests.
Expand Down
66 changes: 66 additions & 0 deletions includes/woopay/class-woopay-session.php
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,7 @@ public static function get_init_session_request( $order_id = null, $key = null,
'return_url' => ! $is_pay_for_order ? wc_get_cart_url() : $order->get_checkout_payment_url(),
'blocks_data' => $blocks_data_extractor->get_data(),
'checkout_schema_namespaces' => $blocks_data_extractor->get_checkout_schema_namespaces(),
'optional_fields_status' => self::get_option_fields_status(),
],
'user_session' => null,
'preloaded_requests' => ! $is_pay_for_order ? [
Expand Down Expand Up @@ -796,4 +797,69 @@ private static function get_formatted_custom_message() {

return str_replace( array_keys( $replacement_map ), array_values( $replacement_map ), $custom_message );
}

/**
* Returns the status of checkout optional/required address fields.
*
* @return array The status of the checkout fields.
*/
private static function get_option_fields_status() {
// Shortcode checkout options.
$company = get_option( 'woocommerce_checkout_company_field', 'optional' );
$address_2 = get_option( 'woocommerce_checkout_address_2_field', 'optional' );
$phone = get_option( 'woocommerce_checkout_phone_field', 'required' );

// Blocks checkout options. To get the blocks checkout options, we need
// to parse the checkout page content because the options are stored
// in the blocks HTML as a JSON.
$checkout_page_id = get_option( 'woocommerce_checkout_page_id' );
$checkout_page = get_post( $checkout_page_id );

if ( empty( $checkout_page ) ) {
return [
'company' => $company,
'address_2' => $address_2,
'phone' => $phone,
];
}

$checkout_page_blocks = parse_blocks( $checkout_page->post_content );
$checkout_block_index = array_search( 'woocommerce/checkout', array_column( $checkout_page_blocks, 'blockName' ), true );

// If we can find the index, it means the merchant checkout page is using blocks checkout.
if ( false !== $checkout_block_index && ! empty( $checkout_page_blocks[ $checkout_block_index ]['attrs'] ) ) {
$checkout_block_attrs = $checkout_page_blocks[ $checkout_block_index ]['attrs'];

$company = 'optional';
$address_2 = 'optional';
$phone = 'optional';

if ( ! empty( $checkout_block_attrs['requireCompanyField'] ) ) {
$company = 'required';
}

if ( ! empty( $checkout_block_attrs['requirePhoneField'] ) ) {
$phone = 'required';
}

// showCompanyField is undefined by default.
if ( empty( $checkout_block_attrs['showCompanyField'] ) ) {
$company = 'hidden';
}

if ( isset( $checkout_block_attrs['showApartmentField'] ) && false === $checkout_block_attrs['showApartmentField'] ) {
$address_2 = 'hidden';
}

if ( isset( $checkout_block_attrs['showPhoneField'] ) && false === $checkout_block_attrs['showPhoneField'] ) {
$phone = 'hidden';
}
}

return [
'company' => $company,
'address_2' => $address_2,
'phone' => $phone,
];
}
}
2 changes: 1 addition & 1 deletion woocommerce-payments.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* Text Domain: woocommerce-payments
* Domain Path: /languages
* WC requires at least: 7.6
* WC tested up to: 8.9.3
* WC tested up to: 9.1.2
* Requires at least: 6.0
* Requires PHP: 7.3
* Version: 7.9.1
Expand Down

0 comments on commit 2618344

Please sign in to comment.