woocommerce-paypal-payments/modules/ppcp-button/src/Helper/ThreeDSecure.php

160 lines
4.6 KiB
PHP
Raw Normal View History

2020-07-15 10:27:40 +03:00
<?php
2020-08-31 11:12:46 +03:00
/**
* Helper class to determine how to proceed with an order depending on the 3d secure feedback.
*
2020-09-11 14:11:10 +03:00
* @package WooCommerce\PayPalCommerce\Button\Helper
2020-08-31 11:12:46 +03:00
*/
2020-07-15 10:27:40 +03:00
declare(strict_types=1);
2020-09-11 14:11:10 +03:00
namespace WooCommerce\PayPalCommerce\Button\Helper;
2020-07-15 10:27:40 +03:00
2021-09-21 11:34:16 +02:00
use Psr\Log\LoggerInterface;
2020-09-11 14:11:10 +03:00
use WooCommerce\PayPalCommerce\ApiClient\Entity\CardAuthenticationResult as AuthResult;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
2023-11-23 14:53:47 +01:00
use WooCommerce\PayPalCommerce\ApiClient\Factory\CardAuthenticationResultFactory;
2020-07-15 10:27:40 +03:00
2020-08-31 11:12:46 +03:00
/**
* Class ThreeDSecure
*/
2020-08-27 11:08:36 +03:00
class ThreeDSecure {
2020-07-15 10:27:40 +03:00
2020-09-11 13:38:02 +03:00
const NO_DECISION = 0;
2025-03-24 14:09:19 +01:00
const PROCEED = 1;
2020-09-11 13:38:02 +03:00
const REJECT = 2;
const RETRY = 3;
2020-07-15 10:27:40 +03:00
2023-11-23 14:53:47 +01:00
/**
* Card authentication result factory.
*
* @var CardAuthenticationResultFactory
*/
private $card_authentication_result_factory;
2021-09-21 11:34:16 +02:00
/**
* The logger.
*
* @var LoggerInterface
*/
protected $logger;
/**
* ThreeDSecure constructor.
*
2023-11-23 14:53:47 +01:00
* @param CardAuthenticationResultFactory $card_authentication_result_factory Card authentication result factory.
* @param LoggerInterface $logger The logger.
2021-09-21 11:34:16 +02:00
*/
2023-11-23 14:53:47 +01:00
public function __construct(
CardAuthenticationResultFactory $card_authentication_result_factory,
LoggerInterface $logger
) {
$this->logger = $logger;
$this->card_authentication_result_factory = $card_authentication_result_factory;
2021-09-21 11:34:16 +02:00
}
2020-08-27 11:08:36 +03:00
/**
* Determine, how we proceed with a given order.
*
* @link https://developer.paypal.com/docs/business/checkout/add-capabilities/3d-secure/#authenticationresult
2020-08-31 11:12:46 +03:00
*
2024-03-27 11:50:40 +00:00
* @param Order $order The order for which the decision is needed.
2020-08-31 11:12:46 +03:00
*
2020-08-27 11:08:36 +03:00
* @return int
*/
2020-08-31 11:12:46 +03:00
public function proceed_with_order( Order $order ): int {
2024-03-27 11:50:40 +00:00
do_action( 'woocommerce_paypal_payments_three_d_secure_before_check', $order );
2023-10-27 15:28:01 +02:00
$payment_source = $order->payment_source();
if ( ! $payment_source ) {
2024-03-27 11:50:40 +00:00
return $this->return_decision( self::NO_DECISION, $order );
2020-08-27 11:08:36 +03:00
}
2023-10-27 15:28:01 +02:00
2024-02-22 17:59:43 +00:00
if ( ! ( $payment_source->properties()->brand ?? '' ) ) {
2024-03-27 11:50:40 +00:00
return $this->return_decision( self::NO_DECISION, $order );
2020-08-27 11:08:36 +03:00
}
2024-02-22 17:59:43 +00:00
if ( ! ( $payment_source->properties()->authentication_result ?? '' ) ) {
2024-03-27 11:50:40 +00:00
return $this->return_decision( self::NO_DECISION, $order );
2020-08-27 11:08:36 +03:00
}
2021-09-21 11:34:16 +02:00
2023-11-21 14:57:55 +01:00
$authentication_result = $payment_source->properties()->authentication_result ?? null;
if ( $authentication_result ) {
2023-11-23 14:53:47 +01:00
$result = $this->card_authentication_result_factory->from_paypal_response( $authentication_result );
2021-09-21 11:34:16 +02:00
$this->logger->info( '3DS Authentication Result: ' . wc_print_r( $result->to_array(), true ) );
2020-07-15 10:27:40 +03:00
2023-11-21 14:57:55 +01:00
if ( $result->liability_shift() === AuthResult::LIABILITY_SHIFT_POSSIBLE ) {
2025-03-24 14:09:19 +01:00
return $this->return_decision( self::PROCEED, $order );
2023-11-21 14:57:55 +01:00
}
if ( $result->liability_shift() === AuthResult::LIABILITY_SHIFT_UNKNOWN ) {
2024-03-27 11:50:40 +00:00
return $this->return_decision( self::RETRY, $order );
2023-11-21 14:57:55 +01:00
}
if ( $result->liability_shift() === AuthResult::LIABILITY_SHIFT_NO ) {
2024-03-27 11:50:40 +00:00
return $this->return_decision( $this->no_liability_shift( $result ), $order );
2023-11-21 14:57:55 +01:00
}
2020-08-27 11:08:36 +03:00
}
2023-11-21 14:57:55 +01:00
2024-03-27 11:50:40 +00:00
return $this->return_decision( self::NO_DECISION, $order );
}
/**
* Processes and returns a ThreeD secure decision.
*
* @param int $decision The ThreeD secure decision.
* @param Order $order The PayPal Order object.
* @return int
*/
public function return_decision( int $decision, Order $order ) {
$decision = apply_filters( 'woocommerce_paypal_payments_three_d_secure_decision', $decision, $order );
do_action( 'woocommerce_paypal_payments_three_d_secure_after_check', $order, $decision );
return $decision;
2020-08-27 11:08:36 +03:00
}
2020-07-15 10:27:40 +03:00
2020-08-27 11:08:36 +03:00
/**
2020-08-31 11:12:46 +03:00
* Determines how to proceed depending on the Liability Shift.
*
* @param AuthResult $result The AuthResult object based on which we make the decision.
*
2020-08-27 11:08:36 +03:00
* @return int
*/
2020-08-31 11:12:46 +03:00
private function no_liability_shift( AuthResult $result ): int {
2020-07-15 10:27:40 +03:00
2020-08-27 11:08:36 +03:00
if (
2020-09-01 09:00:45 +03:00
$result->enrollment_status() === AuthResult::ENROLLMENT_STATUS_BYPASS
&& ! $result->authentication_result()
2020-08-27 11:08:36 +03:00
) {
2025-03-24 14:09:19 +01:00
return self::PROCEED;
2020-08-27 11:08:36 +03:00
}
if (
2020-09-01 09:00:45 +03:00
$result->enrollment_status() === AuthResult::ENROLLMENT_STATUS_UNAVAILABLE
&& ! $result->authentication_result()
2020-08-27 11:08:36 +03:00
) {
2025-03-24 14:09:19 +01:00
return self::PROCEED;
2020-08-27 11:08:36 +03:00
}
if (
2020-09-01 09:00:45 +03:00
$result->enrollment_status() === AuthResult::ENROLLMENT_STATUS_NO
&& ! $result->authentication_result()
2020-08-27 11:08:36 +03:00
) {
2025-03-24 14:09:19 +01:00
return self::PROCEED;
2020-08-27 11:08:36 +03:00
}
2020-07-15 10:27:40 +03:00
2020-09-01 09:00:45 +03:00
if ( $result->authentication_result() === AuthResult::AUTHENTICATION_RESULT_REJECTED ) {
2020-08-27 11:08:36 +03:00
return self::REJECT;
}
2020-07-15 10:27:40 +03:00
2020-09-01 09:00:45 +03:00
if ( $result->authentication_result() === AuthResult::AUTHENTICATION_RESULT_NO ) {
2020-08-27 11:08:36 +03:00
return self::REJECT;
}
2020-07-15 10:27:40 +03:00
2020-09-01 09:00:45 +03:00
if ( $result->authentication_result() === AuthResult::AUTHENTICATION_RESULT_UNABLE ) {
2020-08-27 11:08:36 +03:00
return self::RETRY;
}
2020-09-01 09:00:45 +03:00
if ( ! $result->authentication_result() ) {
2020-08-27 11:08:36 +03:00
return self::RETRY;
}
return self::NO_DECISION;
}
2020-07-15 10:27:40 +03:00
}