Skip to content

Commit e2d0726

Browse files
committed
Address PR review comments on decline message handling and fix unit tests
1 parent 151a2ff commit e2d0726

6 files changed

Lines changed: 52 additions & 34 deletions

File tree

modules/ppcp-api-client/src/Endpoint/OrderEndpoint.php

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -349,12 +349,8 @@ public function capture( Order $order ): Order {
349349
$capture_status = $first_capture ? $first_capture->status() : null;
350350
if ( $capture_status && $capture_status->is( CaptureStatus::DECLINED ) ) {
351351
$fraud = $first_capture->fraud_processor_response();
352-
$decline_message = ( $fraud && $fraud->response_code() )
353-
? sprintf(
354-
/* translators: %s - processor response code and description */
355-
__( 'Payment declined by card processor: %s. Please use a different payment method or contact your bank.', 'woocommerce-paypal-payments' ),
356-
$fraud->get_response_code_message()
357-
)
352+
$decline_message = $fraud
353+
? $fraud->get_customer_decline_message()
358354
: __( 'Payment provider declined the payment, please use a different payment method.', 'woocommerce-paypal-payments' );
359355
throw new RuntimeException( $decline_message );
360356
}

modules/ppcp-api-client/src/Entity/FraudProcessorResponse.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,23 @@ public function get_cvv2_code_message(): string {
175175
return $messages[ $this->cvv_code() ] ?? sprintf( '%s: Error', $this->cvv_code() );
176176
}
177177

178+
/**
179+
* Returns the customer-facing decline message, including the processor response code when available.
180+
*
181+
* @return string
182+
*/
183+
public function get_customer_decline_message(): string {
184+
if ( $this->response_code() ) {
185+
return sprintf(
186+
/* translators: %s - processor response code and description */
187+
__( 'Payment declined by card processor: %s. Please use a different payment method or contact your bank.', 'woocommerce-paypal-payments' ),
188+
$this->get_response_code_message()
189+
);
190+
}
191+
192+
return __( 'Payment provider declined the payment, please use a different payment method.', 'woocommerce-paypal-payments' );
193+
}
194+
178195
/**
179196
* Returns the human-readable description for the processor response code.
180197
*

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

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -87,26 +87,17 @@ protected function handle_capture_status(
8787
// It is checked in the capture endpoint already, but there are other ways to capture,
8888
// such as when paid via saved card.
8989
case CaptureStatus::DECLINED:
90-
$fraud = $capture->fraud_processor_response();
91-
if ( $fraud && $fraud->response_code() ) {
92-
$wc_order->add_order_note(
93-
sprintf(
94-
/* translators: %s - processor response code and description */
95-
__( 'PayPal payment declined. Processor response: %s', 'woocommerce-paypal-payments' ),
96-
$fraud->get_response_code_message()
97-
)
98-
);
99-
}
100-
$wc_order->update_status(
101-
'failed',
102-
__( 'Could not capture the payment.', 'woocommerce-paypal-payments' )
103-
);
104-
$decline_message = ( $fraud && $fraud->response_code() )
90+
$fraud = $capture->fraud_processor_response();
91+
$status_note = ( $fraud && $fraud->response_code() )
10592
? sprintf(
10693
/* translators: %s - processor response code and description */
107-
__( 'Payment declined by card processor: %s. Please use a different payment method or contact your bank.', 'woocommerce-paypal-payments' ),
94+
__( 'Could not capture the payment. Processor response: %s', 'woocommerce-paypal-payments' ),
10895
$fraud->get_response_code_message()
10996
)
97+
: __( 'Could not capture the payment.', 'woocommerce-paypal-payments' );
98+
$wc_order->update_status( 'failed', $status_note );
99+
$decline_message = $fraud
100+
? $fraud->get_customer_decline_message()
110101
: __( 'Payment provider declined the payment, please use a different payment method.', 'woocommerce-paypal-payments' );
111102
throw new RuntimeException( $decline_message );
112103
case CaptureStatus::PENDING:

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

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
use WooCommerce\PayPalCommerce\AdminNotices\Repository\Repository;
1818
use WooCommerce\PayPalCommerce\ApiClient\Entity\Authorization;
1919
use WooCommerce\PayPalCommerce\ApiClient\Entity\Capture;
20-
use WooCommerce\PayPalCommerce\ApiClient\Entity\FraudProcessorResponse;
2120
use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus;
2221
use WooCommerce\PayPalCommerce\ApiClient\Helper\ReferenceTransactionStatus;
2322
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
@@ -169,7 +168,7 @@ function ( int $order_id ) use ( $fees_renderer ) {
169168

170169
add_action(
171170
'woocommerce_admin_order_totals_after_total',
172-
function ( int $order_id ) {
171+
function ( int $order_id ) use ( $c ) {
173172
$wc_order = wc_get_order( $order_id );
174173
if ( ! $wc_order instanceof WC_Order ) {
175174
return;
@@ -178,11 +177,8 @@ function ( int $order_id ) {
178177
if ( empty( $fraud_result['response_code'] ) ) {
179178
return;
180179
}
181-
$fraud = new FraudProcessorResponse(
182-
$fraud_result['avs_code'] ?? null,
183-
$fraud_result['cvv2_code'] ?? null,
184-
$fraud_result['response_code']
185-
);
180+
$fraud = $c->get( 'api.factory.fraud-processor-response' )
181+
->from_paypal_response( (object) $fraud_result );
186182
printf(
187183
'<tr><td class="label">%s:</td><td width="1%%"></td><td class="total">%s</td></tr>',
188184
esc_html__( 'Processor Response', 'woocommerce-paypal-payments' ),

tests/PHPUnit/ApiClient/Entity/FraudProcessorResponseTest.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,22 @@ public function testGetResponseCodeMessageForEmptyCodeReturnsEmptyString(): void
6767
$testee = new FraudProcessorResponse(null, null, null);
6868
$this->assertSame('', $testee->get_response_code_message());
6969
}
70+
71+
public function testGetCustomerDeclineMessageWithKnownCode(): void
72+
{
73+
$testee = new FraudProcessorResponse(null, null, '9500');
74+
$this->assertSame(
75+
'Payment declined by card processor: 9500: Suspected Fraud. Please use a different payment method or contact your bank.',
76+
$testee->get_customer_decline_message()
77+
);
78+
}
79+
80+
public function testGetCustomerDeclineMessageWithEmptyCodeReturnsGenericMessage(): void
81+
{
82+
$testee = new FraudProcessorResponse(null, null, null);
83+
$this->assertSame(
84+
'Payment provider declined the payment, please use a different payment method.',
85+
$testee->get_customer_decline_message()
86+
);
87+
}
7088
}

tests/PHPUnit/WcGateway/Processor/AuthorizedPaymentsProcessorTest.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ private function createAuthorization(string $id, string $status): Authorization
260260
return new Authorization($id, new AuthorizationStatus($status), null);
261261
}
262262

263-
public function testCaptureAuthorizedPaymentDeclinedWithFraudResponseCodeAddsOrderNoteAndThrows(): void
263+
public function testCaptureAuthorizedPaymentDeclinedWithFraudResponseCodePassesCodeToStatusNote(): void
264264
{
265265
$this->orderEndpoint->shouldReceive('order')->andReturn($this->paypalOrder);
266266

@@ -275,13 +275,13 @@ public function testCaptureAuthorizedPaymentDeclinedWithFraudResponseCodeAddsOrd
275275
->with($this->authorizationId, equalTo(new Money($this->amount, $this->currency)))
276276
->andReturn($capture);
277277

278-
$this->wcOrder->shouldReceive('update_status');
279278
$this->wcOrder
280-
->shouldReceive('add_order_note')
279+
->shouldReceive('update_status')
281280
->once()
282-
->with(Mockery::on(function (string $note): bool {
281+
->with('failed', Mockery::on(function (string $note): bool {
283282
return strpos($note, '9500: Suspected Fraud') !== false;
284283
}));
284+
$this->wcOrder->shouldNotReceive('add_order_note');
285285

286286
$this->expectException(RuntimeException::class);
287287
$this->expectExceptionMessageMatches('/9500: Suspected Fraud/');
@@ -302,7 +302,7 @@ public function testCaptureAuthorizedPaymentDeclinedWithoutFraudCodeThrowsGeneri
302302
->with($this->authorizationId, equalTo(new Money($this->amount, $this->currency)))
303303
->andReturn($capture);
304304

305-
$this->wcOrder->shouldReceive('update_status');
305+
$this->wcOrder->shouldReceive('update_status')->with('failed', 'Could not capture the payment.');
306306
$this->wcOrder->shouldNotReceive('add_order_note');
307307

308308
$this->expectException(RuntimeException::class);

0 commit comments

Comments
 (0)