Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add customer payment methods and PPCP chargeback reporting #25

Merged
merged 35 commits into from
Dec 10, 2024

Conversation

chrismccluskey
Copy link
Collaborator

@chrismccluskey chrismccluskey commented Dec 3, 2024

Changes proposed in this Pull Request

  • Adds customer payment methods by enumerating over a customer's order and acquiring the payment method for each.
  • Removes duplicate payment methods before sending.

Testing instructions

  • Apply this branch to an environment with multiple payment methods.
  • Update the account of a user with multiple payment methods.
  • Confirm the payment methods for $update_account is correct.
  • Try a purchase as a new user and confirm that $create_account is correct.

Mentions # 554-gh-automattic/gold

@chrismccluskey chrismccluskey marked this pull request as ready for review December 3, 2024 22:52
@chrismccluskey chrismccluskey changed the title Add customer payment methods Add customer payment methods and PPCP chargeback reporting Dec 6, 2024
@@ -565,12 +569,17 @@ 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.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_current_user_id() definition:

function get_current_user_id() {
	if ( ! function_exists( 'wp_get_current_user' ) ) {
		return 0;
	}
	$user = wp_get_current_user();
	return ( isset( $user->ID ) ? (int) $user->ID : 0 );
}


As you can see it is using wp_get_current_user internally. So I am not sure what this change adds...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if it's needed anymore. At one point this made a difference, but I think I addressed that issue in another way.

}

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;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$user here is only used later to get the $user_id again. Maybe we should not need that...
And simply do

$properties = array(
			'$user_id'         => $user_id ? self::format_user_id( $user_id ) : ''
			[ ... ]
			

What do you think?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll check and simplify if possible.

Comment on lines 577 to 582
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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have the feeling that this whole block can be made more readible... I don't understand much of the logic behind it...
If $user_id is null when getting there, getting the id from the $order should be tried, even if it is not system or admin, no?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It probably can. I didn't know the reasoning behind getting the user_id from the order only when it's a system update. I think the more simple logic is just to try to get the user_id from the order if the user_id isn't available or if it's admin (this would remove the $is_system check).


add_filter( 'sift_for_woocommerce_ppcp-gateway_payment_gateway_string', fn() => '$paypal' );

add_action(
'woocommerce_payments_before_webhook_delivery',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ppcp is using WcPay webhooks structure?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great catch! This isn't the correct filter. I went looking for one for PPCP and could not find one. We may not be able to report chargebacks from PPCP as a result.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding to this a bit, because I'm a bit surprised to see this myself. I've been trying to find some clue about where dispute webhooks would be handled with ppcp, and I'm not finding anything. Some things I thought would be related but appear not to be (unless I'm misunderstanding) are:

  1. Payment capture reversed - it sounds like chargeback, but it's something separate (PAYMENT.CAPTURE.REVERSED).
  2. Capture status reason - chargeback / buyer_complaint. This would sound like it's what we want, except that it happens during capture and not via a webhook. I think this is important because I'm thinking this happens when the customer is trying to purchase something and they already have a dispute (though I may be wrong). I would assume that the typical lifecycle of chargebacks means that the customer needs some time to determine that the charge was fraudulent, that it wouldn't happen in the same request as making the purchase, meaning it would need to come in through the webhook.

According to PayPal docs, the webhook event we want to listen to is CUSTOMER.DISPUTE.CREATED, and in the admin for this payment gateway, we can see that this event is added when the webhook is created (this gateway allows setting up webhooks from inside wp-admin with the click of a button).

What I'm hoping to find at this point is a generic way to hook into all webhook events for ppcp. I'm not finding anything yet with the search terms I would expect to see (webhook, before, dispute, etc..) It's possible that this plugin may not have implemented these webhooks yet.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possible that this plugin may not have implemented these webhooks yet.

Yes, I am not surprised.
This is why I have been talking about reusing @chrisfromthelc code here where he added an endpoint we can send the webhook to.

*
* @return void
*/
function send_chargeback_to_sift( $event ): void {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I kept these functions in case we ever get a filter to allow us to use them in the future.

Copy link

github-actions bot commented Dec 9, 2024

Code Coverage

Package Line Rate Complexity Health
inc/payment-gateways/index.php 0% 0
inc/payment-gateways/lib/stripe.php 63% 77
inc/payment-gateways/load.php 0% 0
inc/payment-gateways/ppcp-gateway.php 0% 18
inc/payment-gateways/stripe.php 23% 17
inc/payment-gateways/transact.php 100% 0
inc/payment-gateways/woocommerce-payments.php 30% 8
inc/sift-decisions/abuse-decisions.php 0% 12
inc/sift-decisions/sift-decision-rest-api-webhooks.php 0% 5
inc/sift-events/class-sift-event-types.php 100% 4
inc/sift-events/normalizers/sift-order.php 96% 6
inc/sift-events/normalizers/sift-payment-gateway.php 100% 5
inc/sift-events/normalizers/sift-payment-method.php 97% 31
inc/sift-events/normalizers/sift-payment-type.php 83% 3
inc/sift-events/normalizers/sift-property.php 100% 3
inc/sift-events/normalizers/sift-verification-status.php 50% 3
inc/sift-events/sift-events-validator.php 85% 140
inc/sift-events/sift-events.php 75% 120
inc/tracking-js.php 0% 4
inc/wc-admin-settings-tab.php 0% 24
index.php 0% 0
sift-for-woocommerce.php 14% 11
Summary 57% (1030 / 1821) 491

Copy link
Collaborator

@millerf millerf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@chrismccluskey chrismccluskey merged commit ec1cf95 into trunk Dec 10, 2024
12 checks passed
@chrismccluskey chrismccluskey deleted the add/customer-payment-methods branch December 10, 2024 18:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants