From e953ca111d179ca4c7a86c4e29842b0dd9122d40 Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Tue, 3 Dec 2024 11:41:44 -0800 Subject: [PATCH 01/35] Add customer payment methods --- src/inc/sift-events/sift-events.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/inc/sift-events/sift-events.php b/src/inc/sift-events/sift-events.php index 53360db..8695900 100644 --- a/src/inc/sift-events/sift-events.php +++ b/src/inc/sift-events/sift-events.php @@ -1022,6 +1022,23 @@ private static function get_order_address( string $order_id, string $type = 'bil private static function get_customer_payment_methods( int $user_id ) { $payment_methods = array(); + $customer_orders = wc_get_orders( + array( + 'limit' => -1, + 'customer' => $user_id, + 'status' => wc_get_is_paid_statuses(), + ) + ); + + $payment_methods = array_map( + function ( $order ) { + return $this->get_order_payment_methods( $order ); + }, + $customer_orders + ); + + $payment_methods = array_reduce( $payment_methods, fn( $payment_method ) => ! in_array( $payment_method, $payment_methods, true ) ); + /** * Include a filter here for unexpected payment providers to be able to add their results in as well. * From 3d72f4309d90d62567887761c60800785d31f37e Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Tue, 3 Dec 2024 12:05:56 -0800 Subject: [PATCH 02/35] Use singular payment method and remove empty values --- src/inc/sift-events/sift-events.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/inc/sift-events/sift-events.php b/src/inc/sift-events/sift-events.php index 8695900..54f29ec 100644 --- a/src/inc/sift-events/sift-events.php +++ b/src/inc/sift-events/sift-events.php @@ -1032,12 +1032,12 @@ private static function get_customer_payment_methods( int $user_id ) { $payment_methods = array_map( function ( $order ) { - return $this->get_order_payment_methods( $order ); + return $this->get_order_payment_methods( $order )[0] ?? null; }, $customer_orders ); - $payment_methods = array_reduce( $payment_methods, fn( $payment_method ) => ! in_array( $payment_method, $payment_methods, true ) ); + $payment_methods = array_reduce( $payment_methods, fn( $payment_method ) => ! empty( $payment_method ) && ! in_array( $payment_method, $payment_methods, true ) ); /** * Include a filter here for unexpected payment providers to be able to add their results in as well. From c7304c76db0a38de8913a0af9bc410c8acb5950f Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Tue, 3 Dec 2024 14:41:31 -0800 Subject: [PATCH 03/35] Return an empty array so that it passes validation --- src/inc/sift-events/sift-events.php | 48 +++++++++++++++++++---------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/src/inc/sift-events/sift-events.php b/src/inc/sift-events/sift-events.php index 54f29ec..9623142 100644 --- a/src/inc/sift-events/sift-events.php +++ b/src/inc/sift-events/sift-events.php @@ -1017,27 +1017,39 @@ private static function get_order_address( string $order_id, string $type = 'bil * * @param integer $user_id The User / Customer ID. * - * @return array|null + * @return array */ private static function get_customer_payment_methods( int $user_id ) { $payment_methods = array(); - $customer_orders = wc_get_orders( - array( - 'limit' => -1, - 'customer' => $user_id, - 'status' => wc_get_is_paid_statuses(), - ) - ); - - $payment_methods = array_map( - function ( $order ) { - return $this->get_order_payment_methods( $order )[0] ?? null; - }, - $customer_orders - ); + /** + * Allow / disallow customer payment method lookup via looping over all customer orders and extracting the payment method from each order. + * + * If this filter returns false, the sift_for_woocommerce_get_customer_payment_methods filter should be implemented so that some payment methods are returned. + * + * Otherwise, no customer payment methods will be returned. + * + * @param boolean $allow True if this method of payment method lookup should be used, otherwise false. + * @param integer $user_id The User / Customer ID. + * + * @return boolean True if this method of payment method lookup should be used, otherwise false. + */ + if ( apply_filters( 'sift_for_woocommerce_get_customer_payment_methods_via_order_enumeration', false, $user_id ) ) { + $customer_orders = wc_get_orders( + array( + 'limit' => -1, + 'customer' => $user_id, + 'status' => wc_get_is_paid_statuses(), + ) + ); - $payment_methods = array_reduce( $payment_methods, fn( $payment_method ) => ! empty( $payment_method ) && ! in_array( $payment_method, $payment_methods, true ) ); + $payment_methods = array_map( + function ( $order ) { + return static::get_order_payment_methods( $order )[0] ?? null; + }, + $customer_orders + ); + } /** * Include a filter here for unexpected payment providers to be able to add their results in as well. @@ -1047,7 +1059,9 @@ function ( $order ) { */ $payment_methods = apply_filters( 'sift_for_woocommerce_get_customer_payment_methods', $payment_methods, $user_id ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound - return $payment_methods ?? null; + $payment_methods = array_reduce( $payment_methods, fn( $payment_method ) => ! empty( $payment_method ) && ! in_array( $payment_method, $payment_methods, true ) ); + + return $payment_methods ?? []; } /** From cf08f8f99a86cff0262011ebfc5e76266d8d647a Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Tue, 3 Dec 2024 14:45:16 -0800 Subject: [PATCH 04/35] Delint --- src/inc/sift-events/sift-events.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/inc/sift-events/sift-events.php b/src/inc/sift-events/sift-events.php index 9623142..2c6c2c7 100644 --- a/src/inc/sift-events/sift-events.php +++ b/src/inc/sift-events/sift-events.php @@ -1061,7 +1061,7 @@ function ( $order ) { $payment_methods = array_reduce( $payment_methods, fn( $payment_method ) => ! empty( $payment_method ) && ! in_array( $payment_method, $payment_methods, true ) ); - return $payment_methods ?? []; + return $payment_methods ?? array(); } /** From 23970099eaac15698aa4cd40bee5048e55ed5265 Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Tue, 3 Dec 2024 15:18:00 -0800 Subject: [PATCH 05/35] Allow enumeration --- src/inc/sift-events/sift-events.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/inc/sift-events/sift-events.php b/src/inc/sift-events/sift-events.php index 2c6c2c7..82cc326 100644 --- a/src/inc/sift-events/sift-events.php +++ b/src/inc/sift-events/sift-events.php @@ -1034,7 +1034,7 @@ private static function get_customer_payment_methods( int $user_id ) { * * @return boolean True if this method of payment method lookup should be used, otherwise false. */ - if ( apply_filters( 'sift_for_woocommerce_get_customer_payment_methods_via_order_enumeration', false, $user_id ) ) { + if ( apply_filters( 'sift_for_woocommerce_get_customer_payment_methods_via_order_enumeration', true, $user_id ) ) { $customer_orders = wc_get_orders( array( 'limit' => -1, From 58f98f7517a3fa7a21e57dceb7e37e3f907c0234 Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Tue, 3 Dec 2024 15:51:20 -0800 Subject: [PATCH 06/35] Try using get_current_user_id when sourcing user_id --- src/inc/sift-events/sift-events.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/inc/sift-events/sift-events.php b/src/inc/sift-events/sift-events.php index 82cc326..c9cd9bd 100644 --- a/src/inc/sift-events/sift-events.php +++ b/src/inc/sift-events/sift-events.php @@ -565,7 +565,7 @@ public static function update_or_create_order( string $order_id, \WC_Order $orde } // Determine user and session context. - $user_id = wp_get_current_user()->ID ?? null; // Check first for logged-in user. + $user_id = get_current_user_id() ?? wp_get_current_user()->ID ?? null; // Check first for logged-in user. $is_system = ! $create_order && str_starts_with( sanitize_title( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ?? '' ) ), 'WordPress' ); // Check if this is an order update via system action. // Figure out if it should use the session ID if no logged-in user exists. From c60b05bccf00f3fc4bd8440be98fecf3104e4446 Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Wed, 4 Dec 2024 10:58:38 -0800 Subject: [PATCH 07/35] Remove payment_method if empty --- src/inc/sift-events/sift-events.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/inc/sift-events/sift-events.php b/src/inc/sift-events/sift-events.php index c9cd9bd..2ac9f4d 100644 --- a/src/inc/sift-events/sift-events.php +++ b/src/inc/sift-events/sift-events.php @@ -332,6 +332,10 @@ public static function update_account( string $user_id, ?\WP_User $old_user_data '$time' => intval( 1000 * microtime( true ) ), ); + if ( empty( $properties['$payment_methods'] ) ) { + unset( $properties['$payment_methods'] ); + } + try { SiftEventsValidator::validate_update_account( $properties ); } catch ( \Exception $e ) { From e15f7918ced76a983e3efb91d82a866e813340b7 Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Wed, 4 Dec 2024 12:59:09 -0800 Subject: [PATCH 08/35] Try to source the user id from order if returned user is admin --- src/inc/sift-events/sift-events.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/inc/sift-events/sift-events.php b/src/inc/sift-events/sift-events.php index 2ac9f4d..6c7c665 100644 --- a/src/inc/sift-events/sift-events.php +++ b/src/inc/sift-events/sift-events.php @@ -571,9 +571,10 @@ public static function update_or_create_order( string $order_id, \WC_Order $orde // Determine user and session context. $user_id = get_current_user_id() ?? wp_get_current_user()->ID ?? null; // Check first for logged-in user. $is_system = ! $create_order && str_starts_with( sanitize_title( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ?? '' ) ), 'WordPress' ); // Check if this is an order update via system action. + $is_admin = 1 === $user_id; // Figure out if it should use the session ID if no logged-in user exists. - if ( ! $user_id ) { + if ( ! $user_id || $is_admin ) { $user_id = $is_system ? $order->get_user_id() : null; // Use order user ID only for system actions. } From 8d46b3ef22913861fb424262187272a377d8b38f Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Wed, 4 Dec 2024 13:39:46 -0800 Subject: [PATCH 09/35] Use user id from order when is_admin --- src/inc/sift-events/sift-events.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/inc/sift-events/sift-events.php b/src/inc/sift-events/sift-events.php index 6c7c665..b395ea1 100644 --- a/src/inc/sift-events/sift-events.php +++ b/src/inc/sift-events/sift-events.php @@ -575,7 +575,7 @@ public static function update_or_create_order( string $order_id, \WC_Order $orde // Figure out if it should use the session ID if no logged-in user exists. if ( ! $user_id || $is_admin ) { - $user_id = $is_system ? $order->get_user_id() : null; // Use order user ID only for system actions. + $user_id = $is_system || $is_admin ? $order->get_user_id() : null; // Use order user ID only for system actions. } $user = $user_id ? get_userdata( $user_id ) : null; From 55a00f3a1be2345fd3a6e507a31bbdc84fa5131e Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Wed, 4 Dec 2024 13:47:17 -0800 Subject: [PATCH 10/35] Try using session id in this case --- src/inc/sift-events/sift-events.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/inc/sift-events/sift-events.php b/src/inc/sift-events/sift-events.php index b395ea1..4b21674 100644 --- a/src/inc/sift-events/sift-events.php +++ b/src/inc/sift-events/sift-events.php @@ -578,6 +578,10 @@ public static function update_or_create_order( string $order_id, \WC_Order $orde $user_id = $is_system || $is_admin ? $order->get_user_id() : null; // Use order user ID only for system actions. } + if ( ! $user_id ) { + $user_id = \WC()->session->get_customer_unique_id(); + } + $user = $user_id ? get_userdata( $user_id ) : null; $physical_or_electronic = '$electronic'; From c0acb38d6e91044176b654c5b2110c8a3d768b78 Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Thu, 5 Dec 2024 11:22:57 -0800 Subject: [PATCH 11/35] Add debugging for woocommerce-payments integration --- src/inc/payment-gateways/woocommerce-payments.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/inc/payment-gateways/woocommerce-payments.php b/src/inc/payment-gateways/woocommerce-payments.php index 836e9f8..ff7d9e1 100644 --- a/src/inc/payment-gateways/woocommerce-payments.php +++ b/src/inc/payment-gateways/woocommerce-payments.php @@ -27,12 +27,14 @@ function ( $value, \WC_Order $order ) { try { $charge_id = \WC_Payments::get_order_service()->get_charge_id_for_order( $order ); if ( empty( $charge_id ) ) { + error_log( '[sift-for-woocommerce] woocommerce-payments - Could not get charge_id from order, could not obtain payment method details.' ); return $value; } $api_client = \WC_Payments::get_payments_api_client(); $charge = $api_client->get_charge( $charge_id ); return $charge['payment_method_details']; - } catch ( \Exception ) { + } catch ( \Exception $e ) { + error_log( '[sift-for-woocommerce] woocommerce-payments - Caught exception when getting payment method details from order: ' . $e->getMessage() ); return $value; } }, @@ -46,11 +48,13 @@ function ( $value, \WC_Order $order ) { try { $charge_id = \WC_Payments::get_order_service()->get_charge_id_for_order( $order ); if ( empty( $charge_id ) ) { + error_log( '[sift-for-woocommerce] woocommerce-payments - could not get charge_id from order, could not obtain charge details.' ); return $value; } $api_client = \WC_Payments::get_payments_api_client(); return $api_client->get_charge( $charge_id ); - } catch ( \Exception ) { + } catch ( \Exception $e ) { + error_log( '[sift-for-woocommerce] woocommerce-payments - Caught exception when getting charge details from order: ' . $e->getMessage() ); return $value; } }, From 6ca58235ce9e821722e0e3996cadb6db0b375e65 Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Thu, 5 Dec 2024 11:47:47 -0800 Subject: [PATCH 12/35] Add more temporary debug statements --- src/inc/sift-events/sift-events.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/inc/sift-events/sift-events.php b/src/inc/sift-events/sift-events.php index 4b21674..48312c9 100644 --- a/src/inc/sift-events/sift-events.php +++ b/src/inc/sift-events/sift-events.php @@ -559,6 +559,11 @@ public static function create_order( string $order_id, \WC_Order $order ) { * @return void */ public static function update_or_create_order( string $order_id, \WC_Order $order, bool $create_order = false ) { + if ( $create_order ) { + error_log( '[sift-for-woocommerce] creating order' ); + } else { + error_log( '[sift-for-woocommerce] updating order' ); + } if ( ! in_array( $order->get_status(), self::SUPPORTED_WOO_ORDER_STATUS_CHANGES, true ) ) { return; @@ -572,15 +577,22 @@ public static function update_or_create_order( string $order_id, \WC_Order $orde $user_id = get_current_user_id() ?? wp_get_current_user()->ID ?? null; // Check first for logged-in user. $is_system = ! $create_order && str_starts_with( sanitize_title( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ?? '' ) ), 'WordPress' ); // Check if this is an order update via system action. $is_admin = 1 === $user_id; + error_log( '[sift-for-woocommerce] get_current_user_id() ' . get_current_user_id() ); + error_log( '[sift-for-woocommerce] wp_get_current_user()->ID ' . wp_get_current_user()->ID ); + error_log( '[sift-for-woocommerce] user_id ' . $user_id ); + error_log( '[sift-for-woocommerce] is_system ' . $is_system ); + error_log( '[sift-for-woocommerce] is_admin ' . $is_admin ); // Figure out if it should use the session ID if no logged-in user exists. if ( ! $user_id || $is_admin ) { $user_id = $is_system || $is_admin ? $order->get_user_id() : null; // Use order user ID only for system actions. } + error_log( '[sift-for-woocommerce] user_id (from order) ' . $user_id ); if ( ! $user_id ) { $user_id = \WC()->session->get_customer_unique_id(); } + error_log( '[sift-for-woocommerce] user_id (from customer unique id) ' . $user_id ); $user = $user_id ? get_userdata( $user_id ) : null; @@ -1029,6 +1041,7 @@ private static function get_order_address( string $order_id, string $type = 'bil * @return array */ private static function get_customer_payment_methods( int $user_id ) { + error_log( '[sift-for-woocommerce] getting customer payment methods' ); $payment_methods = array(); /** @@ -1084,6 +1097,7 @@ function ( $order ) { * @return array */ private static function get_order_payment_methods( \WC_Order $order ) { + error_log( '[sift-for-woocommerce] getting order payment methods' ); $sift_order = new Sift_Order( $order ); return $sift_order->get_payment_methods(); } From 53d38260dbb1170f6489f7e8d871d55706c158c8 Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Thu, 5 Dec 2024 11:58:25 -0800 Subject: [PATCH 13/35] Add more temp debug logging --- src/inc/sift-events/sift-events.php | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/inc/sift-events/sift-events.php b/src/inc/sift-events/sift-events.php index 48312c9..a8dcf84 100644 --- a/src/inc/sift-events/sift-events.php +++ b/src/inc/sift-events/sift-events.php @@ -560,10 +560,11 @@ public static function create_order( string $order_id, \WC_Order $order ) { */ public static function update_or_create_order( string $order_id, \WC_Order $order, bool $create_order = false ) { if ( $create_order ) { - error_log( '[sift-for-woocommerce] creating order' ); + error_log( '[sift-for-woocommerce] creating order ' . $order_id ); } else { - error_log( '[sift-for-woocommerce] updating order' ); + error_log( '[sift-for-woocommerce] updating order ' . $order_id ); } + error_log( '[sift-for-woocommerce] order number '. $order->get_order_number() ); if ( ! in_array( $order->get_status(), self::SUPPORTED_WOO_ORDER_STATUS_CHANGES, true ) ) { return; @@ -577,22 +578,22 @@ public static function update_or_create_order( string $order_id, \WC_Order $orde $user_id = get_current_user_id() ?? wp_get_current_user()->ID ?? null; // Check first for logged-in user. $is_system = ! $create_order && str_starts_with( sanitize_title( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ?? '' ) ), 'WordPress' ); // Check if this is an order update via system action. $is_admin = 1 === $user_id; - error_log( '[sift-for-woocommerce] get_current_user_id() ' . get_current_user_id() ); - error_log( '[sift-for-woocommerce] wp_get_current_user()->ID ' . wp_get_current_user()->ID ); - error_log( '[sift-for-woocommerce] user_id ' . $user_id ); + error_log( '[sift-for-woocommerce] 1: get_current_user_id() ' . get_current_user_id() ); + error_log( '[sift-for-woocommerce] 2: wp_get_current_user()->ID ' . wp_get_current_user()->ID ); + error_log( '[sift-for-woocommerce] user_id (from 1 or 2) ' . $user_id ); error_log( '[sift-for-woocommerce] is_system ' . $is_system ); error_log( '[sift-for-woocommerce] is_admin ' . $is_admin ); // Figure out if it should use the session ID if no logged-in user exists. if ( ! $user_id || $is_admin ) { $user_id = $is_system || $is_admin ? $order->get_user_id() : null; // Use order user ID only for system actions. + error_log( '[sift-for-woocommerce] user_id (from order) ' . $user_id ); } - error_log( '[sift-for-woocommerce] user_id (from order) ' . $user_id ); if ( ! $user_id ) { $user_id = \WC()->session->get_customer_unique_id(); + error_log( '[sift-for-woocommerce] user_id (from customer unique id) ' . $user_id ); } - error_log( '[sift-for-woocommerce] user_id (from customer unique id) ' . $user_id ); $user = $user_id ? get_userdata( $user_id ) : null; @@ -647,6 +648,9 @@ public static function update_or_create_order( string $order_id, \WC_Order $orde '$time' => intval( 1000 * microtime( true ) ), ); + error_log( '[sift-for-woocommerce] $payment_methods: ' ); + error_log( print_r( $properties['$payment_methods'] ) ); + // Add the user_id only if a user exists, otherwise, let it remain empty. // Ref: https://developers.sift.com/docs/php/apis-overview/core-topics/faq/tracking-users if ( $user ) { From 5a304b56b8269c104d124e626729b03dd40fc101 Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Thu, 5 Dec 2024 12:10:26 -0800 Subject: [PATCH 14/35] Fix debugging bug --- src/inc/sift-events/sift-events.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/inc/sift-events/sift-events.php b/src/inc/sift-events/sift-events.php index a8dcf84..eaff402 100644 --- a/src/inc/sift-events/sift-events.php +++ b/src/inc/sift-events/sift-events.php @@ -649,7 +649,7 @@ public static function update_or_create_order( string $order_id, \WC_Order $orde ); error_log( '[sift-for-woocommerce] $payment_methods: ' ); - error_log( print_r( $properties['$payment_methods'] ) ); + error_log( print_r( $properties['$payment_methods'], true ) ); // Add the user_id only if a user exists, otherwise, let it remain empty. // Ref: https://developers.sift.com/docs/php/apis-overview/core-topics/faq/tracking-users From 8ea0b104e3b7fc83154d24df99b7f6fa3417d6ce Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Thu, 5 Dec 2024 12:20:21 -0800 Subject: [PATCH 15/35] Log events as they are sent to Sift --- src/inc/sift-events/sift-events.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/inc/sift-events/sift-events.php b/src/inc/sift-events/sift-events.php index eaff402..05f82d5 100644 --- a/src/inc/sift-events/sift-events.php +++ b/src/inc/sift-events/sift-events.php @@ -836,9 +836,12 @@ public static function chargeback( string $order_id, \WC_Order $order, string $c * @return void */ public static function add( string $event, array $properties ) { - + error_log( '[sift-for-woocommerce] add ' . $event . ' with properties:' ); + error_log( print_r( $properties, true ) ); // Give a chance for the platform to modify the data (and add potentially new custom data) $properties = apply_filters( 'sift_for_woocommerce_pre_send_event_properties', $properties, $event ); + error_log( '[sift-for-woocommerce] add ' . $event . ' with filtered properties:' ); + error_log( print_r( $properties, true ) ); array_push( self::$to_send, @@ -867,6 +870,7 @@ public static function send() { if ( self::count() > 0 ) { $client = \Sift_For_WooCommerce\Sift_For_WooCommerce::get_api_client(); if ( empty( $client ) ) { + error_log( '[sift-for-woocommerce] send failed to send events to Sift (no client)' ); wc_get_logger()->error( 'Failed to send events to Sift', array( @@ -898,6 +902,7 @@ public static function send() { 'response' => $response, ) ); + error_log( '[sift-for-woocommerce] send ' . $log_title ); } // Now that it's sent, clear the $to_send static in case it was run manually. From 44702cb5f0cee5fc42c4b210cf1a26d6307ff430 Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Thu, 5 Dec 2024 12:38:41 -0800 Subject: [PATCH 16/35] Try to find missing event with temp debug logs --- src/inc/sift-events/sift-events.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/inc/sift-events/sift-events.php b/src/inc/sift-events/sift-events.php index 05f82d5..72d0803 100644 --- a/src/inc/sift-events/sift-events.php +++ b/src/inc/sift-events/sift-events.php @@ -867,6 +867,7 @@ private static function count() { * @return boolean */ public static function send() { + error_log( '[sift-for-woocommerce] send called with ' . static::count() . ' events to send' ); if ( self::count() > 0 ) { $client = \Sift_For_WooCommerce\Sift_For_WooCommerce::get_api_client(); if ( empty( $client ) ) { @@ -908,8 +909,10 @@ public static function send() { // Now that it's sent, clear the $to_send static in case it was run manually. self::$to_send = array(); + error_log( '[sift-for-woocommerce] send finished, returning true' ); return true; } + error_log( '[sift-for-woocommerce] send finished, returning false' ); return false; } From a3a67777c2e9e07ebae63d0d58bcdf345c3fd4da Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Thu, 5 Dec 2024 13:15:33 -0800 Subject: [PATCH 17/35] Use user id from order if it isn't otherwise available --- src/inc/sift-events/sift-events.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/inc/sift-events/sift-events.php b/src/inc/sift-events/sift-events.php index 72d0803..de03778 100644 --- a/src/inc/sift-events/sift-events.php +++ b/src/inc/sift-events/sift-events.php @@ -586,7 +586,7 @@ public static function update_or_create_order( string $order_id, \WC_Order $orde // Figure out if it should use the session ID if no logged-in user exists. if ( ! $user_id || $is_admin ) { - $user_id = $is_system || $is_admin ? $order->get_user_id() : null; // Use order user ID only for system actions. + $user_id = $order->get_user_id() ?? null; // Use order user ID if it isn't available otherwise error_log( '[sift-for-woocommerce] user_id (from order) ' . $user_id ); } From 35b789d86606f3dea7242d9e8231978ff5165523 Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Thu, 5 Dec 2024 13:30:12 -0800 Subject: [PATCH 18/35] Add debugging logs for getting customer payment methods --- src/inc/sift-events/sift-events.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/inc/sift-events/sift-events.php b/src/inc/sift-events/sift-events.php index de03778..84caac2 100644 --- a/src/inc/sift-events/sift-events.php +++ b/src/inc/sift-events/sift-events.php @@ -1069,6 +1069,7 @@ private static function get_customer_payment_methods( int $user_id ) { * @return boolean True if this method of payment method lookup should be used, otherwise false. */ if ( apply_filters( 'sift_for_woocommerce_get_customer_payment_methods_via_order_enumeration', true, $user_id ) ) { + error_log( '[sift-for-woocommerce] will enumerate orders while getting customer payment methods' ); $customer_orders = wc_get_orders( array( 'limit' => -1, @@ -1083,6 +1084,8 @@ function ( $order ) { }, $customer_orders ); + error_log( '[sift-for-woocommerce] got payment methods from enumerate orders while getting customer payment methods:' ); + error_log( print_r( $payment_methods, true ) ); } /** @@ -1092,8 +1095,12 @@ function ( $order ) { * @param integer $user_id The User / Customer ID. */ $payment_methods = apply_filters( 'sift_for_woocommerce_get_customer_payment_methods', $payment_methods, $user_id ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound + error_log( '[sift-for-woocommerce] filtered payment methods while getting customer payment methods:' ); + error_log( print_r( $payment_methods, true ) ); $payment_methods = array_reduce( $payment_methods, fn( $payment_method ) => ! empty( $payment_method ) && ! in_array( $payment_method, $payment_methods, true ) ); + error_log( '[sift-for-woocommerce] reduced filtered payment methods while getting customer payment methods:' ); + error_log( print_r( $payment_methods, true ) ); return $payment_methods ?? array(); } From 93304f5d13099b5f2b6fa0fdfe7a50b969f85bfe Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Thu, 5 Dec 2024 13:34:30 -0800 Subject: [PATCH 19/35] Use array filter instead of array reduce --- src/inc/sift-events/sift-events.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/inc/sift-events/sift-events.php b/src/inc/sift-events/sift-events.php index 84caac2..17475b3 100644 --- a/src/inc/sift-events/sift-events.php +++ b/src/inc/sift-events/sift-events.php @@ -1098,7 +1098,7 @@ function ( $order ) { error_log( '[sift-for-woocommerce] filtered payment methods while getting customer payment methods:' ); error_log( print_r( $payment_methods, true ) ); - $payment_methods = array_reduce( $payment_methods, fn( $payment_method ) => ! empty( $payment_method ) && ! in_array( $payment_method, $payment_methods, true ) ); + $payment_methods = array_filter( $payment_methods, fn( $payment_method ) => ! empty( $payment_method ) && ! in_array( $payment_method, $payment_methods, true ) ); error_log( '[sift-for-woocommerce] reduced filtered payment methods while getting customer payment methods:' ); error_log( print_r( $payment_methods, true ) ); From 318240e1d7cbfcacd5a41ebfbbd0dd8e1e7839b3 Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Thu, 5 Dec 2024 13:42:35 -0800 Subject: [PATCH 20/35] Use array_reduce correctly --- src/inc/sift-events/sift-events.php | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/inc/sift-events/sift-events.php b/src/inc/sift-events/sift-events.php index 17475b3..88a4770 100644 --- a/src/inc/sift-events/sift-events.php +++ b/src/inc/sift-events/sift-events.php @@ -564,7 +564,7 @@ public static function update_or_create_order( string $order_id, \WC_Order $orde } else { error_log( '[sift-for-woocommerce] updating order ' . $order_id ); } - error_log( '[sift-for-woocommerce] order number '. $order->get_order_number() ); + error_log( '[sift-for-woocommerce] order number ' . $order->get_order_number() ); if ( ! in_array( $order->get_status(), self::SUPPORTED_WOO_ORDER_STATUS_CHANGES, true ) ) { return; @@ -1098,7 +1098,15 @@ function ( $order ) { error_log( '[sift-for-woocommerce] filtered payment methods while getting customer payment methods:' ); error_log( print_r( $payment_methods, true ) ); - $payment_methods = array_filter( $payment_methods, fn( $payment_method ) => ! empty( $payment_method ) && ! in_array( $payment_method, $payment_methods, true ) ); + $payment_methods = array_reduce( + $payment_methods, + function ( $payment_methods, $payment_method ) { + if ( ! empty( $payment_method ) && ! in_array( $payment_method, $payment_methods, true ) ) { + $payment_methods[] = $payment_method; + } + return $payment_methods; + } + ); error_log( '[sift-for-woocommerce] reduced filtered payment methods while getting customer payment methods:' ); error_log( print_r( $payment_methods, true ) ); From 84b2a67e8b7549583b7589578d6936179fc2bf87 Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Thu, 5 Dec 2024 13:46:56 -0800 Subject: [PATCH 21/35] Seed the array_reduce function correctly --- src/inc/sift-events/sift-events.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/inc/sift-events/sift-events.php b/src/inc/sift-events/sift-events.php index 88a4770..d370866 100644 --- a/src/inc/sift-events/sift-events.php +++ b/src/inc/sift-events/sift-events.php @@ -1105,7 +1105,8 @@ function ( $payment_methods, $payment_method ) { $payment_methods[] = $payment_method; } return $payment_methods; - } + }, + array() ); error_log( '[sift-for-woocommerce] reduced filtered payment methods while getting customer payment methods:' ); error_log( print_r( $payment_methods, true ) ); From 858a91347e69fadf29b1c6b629750f925d3c8420 Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Thu, 5 Dec 2024 14:01:21 -0800 Subject: [PATCH 22/35] Cache customer orders --- src/inc/sift-events/sift-events.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/inc/sift-events/sift-events.php b/src/inc/sift-events/sift-events.php index d370866..311f7a3 100644 --- a/src/inc/sift-events/sift-events.php +++ b/src/inc/sift-events/sift-events.php @@ -25,6 +25,8 @@ class Events { public static $to_send = array(); + private static $sift_orders = array(); + const SUPPORTED_WOO_ORDER_STATUS_CHANGES = array( 'pending', 'processing', @@ -1126,8 +1128,10 @@ function ( $payment_methods, $payment_method ) { */ private static function get_order_payment_methods( \WC_Order $order ) { error_log( '[sift-for-woocommerce] getting order payment methods' ); - $sift_order = new Sift_Order( $order ); - return $sift_order->get_payment_methods(); + if ( ! array_key_exists( $order->get_order_key(), static::$sift_orders ) ) { + static::$sift_orders[ $order->get_order_key() ] = new Sift_Order( $order ); + } + return static::$sift_orders[ $order->get_order_key() ]->get_payment_methods(); } /** From b7ef122b236ac752c4a97f518a6d55063349b672 Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Thu, 5 Dec 2024 14:07:41 -0800 Subject: [PATCH 23/35] Remove debug logs --- src/inc/sift-events/sift-events.php | 35 ----------------------------- 1 file changed, 35 deletions(-) diff --git a/src/inc/sift-events/sift-events.php b/src/inc/sift-events/sift-events.php index 311f7a3..f83dcd5 100644 --- a/src/inc/sift-events/sift-events.php +++ b/src/inc/sift-events/sift-events.php @@ -561,13 +561,6 @@ public static function create_order( string $order_id, \WC_Order $order ) { * @return void */ public static function update_or_create_order( string $order_id, \WC_Order $order, bool $create_order = false ) { - if ( $create_order ) { - error_log( '[sift-for-woocommerce] creating order ' . $order_id ); - } else { - error_log( '[sift-for-woocommerce] updating order ' . $order_id ); - } - error_log( '[sift-for-woocommerce] order number ' . $order->get_order_number() ); - if ( ! in_array( $order->get_status(), self::SUPPORTED_WOO_ORDER_STATUS_CHANGES, true ) ) { return; } @@ -580,21 +573,14 @@ public static function update_or_create_order( string $order_id, \WC_Order $orde $user_id = get_current_user_id() ?? wp_get_current_user()->ID ?? null; // Check first for logged-in user. $is_system = ! $create_order && str_starts_with( sanitize_title( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ?? '' ) ), 'WordPress' ); // Check if this is an order update via system action. $is_admin = 1 === $user_id; - error_log( '[sift-for-woocommerce] 1: get_current_user_id() ' . get_current_user_id() ); - error_log( '[sift-for-woocommerce] 2: wp_get_current_user()->ID ' . wp_get_current_user()->ID ); - error_log( '[sift-for-woocommerce] user_id (from 1 or 2) ' . $user_id ); - error_log( '[sift-for-woocommerce] is_system ' . $is_system ); - error_log( '[sift-for-woocommerce] is_admin ' . $is_admin ); // Figure out if it should use the session ID if no logged-in user exists. if ( ! $user_id || $is_admin ) { $user_id = $order->get_user_id() ?? null; // Use order user ID if it isn't available otherwise - error_log( '[sift-for-woocommerce] user_id (from order) ' . $user_id ); } if ( ! $user_id ) { $user_id = \WC()->session->get_customer_unique_id(); - error_log( '[sift-for-woocommerce] user_id (from customer unique id) ' . $user_id ); } $user = $user_id ? get_userdata( $user_id ) : null; @@ -650,9 +636,6 @@ public static function update_or_create_order( string $order_id, \WC_Order $orde '$time' => intval( 1000 * microtime( true ) ), ); - error_log( '[sift-for-woocommerce] $payment_methods: ' ); - error_log( print_r( $properties['$payment_methods'], true ) ); - // Add the user_id only if a user exists, otherwise, let it remain empty. // Ref: https://developers.sift.com/docs/php/apis-overview/core-topics/faq/tracking-users if ( $user ) { @@ -838,12 +821,8 @@ public static function chargeback( string $order_id, \WC_Order $order, string $c * @return void */ public static function add( string $event, array $properties ) { - error_log( '[sift-for-woocommerce] add ' . $event . ' with properties:' ); - error_log( print_r( $properties, true ) ); // Give a chance for the platform to modify the data (and add potentially new custom data) $properties = apply_filters( 'sift_for_woocommerce_pre_send_event_properties', $properties, $event ); - error_log( '[sift-for-woocommerce] add ' . $event . ' with filtered properties:' ); - error_log( print_r( $properties, true ) ); array_push( self::$to_send, @@ -869,11 +848,9 @@ private static function count() { * @return boolean */ public static function send() { - error_log( '[sift-for-woocommerce] send called with ' . static::count() . ' events to send' ); if ( self::count() > 0 ) { $client = \Sift_For_WooCommerce\Sift_For_WooCommerce::get_api_client(); if ( empty( $client ) ) { - error_log( '[sift-for-woocommerce] send failed to send events to Sift (no client)' ); wc_get_logger()->error( 'Failed to send events to Sift', array( @@ -905,16 +882,13 @@ public static function send() { 'response' => $response, ) ); - error_log( '[sift-for-woocommerce] send ' . $log_title ); } // Now that it's sent, clear the $to_send static in case it was run manually. self::$to_send = array(); - error_log( '[sift-for-woocommerce] send finished, returning true' ); return true; } - error_log( '[sift-for-woocommerce] send finished, returning false' ); return false; } @@ -1055,7 +1029,6 @@ private static function get_order_address( string $order_id, string $type = 'bil * @return array */ private static function get_customer_payment_methods( int $user_id ) { - error_log( '[sift-for-woocommerce] getting customer payment methods' ); $payment_methods = array(); /** @@ -1071,7 +1044,6 @@ private static function get_customer_payment_methods( int $user_id ) { * @return boolean True if this method of payment method lookup should be used, otherwise false. */ if ( apply_filters( 'sift_for_woocommerce_get_customer_payment_methods_via_order_enumeration', true, $user_id ) ) { - error_log( '[sift-for-woocommerce] will enumerate orders while getting customer payment methods' ); $customer_orders = wc_get_orders( array( 'limit' => -1, @@ -1086,8 +1058,6 @@ function ( $order ) { }, $customer_orders ); - error_log( '[sift-for-woocommerce] got payment methods from enumerate orders while getting customer payment methods:' ); - error_log( print_r( $payment_methods, true ) ); } /** @@ -1097,8 +1067,6 @@ function ( $order ) { * @param integer $user_id The User / Customer ID. */ $payment_methods = apply_filters( 'sift_for_woocommerce_get_customer_payment_methods', $payment_methods, $user_id ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound - error_log( '[sift-for-woocommerce] filtered payment methods while getting customer payment methods:' ); - error_log( print_r( $payment_methods, true ) ); $payment_methods = array_reduce( $payment_methods, @@ -1110,8 +1078,6 @@ function ( $payment_methods, $payment_method ) { }, array() ); - error_log( '[sift-for-woocommerce] reduced filtered payment methods while getting customer payment methods:' ); - error_log( print_r( $payment_methods, true ) ); return $payment_methods ?? array(); } @@ -1127,7 +1093,6 @@ function ( $payment_methods, $payment_method ) { * @return array */ private static function get_order_payment_methods( \WC_Order $order ) { - error_log( '[sift-for-woocommerce] getting order payment methods' ); if ( ! array_key_exists( $order->get_order_key(), static::$sift_orders ) ) { static::$sift_orders[ $order->get_order_key() ] = new Sift_Order( $order ); } From 92869e4fa69927ba2d76c81b48f0121fa81f1b50 Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Thu, 5 Dec 2024 14:24:28 -0800 Subject: [PATCH 24/35] Remove log from woocommerce-payments integration --- src/inc/payment-gateways/woocommerce-payments.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/inc/payment-gateways/woocommerce-payments.php b/src/inc/payment-gateways/woocommerce-payments.php index ff7d9e1..6efa0ec 100644 --- a/src/inc/payment-gateways/woocommerce-payments.php +++ b/src/inc/payment-gateways/woocommerce-payments.php @@ -27,14 +27,12 @@ function ( $value, \WC_Order $order ) { try { $charge_id = \WC_Payments::get_order_service()->get_charge_id_for_order( $order ); if ( empty( $charge_id ) ) { - error_log( '[sift-for-woocommerce] woocommerce-payments - Could not get charge_id from order, could not obtain payment method details.' ); return $value; } $api_client = \WC_Payments::get_payments_api_client(); $charge = $api_client->get_charge( $charge_id ); return $charge['payment_method_details']; } catch ( \Exception $e ) { - error_log( '[sift-for-woocommerce] woocommerce-payments - Caught exception when getting payment method details from order: ' . $e->getMessage() ); return $value; } }, @@ -48,13 +46,11 @@ function ( $value, \WC_Order $order ) { try { $charge_id = \WC_Payments::get_order_service()->get_charge_id_for_order( $order ); if ( empty( $charge_id ) ) { - error_log( '[sift-for-woocommerce] woocommerce-payments - could not get charge_id from order, could not obtain charge details.' ); return $value; } $api_client = \WC_Payments::get_payments_api_client(); return $api_client->get_charge( $charge_id ); } catch ( \Exception $e ) { - error_log( '[sift-for-woocommerce] woocommerce-payments - Caught exception when getting charge details from order: ' . $e->getMessage() ); return $value; } }, From 72162510667533560c65c381ee9bfc986a4692e8 Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Thu, 5 Dec 2024 14:32:41 -0800 Subject: [PATCH 25/35] Promote order cache to singleton --- src/inc/sift-events/sift-events.php | 8 ++------ src/sift-for-woocommerce.php | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/inc/sift-events/sift-events.php b/src/inc/sift-events/sift-events.php index f83dcd5..21a7505 100644 --- a/src/inc/sift-events/sift-events.php +++ b/src/inc/sift-events/sift-events.php @@ -17,6 +17,7 @@ use Sift_For_WooCommerce\Sift_Order; use Sift_For_WooCommerce\Sift\SiftEventsValidator; +use Sift_For_WooCommerce\Sift_For_WooCommerce; use WC_Product; /** @@ -25,8 +26,6 @@ class Events { public static $to_send = array(); - private static $sift_orders = array(); - const SUPPORTED_WOO_ORDER_STATUS_CHANGES = array( 'pending', 'processing', @@ -1093,10 +1092,7 @@ function ( $payment_methods, $payment_method ) { * @return array */ private static function get_order_payment_methods( \WC_Order $order ) { - if ( ! array_key_exists( $order->get_order_key(), static::$sift_orders ) ) { - static::$sift_orders[ $order->get_order_key() ] = new Sift_Order( $order ); - } - return static::$sift_orders[ $order->get_order_key() ]->get_payment_methods(); + return Sift_For_WooCommerce::get_instance()->get_sift_order_from_wc_order( $order )->get_payment_methods(); } /** diff --git a/src/sift-for-woocommerce.php b/src/sift-for-woocommerce.php index af6e08c..ea9cad8 100644 --- a/src/sift-for-woocommerce.php +++ b/src/sift-for-woocommerce.php @@ -20,6 +20,8 @@ */ class Sift_For_WooCommerce { + private static $sift_orders = array(); + // region MAGIC METHODS /** @@ -132,5 +134,20 @@ public static function get_api_client() { return $client; } + /** + * Get a Sift_Order object from a WC_Order object. + * Allows a small speed up in performance due to caching the orders. + * + * @param \WC_Order $order The WC_Order object. + * + * @return Sift_Order The Sift_Order object. + */ + public static function get_sift_order_from_wc_order( \WC_Order $order ): Sift_Order { + if ( ! array_key_exists( $order->get_order_key(), static::$sift_orders ) ) { + static::$sift_orders[ $order->get_order_key() ] = new Sift_Order( $order ); + } + return static::$sift_orders[ $order->get_order_key() ]; + } + // endregion } From 8459132af46a54ed28d7bdadcca99b7f26e9f7e8 Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Thu, 5 Dec 2024 16:14:03 -0800 Subject: [PATCH 26/35] Get payments from purchase-unit in order instead of purchase unit from factory --- src/inc/payment-gateways/ppcp-gateway.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/inc/payment-gateways/ppcp-gateway.php b/src/inc/payment-gateways/ppcp-gateway.php index 20c58ac..5dbe31c 100644 --- a/src/inc/payment-gateways/ppcp-gateway.php +++ b/src/inc/payment-gateways/ppcp-gateway.php @@ -44,13 +44,13 @@ function get_from_order( $value, \WC_Order $order ) { add_filter( 'sift_for_woocommerce_ppcp-gateway_payment_type_string', fn( $value, $ppcp_gateway_payment_type ) => 'ppcp' === $ppcp_gateway_payment_type ? '$third_party_processor' : $value ); add_filter( 'sift_for_woocommerce_ppcp-gateway_card_last4', fn( $value, $ppcp_data ) => $ppcp_data['wc_order']?->get_meta_data( PayPalGateway::FRAUD_RESULT_META_KEY )['card_last_digits'] ?? $value, 10, 2 ); -add_filter( 'sift_for_woocommerce_ppcp-gateway_avs_result_code', fn( $value, $ppcp_data ) => $ppcp_data['purchase-unit']?->payments()?->authorizations()[0]?->fraud_processor_response()->avs_code() ?? $value, 10, 2 ); -add_filter( 'sift_for_woocommerce_ppcp-gateway_cvv_result_code', fn( $value, $ppcp_data ) => $ppcp_data['purchase-unit']?->payments()?->authorizations()[0]?->fraud_processor_response()->cvv_code() ?? $value, 10, 2 ); -add_filter( 'sift_for_woocommerce_ppcp-gateway_verification_status', fn( $value, $ppcp_data ) => $ppcp_data['purchase-unit']?->payments()?->authorizations()[0]?->status() ?? $value, 10, 2 ); -add_filter( 'sift_for_woocommerce_ppcp-gateway_decline_reason_code', fn( $value, $ppcp_data ) => $ppcp_data['purchase-unit']?->payments()?->authorizations()[0]?->to_array()['reason_code'] ?? $value, 10, 2 ); +add_filter( 'sift_for_woocommerce_ppcp-gateway_avs_result_code', fn( $value, $ppcp_data ) => $ppcp_data['order']?->purchase_units()[0]?->payments()?->authorizations()[0]?->fraud_processor_response()->avs_code() ?? $value, 10, 2 ); +add_filter( 'sift_for_woocommerce_ppcp-gateway_cvv_result_code', fn( $value, $ppcp_data ) => $ppcp_data['order']?->purchase_units()[0]?->payments()?->authorizations()[0]?->fraud_processor_response()->cvv_code() ?? $value, 10, 2 ); +add_filter( 'sift_for_woocommerce_ppcp-gateway_verification_status', fn( $value, $ppcp_data ) => $ppcp_data['order']?->purchase_units()[0]?->payments()?->authorizations()[0]?->status() ?? $value, 10, 2 ); +add_filter( 'sift_for_woocommerce_ppcp-gateway_decline_reason_code', fn( $value, $ppcp_data ) => $ppcp_data['order']?->purchase_units()[0]?->payments()?->authorizations()[0]?->to_array()['reason_code'] ?? $value, 10, 2 ); add_filter( 'sift_for_woocommerce_ppcp-gateway_paypal_payer_id', fn( $value, $ppcp_data ) => $ppcp_data['order']?->payer()?->payer_id() ?? $value, 10, 2 ); add_filter( 'sift_for_woocommerce_ppcp-gateway_paypal_payer_email', fn( $value, $ppcp_data ) => $ppcp_data['order']?->payer()?->email_address() ?? $value, 10, 2 ); -add_filter( 'sift_for_woocommerce_ppcp-gateway_paypal_protection_eligibility', fn( $value, $ppcp_data ) => $ppcp_data['purchase-unit']?->payments()?->captures()[0]->seller_protection() ?? $value, 10, 2 ); -add_filter( 'sift_for_woocommerce_ppcp-gateway_paypal_payment_status', fn( $value, $ppcp_data ) => $ppcp_data['purchase-unit']?->payments()?->captures()[0]->status()->name() ?? $value, 10, 2 ); +add_filter( 'sift_for_woocommerce_ppcp-gateway_paypal_protection_eligibility', fn( $value, $ppcp_data ) => $ppcp_data['order']?->purchase_units()[0]?->payments()?->captures()[0]?->seller_protection() ?? $value, 10, 2 ); +add_filter( 'sift_for_woocommerce_ppcp-gateway_paypal_payment_status', fn( $value, $ppcp_data ) => $ppcp_data['order']?->purchase_units()[0]?->payments()?->captures()[0]->status()->name() ?? $value, 10, 2 ); From 9230b1a653d4aefadd3b9b5462f4f5e57b0654de Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Thu, 5 Dec 2024 16:16:18 -0800 Subject: [PATCH 27/35] Get name from objects --- src/inc/payment-gateways/ppcp-gateway.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/inc/payment-gateways/ppcp-gateway.php b/src/inc/payment-gateways/ppcp-gateway.php index 5dbe31c..01c19f5 100644 --- a/src/inc/payment-gateways/ppcp-gateway.php +++ b/src/inc/payment-gateways/ppcp-gateway.php @@ -46,11 +46,11 @@ function get_from_order( $value, \WC_Order $order ) { add_filter( 'sift_for_woocommerce_ppcp-gateway_card_last4', fn( $value, $ppcp_data ) => $ppcp_data['wc_order']?->get_meta_data( PayPalGateway::FRAUD_RESULT_META_KEY )['card_last_digits'] ?? $value, 10, 2 ); add_filter( 'sift_for_woocommerce_ppcp-gateway_avs_result_code', fn( $value, $ppcp_data ) => $ppcp_data['order']?->purchase_units()[0]?->payments()?->authorizations()[0]?->fraud_processor_response()->avs_code() ?? $value, 10, 2 ); add_filter( 'sift_for_woocommerce_ppcp-gateway_cvv_result_code', fn( $value, $ppcp_data ) => $ppcp_data['order']?->purchase_units()[0]?->payments()?->authorizations()[0]?->fraud_processor_response()->cvv_code() ?? $value, 10, 2 ); -add_filter( 'sift_for_woocommerce_ppcp-gateway_verification_status', fn( $value, $ppcp_data ) => $ppcp_data['order']?->purchase_units()[0]?->payments()?->authorizations()[0]?->status() ?? $value, 10, 2 ); +add_filter( 'sift_for_woocommerce_ppcp-gateway_verification_status', fn( $value, $ppcp_data ) => $ppcp_data['order']?->purchase_units()[0]?->payments()?->authorizations()[0]?->status()->name() ?? $value, 10, 2 ); add_filter( 'sift_for_woocommerce_ppcp-gateway_decline_reason_code', fn( $value, $ppcp_data ) => $ppcp_data['order']?->purchase_units()[0]?->payments()?->authorizations()[0]?->to_array()['reason_code'] ?? $value, 10, 2 ); add_filter( 'sift_for_woocommerce_ppcp-gateway_paypal_payer_id', fn( $value, $ppcp_data ) => $ppcp_data['order']?->payer()?->payer_id() ?? $value, 10, 2 ); add_filter( 'sift_for_woocommerce_ppcp-gateway_paypal_payer_email', fn( $value, $ppcp_data ) => $ppcp_data['order']?->payer()?->email_address() ?? $value, 10, 2 ); -add_filter( 'sift_for_woocommerce_ppcp-gateway_paypal_protection_eligibility', fn( $value, $ppcp_data ) => $ppcp_data['order']?->purchase_units()[0]?->payments()?->captures()[0]?->seller_protection() ?? $value, 10, 2 ); +add_filter( 'sift_for_woocommerce_ppcp-gateway_paypal_protection_eligibility', fn( $value, $ppcp_data ) => $ppcp_data['order']?->purchase_units()[0]?->payments()?->captures()[0]?->seller_protection()->name() ?? $value, 10, 2 ); add_filter( 'sift_for_woocommerce_ppcp-gateway_paypal_payment_status', fn( $value, $ppcp_data ) => $ppcp_data['order']?->purchase_units()[0]?->payments()?->captures()[0]->status()->name() ?? $value, 10, 2 ); From ad62efc472f043cb22c5feb6cbf37255ff95c3e9 Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Thu, 5 Dec 2024 16:17:53 -0800 Subject: [PATCH 28/35] Fix typo --- src/inc/payment-gateways/ppcp-gateway.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/inc/payment-gateways/ppcp-gateway.php b/src/inc/payment-gateways/ppcp-gateway.php index 01c19f5..f3423f4 100644 --- a/src/inc/payment-gateways/ppcp-gateway.php +++ b/src/inc/payment-gateways/ppcp-gateway.php @@ -52,5 +52,5 @@ function get_from_order( $value, \WC_Order $order ) { add_filter( 'sift_for_woocommerce_ppcp-gateway_paypal_payer_id', fn( $value, $ppcp_data ) => $ppcp_data['order']?->payer()?->payer_id() ?? $value, 10, 2 ); add_filter( 'sift_for_woocommerce_ppcp-gateway_paypal_payer_email', fn( $value, $ppcp_data ) => $ppcp_data['order']?->payer()?->email_address() ?? $value, 10, 2 ); -add_filter( 'sift_for_woocommerce_ppcp-gateway_paypal_protection_eligibility', fn( $value, $ppcp_data ) => $ppcp_data['order']?->purchase_units()[0]?->payments()?->captures()[0]?->seller_protection()->name() ?? $value, 10, 2 ); +add_filter( 'sift_for_woocommerce_ppcp-gateway_paypal_protection_eligibility', fn( $value, $ppcp_data ) => $ppcp_data['order']?->purchase_units()[0]?->payments()?->captures()[0]?->seller_protection() ?? $value, 10, 2 ); add_filter( 'sift_for_woocommerce_ppcp-gateway_paypal_payment_status', fn( $value, $ppcp_data ) => $ppcp_data['order']?->purchase_units()[0]?->payments()?->captures()[0]->status()->name() ?? $value, 10, 2 ); From 9a8843d87c7003710e62c55866a1f63a1b45cb69 Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Thu, 5 Dec 2024 16:21:26 -0800 Subject: [PATCH 29/35] Use correct property from object --- src/inc/payment-gateways/ppcp-gateway.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/inc/payment-gateways/ppcp-gateway.php b/src/inc/payment-gateways/ppcp-gateway.php index f3423f4..67d6a5f 100644 --- a/src/inc/payment-gateways/ppcp-gateway.php +++ b/src/inc/payment-gateways/ppcp-gateway.php @@ -52,5 +52,5 @@ function get_from_order( $value, \WC_Order $order ) { add_filter( 'sift_for_woocommerce_ppcp-gateway_paypal_payer_id', fn( $value, $ppcp_data ) => $ppcp_data['order']?->payer()?->payer_id() ?? $value, 10, 2 ); add_filter( 'sift_for_woocommerce_ppcp-gateway_paypal_payer_email', fn( $value, $ppcp_data ) => $ppcp_data['order']?->payer()?->email_address() ?? $value, 10, 2 ); -add_filter( 'sift_for_woocommerce_ppcp-gateway_paypal_protection_eligibility', fn( $value, $ppcp_data ) => $ppcp_data['order']?->purchase_units()[0]?->payments()?->captures()[0]?->seller_protection() ?? $value, 10, 2 ); +add_filter( 'sift_for_woocommerce_ppcp-gateway_paypal_protection_eligibility', fn( $value, $ppcp_data ) => $ppcp_data['order']?->purchase_units()[0]?->payments()?->captures()[0]?->seller_protection()?->status ?? $value, 10, 2 ); add_filter( 'sift_for_woocommerce_ppcp-gateway_paypal_payment_status', fn( $value, $ppcp_data ) => $ppcp_data['order']?->purchase_units()[0]?->payments()?->captures()[0]->status()->name() ?? $value, 10, 2 ); From 0c51c2e64ec650e67dace8c95d1f6fc95ad0fbd1 Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Fri, 6 Dec 2024 12:12:09 -0800 Subject: [PATCH 30/35] Remove use of session unique id for user_id --- src/inc/sift-events/sift-events.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/inc/sift-events/sift-events.php b/src/inc/sift-events/sift-events.php index 21a7505..68ddb09 100644 --- a/src/inc/sift-events/sift-events.php +++ b/src/inc/sift-events/sift-events.php @@ -574,12 +574,12 @@ public static function update_or_create_order( string $order_id, \WC_Order $orde $is_admin = 1 === $user_id; // Figure out if it should use the session ID if no logged-in user exists. - if ( ! $user_id || $is_admin ) { - $user_id = $order->get_user_id() ?? null; // Use order user ID if it isn't available otherwise + if ( ! $user_id && $is_system ) { + $user_id = $order->get_user_id() ?? null; // Use order user ID if is a system update } - if ( ! $user_id ) { - $user_id = \WC()->session->get_customer_unique_id(); + if ( ! $user_id || $is_admin ) { + $user_id = $order->get_user_id() ?? null; // Use order user ID if it isn't available otherwise } $user = $user_id ? get_userdata( $user_id ) : null; From 819296362f1d9e6c8574849d324564d70b2ec292 Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Fri, 6 Dec 2024 13:13:35 -0800 Subject: [PATCH 31/35] Add chargeback event to PPCP --- src/inc/payment-gateways/ppcp-gateway.php | 72 +++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/src/inc/payment-gateways/ppcp-gateway.php b/src/inc/payment-gateways/ppcp-gateway.php index 67d6a5f..641a25b 100644 --- a/src/inc/payment-gateways/ppcp-gateway.php +++ b/src/inc/payment-gateways/ppcp-gateway.php @@ -4,9 +4,23 @@ use WooCommerce\PayPalCommerce\PPCP; use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; +use Sift_For_WooCommerce\Sift_Events\Events; add_filter( 'sift_for_woocommerce_ppcp-gateway_payment_gateway_string', fn() => '$paypal' ); +add_action( + 'woocommerce_payments_before_webhook_delivery', + function ( $event_type, $event_body ) { + // Using a switch case since we'll likely handle more future event types + switch ( $event_type ) { + case 'CUSTOMER.DISPUTE.CREATED': + send_chargeback_to_sift( $event_body ); + break; + } + }, + 10, + 2 +); /** * Get relevant information from the order. * @@ -54,3 +68,61 @@ function get_from_order( $value, \WC_Order $order ) { add_filter( 'sift_for_woocommerce_ppcp-gateway_paypal_protection_eligibility', fn( $value, $ppcp_data ) => $ppcp_data['order']?->purchase_units()[0]?->payments()?->captures()[0]?->seller_protection()?->status ?? $value, 10, 2 ); add_filter( 'sift_for_woocommerce_ppcp-gateway_paypal_payment_status', fn( $value, $ppcp_data ) => $ppcp_data['order']?->purchase_units()[0]?->payments()?->captures()[0]->status()->name() ?? $value, 10, 2 ); + +/** + * Send a chargeback event to Sift. + * + * @param object $event The Stripe event object. + * + * @return void + */ +function send_chargeback_to_sift( $event ): void { + $order_id = $event['data']['object']['resource']['disputed_transactions'][0]['seller_transaction_id']; + // Log the resolved order ID. + if ( ! $order_id ) { + wc_get_logger()->error( 'Order ID not found in event.' ); + return; + } + $order = wc_get_order( $order_id ); + + if ( ! $order instanceof \WC_Order ) { + wc_get_logger()->error( 'WooCommerce order not found for Order ID: ' . esc_html( $order_id ) ); + return; + } + + $chargeback_reason = convert_dispute_reason_to_sift_chargeback_reason( $event['data']['object']['resource']['reason'] ); + + Events::chargeback( $order_id, $order, $chargeback_reason ); +} + +/** + * Convert a dispute reason from a string that PayPal would use to a string that Sift would use. + * + * @param string $dispute_reason A dispute reason string that PayPal would use. + * + * @return string|null A dispute reason string that Sift would use. + */ +function convert_dispute_reason_to_sift_chargeback_reason( string $dispute_reason ): ?string { + switch ( $dispute_reason ) { + case 'MERCHANDISE_OR_SERVICE_NOT_RECEIVED': + return '$product_not_received'; + case 'MERCHANDISE_OR_SERVICE_NOT_AS_DESCRIBED': + return '$product_unacceptable'; + case 'UNAUTHORIZED': + return '$authorization'; + case 'PROBLEM_WITH_REMITTANCE': + return '$processing_errors'; + case 'DUPLICATE_TRANSACTION': + return '$duplicate'; + case 'INCORRECT_AMOUNT': + case 'CREDIT_NOT_PROCESSED': + case 'PAYMENT_BY_OTHER_MEANS': + return '$customer_disputes'; + case 'CANCELED_RECURRING_BILLING': + return '$cancel_subscription'; + case 'OTHER': + return '$other'; + default: + return null; + } +} From 4d896956f7f2c760cac212d237bde4941d9031b1 Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Fri, 6 Dec 2024 13:17:37 -0800 Subject: [PATCH 32/35] Remove unused variable --- src/inc/payment-gateways/woocommerce-payments.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/inc/payment-gateways/woocommerce-payments.php b/src/inc/payment-gateways/woocommerce-payments.php index 6efa0ec..836e9f8 100644 --- a/src/inc/payment-gateways/woocommerce-payments.php +++ b/src/inc/payment-gateways/woocommerce-payments.php @@ -32,7 +32,7 @@ function ( $value, \WC_Order $order ) { $api_client = \WC_Payments::get_payments_api_client(); $charge = $api_client->get_charge( $charge_id ); return $charge['payment_method_details']; - } catch ( \Exception $e ) { + } catch ( \Exception ) { return $value; } }, @@ -50,7 +50,7 @@ function ( $value, \WC_Order $order ) { } $api_client = \WC_Payments::get_payments_api_client(); return $api_client->get_charge( $charge_id ); - } catch ( \Exception $e ) { + } catch ( \Exception ) { return $value; } }, From e95aebb8d9e32ad20fbeade3b88c47951149d119 Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Fri, 6 Dec 2024 13:21:32 -0800 Subject: [PATCH 33/35] Prevent errors --- src/inc/payment-gateways/ppcp-gateway.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/inc/payment-gateways/ppcp-gateway.php b/src/inc/payment-gateways/ppcp-gateway.php index 641a25b..528c762 100644 --- a/src/inc/payment-gateways/ppcp-gateway.php +++ b/src/inc/payment-gateways/ppcp-gateway.php @@ -77,7 +77,7 @@ function get_from_order( $value, \WC_Order $order ) { * @return void */ function send_chargeback_to_sift( $event ): void { - $order_id = $event['data']['object']['resource']['disputed_transactions'][0]['seller_transaction_id']; + $order_id = $event['data']['object']['resource']['disputed_transactions'][0]['seller_transaction_id'] ?? null; // Log the resolved order ID. if ( ! $order_id ) { wc_get_logger()->error( 'Order ID not found in event.' ); @@ -90,7 +90,7 @@ function send_chargeback_to_sift( $event ): void { return; } - $chargeback_reason = convert_dispute_reason_to_sift_chargeback_reason( $event['data']['object']['resource']['reason'] ); + $chargeback_reason = convert_dispute_reason_to_sift_chargeback_reason( $event['data']['object']['resource']['reason'] ?? '' ); Events::chargeback( $order_id, $order, $chargeback_reason ); } From f375dd63a8fabd86d9d9ba3b0e9101f42c44c0a0 Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Mon, 9 Dec 2024 12:53:57 -0800 Subject: [PATCH 34/35] Remove action for creating chargeback with ppcp gateway and address feedback --- src/inc/payment-gateways/ppcp-gateway.php | 13 ------------- src/inc/sift-events/sift-events.php | 13 +++---------- 2 files changed, 3 insertions(+), 23 deletions(-) diff --git a/src/inc/payment-gateways/ppcp-gateway.php b/src/inc/payment-gateways/ppcp-gateway.php index 528c762..1ebad76 100644 --- a/src/inc/payment-gateways/ppcp-gateway.php +++ b/src/inc/payment-gateways/ppcp-gateway.php @@ -8,19 +8,6 @@ add_filter( 'sift_for_woocommerce_ppcp-gateway_payment_gateway_string', fn() => '$paypal' ); -add_action( - 'woocommerce_payments_before_webhook_delivery', - function ( $event_type, $event_body ) { - // Using a switch case since we'll likely handle more future event types - switch ( $event_type ) { - case 'CUSTOMER.DISPUTE.CREATED': - send_chargeback_to_sift( $event_body ); - break; - } - }, - 10, - 2 -); /** * Get relevant information from the order. * diff --git a/src/inc/sift-events/sift-events.php b/src/inc/sift-events/sift-events.php index 68ddb09..53eb24f 100644 --- a/src/inc/sift-events/sift-events.php +++ b/src/inc/sift-events/sift-events.php @@ -569,21 +569,14 @@ public static function update_or_create_order( string $order_id, \WC_Order $orde } // Determine user and session context. - $user_id = get_current_user_id() ?? wp_get_current_user()->ID ?? null; // Check first for logged-in user. - $is_system = ! $create_order && str_starts_with( sanitize_title( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ?? '' ) ), 'WordPress' ); // Check if this is an order update via system action. + $user_id = wp_get_current_user()->ID ?? null; // Check first for logged-in user. $is_admin = 1 === $user_id; // Figure out if it should use the session ID if no logged-in user exists. - if ( ! $user_id && $is_system ) { - $user_id = $order->get_user_id() ?? null; // Use order user ID if is a system update - } - if ( ! $user_id || $is_admin ) { $user_id = $order->get_user_id() ?? null; // Use order user ID if it isn't available otherwise } - $user = $user_id ? get_userdata( $user_id ) : null; - $physical_or_electronic = '$electronic'; $items = array(); foreach ( $order->get_items( 'line_item' ) as $item ) { @@ -637,8 +630,8 @@ public static function update_or_create_order( string $order_id, \WC_Order $orde // Add the user_id only if a user exists, otherwise, let it remain empty. // Ref: https://developers.sift.com/docs/php/apis-overview/core-topics/faq/tracking-users - if ( $user ) { - $properties['$user_id'] = self::format_user_id( $user->ID ); + if ( $user_id && ! $is_admin ) { + $properties['$user_id'] = self::format_user_id( $user_id ); } // Add in the address information if it's available. From a4edc85b82d96619fac7e6dab5fd01e9152096f4 Mon Sep 17 00:00:00 2001 From: Chris McCluskey Date: Mon, 9 Dec 2024 13:01:20 -0800 Subject: [PATCH 35/35] Delint --- src/inc/sift-events/sift-events.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/inc/sift-events/sift-events.php b/src/inc/sift-events/sift-events.php index 53eb24f..c86b59c 100644 --- a/src/inc/sift-events/sift-events.php +++ b/src/inc/sift-events/sift-events.php @@ -569,8 +569,8 @@ public static function update_or_create_order( string $order_id, \WC_Order $orde } // Determine user and session context. - $user_id = wp_get_current_user()->ID ?? null; // Check first for logged-in user. - $is_admin = 1 === $user_id; + $user_id = wp_get_current_user()->ID ?? null; // Check first for logged-in user. + $is_admin = 1 === $user_id; // Figure out if it should use the session ID if no logged-in user exists. if ( ! $user_id || $is_admin ) {