Skip to content

Commit c5b9533

Browse files
authored
Merge pull request #3518 from woocommerce/PCP-4951-fix-contacts-race-condition-in-block
Fix contacts race condition in block
2 parents cb10765 + ae0d143 commit c5b9533

File tree

3 files changed

+54
-10
lines changed

3 files changed

+54
-10
lines changed

modules/ppcp-wc-gateway/src/Gateway/PayPalGateway.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ class PayPalGateway extends \WC_Payment_Gateway {
6161
public const THREE_D_AUTH_RESULT_META_KEY = '_ppcp_paypal_3DS_auth_result';
6262
public const FRAUD_RESULT_META_KEY = '_ppcp_paypal_fraud_result';
6363

64+
// Used by the Contact Module integration.
65+
public const CONTACT_EMAIL_META_KEY = '_ppcp_paypal_contact_email';
66+
public const CONTACT_PHONE_META_KEY = '_ppcp_paypal_contact_phone';
67+
6468
// Used by the Contact Module integration to store the original details.
6569
public const ORIGINAL_EMAIL_META_KEY = '_ppcp_paypal_billing_email';
6670
public const ORIGINAL_PHONE_META_KEY = '_ppcp_paypal_billing_phone';

modules/ppcp-wc-gateway/src/Processor/OrderMetaTrait.php

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,16 +66,10 @@ public function add_paypal_meta(
6666
}
6767

6868
/**
69-
* Swaps out the billing details with the custom contact details provided by PayPal via the
70-
* "Contact Module" integration.
71-
*
72-
* The contact module can provide a custom email and phone number via the shipping details;
73-
* Though it's part of the shipping object, these two properties are intended to be treated
74-
* as primary contact details.
69+
* Adds the custom contact details provided by PayPal via the "Contact Module" integration.
7570
*
7671
* @param WC_Order $wc_order The WooCommerce order to update.
7772
* @param Order $order The PayPal order which provides the details.
78-
* @return void
7973
*/
8074
private function add_contact_details_to_wc_order( WC_Order $wc_order, Order $order ): void {
8175
$shipping_details = $this->get_shipping_details( $order );
@@ -87,25 +81,33 @@ private function add_contact_details_to_wc_order( WC_Order $wc_order, Order $ord
8781
$contact_email = $shipping_details->email_address();
8882
$contact_phone = $shipping_details->phone_number();
8983

84+
$added = false;
85+
9086
if ( $contact_email && is_email( $contact_email ) ) {
9187
$billing_email = $wc_order->get_billing_email();
9288

9389
if ( $billing_email && $billing_email !== $contact_email ) {
90+
$wc_order->update_meta_data( PayPalGateway::CONTACT_EMAIL_META_KEY, $contact_email );
9491
$wc_order->update_meta_data( PayPalGateway::ORIGINAL_EMAIL_META_KEY, $billing_email );
95-
}
9692

97-
$wc_order->set_billing_email( $contact_email );
93+
$added = true;
94+
}
9895
}
9996

10097
if ( $contact_phone ) {
10198
$billing_phone = $wc_order->get_billing_phone();
10299
$contact_phone_number = $contact_phone->national_number();
103100

104101
if ( $billing_phone && $billing_phone !== $contact_phone_number ) {
102+
$wc_order->update_meta_data( PayPalGateway::CONTACT_PHONE_META_KEY, $contact_phone_number );
105103
$wc_order->update_meta_data( PayPalGateway::ORIGINAL_PHONE_META_KEY, $billing_phone );
104+
105+
$added = true;
106106
}
107+
}
107108

108-
$wc_order->set_billing_phone( $contact_phone_number );
109+
if ( $added ) {
110+
do_action( 'woocommerce_paypal_payments_contacts_added', $wc_order, $order );
109111
}
110112
}
111113

modules/ppcp-wc-gateway/src/WCGatewayModule.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ public function extensions(): array {
9393
public function run( ContainerInterface $c ): bool {
9494
$this->register_payment_gateways( $c );
9595
$this->register_order_functionality( $c );
96+
$this->register_contact_handlers();
9697
$this->register_columns( $c );
9798
$this->register_checkout_paypal_address_preset( $c );
9899
$this->register_wc_tasks( $c );
@@ -1035,6 +1036,43 @@ private function is_order_paid_by_paypal( $order ): bool {
10351036
return false === strpos( $order->get_payment_method_title(), '(via PayPal)' );
10361037
}
10371038

1039+
/**
1040+
* Overwrite WC order email/phone.
1041+
*
1042+
* The contact module can provide a custom email and phone number.
1043+
* These two properties are intended to be treated as primary contact details.
1044+
*/
1045+
private function register_contact_handlers(): void {
1046+
$set_order_contacts = function ( WC_Order $wc_order ): void {
1047+
$email = $wc_order->get_meta( PayPalGateway::CONTACT_EMAIL_META_KEY );
1048+
$phone = $wc_order->get_meta( PayPalGateway::CONTACT_PHONE_META_KEY );
1049+
1050+
if ( $email && is_email( $email ) ) {
1051+
$wc_order->set_billing_email( $email );
1052+
}
1053+
if ( $phone && is_string( $phone ) ) {
1054+
$wc_order->set_billing_phone( $phone );
1055+
}
1056+
};
1057+
1058+
add_action(
1059+
'woocommerce_paypal_payments_contacts_added',
1060+
function ( WC_Order $wc_order ) use ( $set_order_contacts ): void {
1061+
$set_order_contacts( $wc_order );
1062+
}
1063+
);
1064+
// There is a race condition in express block checkout, the contacts set in woocommerce_paypal_payments_contacts_added
1065+
// may get reverted by another ajax WC request. So we set them again after that.
1066+
add_action(
1067+
'woocommerce_store_api_cart_update_order_from_request',
1068+
function ( WC_Order $wc_order ) use ( $set_order_contacts ): void {
1069+
// This hook fires for all methods, but we do not do anything if the meta is not set
1070+
// so probably no need to add additional checks.
1071+
$set_order_contacts( $wc_order );
1072+
}
1073+
);
1074+
}
1075+
10381076
/**
10391077
* Inserts custom fields into the order-detail view.
10401078
*

0 commit comments

Comments
 (0)