Skip to content

Commit 7ca47c2

Browse files
committed
Enhance fraud protection reporting with event source tracking
This update modifies the `wc_fraud_protection_report` function and the `fraud_protection_report` method in the `OrderEventsTracker` class to include a new parameter for the event source, utilizing constants from the `ApiClient`. Additionally, the implementation now validates the source against predefined constants, logging warnings for invalid sources. Unit tests have been updated to reflect these changes, ensuring robust coverage for the new functionality.
1 parent 89d1ff4 commit 7ca47c2

File tree

4 files changed

+64
-11
lines changed

4 files changed

+64
-11
lines changed

src/ApiClient.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,32 @@ class ApiClient {
9595
self::REPORT_STATUS_BAD,
9696
);
9797

98+
/**
99+
* Report source: chargeback event.
100+
*/
101+
public const REPORT_SOURCE_CHARGEBACK = 'chargeback';
102+
103+
/**
104+
* Report source: manual review outcome.
105+
*/
106+
public const REPORT_SOURCE_MANUAL_REVIEW = 'manual_review';
107+
108+
/**
109+
* Report source: API-driven event.
110+
*/
111+
public const REPORT_SOURCE_API = 'api';
112+
113+
/**
114+
* Valid report source values.
115+
*
116+
* @var array<string>
117+
*/
118+
public const VALID_REPORT_SOURCES = array(
119+
self::REPORT_SOURCE_CHARGEBACK,
120+
self::REPORT_SOURCE_MANUAL_REVIEW,
121+
self::REPORT_SOURCE_API,
122+
);
123+
98124
/**
99125
* Verify a session with the Blackbox API and get a fraud decision.
100126
*

src/OrderEventsTracker.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,20 @@ public function register(): void {}
5353
*
5454
* @internal
5555
* @param \WC_Order $order The order to report on.
56+
* @param string $source The source of the event. Use ApiClient::REPORT_SOURCE_* constants.
5657
* @param string $status The status of the event. Use ApiClient::REPORT_STATUS_GOOD or ApiClient::REPORT_STATUS_BAD.
5758
* @param string $notes The notes of the event.
5859
*/
59-
public function fraud_protection_report( \WC_Order $order, string $status, string $notes ): void {
60+
public function fraud_protection_report( \WC_Order $order, string $source, string $status, string $notes ): void {
6061
try {
62+
if ( ! in_array( $source, ApiClient::VALID_REPORT_SOURCES, true ) ) {
63+
FraudProtectionController::log(
64+
'warning',
65+
sprintf( 'Invalid report source "%s", skipping report.', $source )
66+
);
67+
return;
68+
}
69+
6170
if ( ! in_array( $status, ApiClient::VALID_REPORT_STATUSES, true ) ) {
6271
FraudProtectionController::log(
6372
'warning',
@@ -79,7 +88,7 @@ public function fraud_protection_report( \WC_Order $order, string $status, strin
7988
$session_id,
8089
array(
8190
'label' => $status,
82-
'source' => 'payment_gateway_event',
91+
'source' => $source,
8392
'notes' => sanitize_text_field( $notes ),
8493
)
8594
);

tests/php/src/OrderEventsTrackerTest.php

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,12 @@ public function test_fraud_protection_report_reports_when_session_id_exists(): v
6969
'bb-session-123',
7070
array(
7171
'label' => 'bad',
72-
'source' => 'payment_gateway_event',
72+
'source' => ApiClient::REPORT_SOURCE_API,
7373
'notes' => 'Payment failed via Stripe.',
7474
)
7575
);
7676

77-
$this->sut->fraud_protection_report( $order, 'bad', 'Payment failed via Stripe.' );
77+
$this->sut->fraud_protection_report( $order, ApiClient::REPORT_SOURCE_API, 'bad', 'Payment failed via Stripe.' );
7878
}
7979

8080
/**
@@ -92,12 +92,12 @@ public function test_fraud_protection_report_reports_good_status(): void {
9292
'bb-session-456',
9393
array(
9494
'label' => 'good',
95-
'source' => 'payment_gateway_event',
95+
'source' => ApiClient::REPORT_SOURCE_API,
9696
'notes' => 'Payment completed successfully.',
9797
)
9898
);
9999

100-
$this->sut->fraud_protection_report( $order, 'good', 'Payment completed successfully.' );
100+
$this->sut->fraud_protection_report( $order, ApiClient::REPORT_SOURCE_API, 'good', 'Payment completed successfully.' );
101101
}
102102

103103
/**
@@ -110,7 +110,7 @@ public function test_fraud_protection_report_skips_when_no_session_id(): void {
110110
->expects( $this->never() )
111111
->method( 'report' );
112112

113-
$this->sut->fraud_protection_report( $order, 'bad', 'Some notes.' );
113+
$this->sut->fraud_protection_report( $order, ApiClient::REPORT_SOURCE_API, 'bad', 'Some notes.' );
114114
}
115115

116116
/**
@@ -125,11 +125,28 @@ public function test_fraud_protection_report_skips_when_invalid_status(): void {
125125
->expects( $this->never() )
126126
->method( 'report' );
127127

128-
$this->sut->fraud_protection_report( $order, 'invalid_status', 'Some notes.' );
128+
$this->sut->fraud_protection_report( $order, ApiClient::REPORT_SOURCE_API, 'invalid_status', 'Some notes.' );
129129

130130
$this->assertLogged( 'warning', 'Invalid report status "invalid_status", skipping report.' );
131131
}
132132

133+
/**
134+
* @testdox fraud_protection_report() skips reporting and logs warning when source is invalid.
135+
*/
136+
public function test_fraud_protection_report_skips_when_invalid_source(): void {
137+
$order = \WC_Helper_Order::create_order();
138+
$order->update_meta_data( SessionVerifier::ORDER_BLACKBOX_SESSION_ID_KEY, 'bb-session-123' );
139+
$order->save_meta_data();
140+
141+
$this->api_client
142+
->expects( $this->never() )
143+
->method( 'report' );
144+
145+
$this->sut->fraud_protection_report( $order, 'invalid_source', 'bad', 'Some notes.' );
146+
147+
$this->assertLogged( 'warning', 'Invalid report source "invalid_source", skipping report.' );
148+
}
149+
133150
/**
134151
* @testdox fraud_protection_report() catches exceptions and logs error.
135152
*/
@@ -142,7 +159,7 @@ public function test_fraud_protection_report_catches_exceptions(): void {
142159
->method( 'report' )
143160
->willThrowException( new \RuntimeException( 'API connection failed' ) );
144161

145-
$this->sut->fraud_protection_report( $order, 'bad', 'Payment failed.' );
162+
$this->sut->fraud_protection_report( $order, ApiClient::REPORT_SOURCE_API, 'bad', 'Payment failed.' );
146163

147164
$this->assertLogged( 'error', 'Failed to report 3rd party event to Blackbox API: API connection failed' );
148165
}

woocommerce-fraud-protection.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,13 +142,14 @@ function () {
142142
* (i.e. after `woocommerce_store_api_checkout_order_processed`).
143143
*
144144
* @param \WC_Order $order The order to report on.
145+
* @param string $source The source of the event. Use ApiClient::REPORT_SOURCE_* constants.
145146
* @param string $status The status of the event. Use ApiClient::REPORT_STATUS_GOOD or ApiClient::REPORT_STATUS_BAD.
146147
* @param string $notes Free-form notes describing the event.
147148
*/
148-
function wc_fraud_protection_report( \WC_Order $order, string $status, string $notes ): void {
149+
function wc_fraud_protection_report( \WC_Order $order, string $source, string $status, string $notes ): void {
149150
$api_client = new \Automattic\WooCommerce\FraudProtection\ApiClient();
150151

151152
$order_events_tracker = new \Automattic\WooCommerce\FraudProtection\OrderEventsTracker();
152153
$order_events_tracker->init( $api_client );
153-
$order_events_tracker->fraud_protection_report( $order, $status, $notes );
154+
$order_events_tracker->fraud_protection_report( $order, $source, $status, $notes );
154155
}

0 commit comments

Comments
 (0)