Merge branch 'trunk' into modularity-module-migration

# Conflicts:
#	modules/ppcp-wc-gateway/src/WCGatewayModule.php
This commit is contained in:
Pedro Silva 2024-04-19 11:59:28 +01:00
commit 161e933d39
No known key found for this signature in database
GPG key ID: E2EE20C0669D24B3
96 changed files with 6599 additions and 223 deletions

View file

@ -9,6 +9,7 @@ declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\ApiClient;
use WooCommerce\PayPalCommerce\ApiClient\Authentication\SdkClientToken;
use WooCommerce\PayPalCommerce\ApiClient\Authentication\UserIdToken;
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentMethodTokensEndpoint;
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokensEndpoint;
@ -1408,32 +1409,32 @@ return array(
'BE' => array(
'mastercard' => array(),
'visa' => array(),
'amex' => array( 'EUR', 'USD', 'CAD' ),
'amex' => array(),
),
'BG' => array(
'mastercard' => array(),
'visa' => array(),
'amex' => array( 'EUR' ),
'amex' => array(),
),
'CY' => array(
'mastercard' => array(),
'visa' => array(),
'amex' => array( 'EUR' ),
'amex' => array(),
),
'CZ' => array(
'mastercard' => array(),
'visa' => array(),
'amex' => array( 'CZK' ),
'amex' => array(),
),
'DE' => array(
'mastercard' => array(),
'visa' => array(),
'amex' => array( 'EUR' ),
'amex' => array(),
),
'DK' => array(
'mastercard' => array(),
'visa' => array(),
'amex' => array( 'DKK' ),
'amex' => array(),
),
'EE' => array(
'mastercard' => array(),
@ -1443,32 +1444,32 @@ return array(
'ES' => array(
'mastercard' => array(),
'visa' => array(),
'amex' => array( 'EUR' ),
'amex' => array(),
),
'FI' => array(
'mastercard' => array(),
'visa' => array(),
'amex' => array( 'EUR' ),
'amex' => array(),
),
'FR' => array(
'mastercard' => array(),
'visa' => array(),
'amex' => array( 'EUR' ),
'amex' => array(),
),
'GB' => array(
'mastercard' => array(),
'visa' => array(),
'amex' => array( 'GBP', 'USD' ),
'amex' => array(),
),
'GR' => array(
'mastercard' => array(),
'visa' => array(),
'amex' => array( 'EUR' ),
'amex' => array(),
),
'HU' => array(
'mastercard' => array(),
'visa' => array(),
'amex' => array( 'HUF' ),
'amex' => array(),
),
'IE' => array(
'mastercard' => array(),
@ -1478,7 +1479,7 @@ return array(
'IT' => array(
'mastercard' => array(),
'visa' => array(),
'amex' => array( 'EUR' ),
'amex' => array(),
),
'US' => array(
'mastercard' => array(),
@ -1489,7 +1490,7 @@ return array(
'CA' => array(
'mastercard' => array(),
'visa' => array(),
'amex' => array( 'CAD' ),
'amex' => array( 'CAD', 'USD' ),
'jcb' => array( 'CAD' ),
),
'LI' => array(
@ -1500,22 +1501,22 @@ return array(
'LT' => array(
'mastercard' => array(),
'visa' => array(),
'amex' => array( 'EUR' ),
'amex' => array(),
),
'LU' => array(
'mastercard' => array(),
'visa' => array(),
'amex' => array( 'EUR' ),
'amex' => array(),
),
'LV' => array(
'mastercard' => array(),
'visa' => array(),
'amex' => array( 'EUR', 'USD' ),
'amex' => array(),
),
'MT' => array(
'mastercard' => array(),
'visa' => array(),
'amex' => array( 'EUR' ),
'amex' => array(),
),
'MX' => array(
'mastercard' => array(),
@ -1525,7 +1526,7 @@ return array(
'NL' => array(
'mastercard' => array(),
'visa' => array(),
'amex' => array( 'EUR', 'USD' ),
'amex' => array(),
),
'NO' => array(
'mastercard' => array(),
@ -1535,32 +1536,32 @@ return array(
'PL' => array(
'mastercard' => array(),
'visa' => array(),
'amex' => array( 'EUR', 'USD', 'GBP', 'PLN' ),
'amex' => array(),
),
'PT' => array(
'mastercard' => array(),
'visa' => array(),
'amex' => array( 'EUR', 'USD', 'CAD', 'GBP' ),
'amex' => array(),
),
'RO' => array(
'mastercard' => array(),
'visa' => array(),
'amex' => array( 'EUR', 'USD' ),
'amex' => array(),
),
'SE' => array(
'mastercard' => array(),
'visa' => array(),
'amex' => array( 'EUR', 'SEK' ),
'amex' => array(),
),
'SI' => array(
'mastercard' => array(),
'visa' => array(),
'amex' => array( 'EUR' ),
'amex' => array(),
),
'SK' => array(
'mastercard' => array(),
'visa' => array(),
'amex' => array( 'EUR', 'GBP' ),
'amex' => array(),
),
'JP' => array(
'mastercard' => array(),
@ -1633,4 +1634,11 @@ return array(
$container->get( 'woocommerce.logger.woocommerce' )
);
},
'api.sdk-client-token' => static function( ContainerInterface $container ): SdkClientToken {
return new SdkClientToken(
$container->get( 'api.host' ),
$container->get( 'api.bearer' ),
$container->get( 'woocommerce.logger.woocommerce' )
);
},
);

View file

@ -0,0 +1,109 @@
<?php
/**
* Generates user ID token for payer.
*
* @package WooCommerce\PayPalCommerce\ApiClient\Authentication
*/
namespace WooCommerce\PayPalCommerce\ApiClient\Authentication;
use Psr\Log\LoggerInterface;
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\RequestTrait;
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
use WP_Error;
/**
* Class SdkClientToken
*/
class SdkClientToken {
use RequestTrait;
/**
* The host.
*
* @var string
*/
private $host;
/**
* The bearer.
*
* @var Bearer
*/
private $bearer;
/**
* The logger.
*
* @var LoggerInterface
*/
private $logger;
/**
* SdkClientToken constructor.
*
* @param string $host The host.
* @param Bearer $bearer The bearer.
* @param LoggerInterface $logger The logger.
*/
public function __construct(
string $host,
Bearer $bearer,
LoggerInterface $logger
) {
$this->host = $host;
$this->bearer = $bearer;
$this->logger = $logger;
}
/**
* Returns `sdk_client_token` which uniquely identifies the payer.
*
* @param string $target_customer_id Vaulted customer id.
*
* @return string
*
* @throws PayPalApiException If the request fails.
* @throws RuntimeException If something unexpected happens.
*/
public function sdk_client_token( string $target_customer_id = '' ): string {
$bearer = $this->bearer->bearer();
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$domain = wp_unslash( $_SERVER['HTTP_HOST'] ?? '' );
$url = trailingslashit( $this->host ) . 'v1/oauth2/token?grant_type=client_credentials&response_type=client_token&intent=sdk_init&domains[]=*.' . $domain;
if ( $target_customer_id ) {
$url = add_query_arg(
array(
'target_customer_id' => $target_customer_id,
),
$url
);
}
$args = array(
'method' => 'POST',
'headers' => array(
'Authorization' => 'Bearer ' . $bearer->token(),
'Content-Type' => 'application/x-www-form-urlencoded',
),
);
$response = $this->request( $url, $args );
if ( $response instanceof WP_Error ) {
throw new RuntimeException( $response->get_error_message() );
}
$json = json_decode( $response['body'] );
$status_code = (int) wp_remote_retrieve_response_code( $response );
if ( 200 !== $status_code ) {
throw new PayPalApiException( $json, $status_code );
}
return $json->access_token;
}
}

View file

@ -115,7 +115,7 @@ class PaymentMethodTokensEndpoint {
* @throws RuntimeException When something when wrong with the request.
* @throws PayPalApiException When something when wrong setting up the token.
*/
public function payment_tokens( PaymentSource $payment_source ): stdClass {
public function create_payment_token( PaymentSource $payment_source ): stdClass {
$data = array(
'payment_source' => array(
$payment_source->name() => $payment_source->properties(),

View file

@ -9,6 +9,8 @@ declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\ApiClient\Exception;
use stdClass;
/**
* Class PayPalApiException
*/
@ -17,7 +19,7 @@ class PayPalApiException extends RuntimeException {
/**
* The JSON response object of PayPal.
*
* @var \stdClass
* @var stdClass
*/
private $response;
@ -31,10 +33,10 @@ class PayPalApiException extends RuntimeException {
/**
* PayPalApiException constructor.
*
* @param \stdClass|null $response The JSON object.
* @param int $status_code The HTTP status code.
* @param stdClass|null $response The JSON object.
* @param int $status_code The HTTP status code.
*/
public function __construct( \stdClass $response = null, int $status_code = 0 ) {
public function __construct( stdClass $response = null, int $status_code = 0 ) {
if ( is_null( $response ) ) {
$response = new \stdClass();
}
@ -65,7 +67,7 @@ class PayPalApiException extends RuntimeException {
*/
$this->response = $response;
$this->status_code = $status_code;
$message = $response->message;
$message = $this->get_customer_friendly_message( $response );
if ( $response->name ) {
$message = '[' . $response->name . '] ' . $message;
}
@ -141,4 +143,40 @@ class PayPalApiException extends RuntimeException {
return $details;
}
/**
* Returns a friendly message if the error detail is known.
*
* @param stdClass $json The response.
* @return string
*/
public function get_customer_friendly_message( stdClass $json ): string {
if ( empty( $json->details ) ) {
return $json->message;
}
$improved_keys_messages = array(
'PAYMENT_DENIED' => __( 'PayPal rejected the payment. Please reach out to the PayPal support for more information.', 'woocommerce-paypal-payments' ),
'TRANSACTION_REFUSED' => __( 'The transaction has been refused by the payment processor. Please reach out to the PayPal support for more information.', 'woocommerce-paypal-payments' ),
'DUPLICATE_INVOICE_ID' => __( 'The transaction has been refused because the Invoice ID already exists. Please create a new order or reach out to the store owner.', 'woocommerce-paypal-payments' ),
'PAYER_CANNOT_PAY' => __( 'There was a problem processing this transaction. Please reach out to the store owner.', 'woocommerce-paypal-payments' ),
'PAYEE_ACCOUNT_RESTRICTED' => __( 'There was a problem processing this transaction. Please reach out to the store owner.', 'woocommerce-paypal-payments' ),
'AGREEMENT_ALREADY_CANCELLED' => __( 'The requested agreement is already canceled. Please reach out to the PayPal support for more information.', 'woocommerce-paypal-payments' ),
);
$improved_errors = array_filter(
array_keys( $improved_keys_messages ),
function ( $key ) use ( $json ): bool {
foreach ( $json->details as $detail ) {
if ( isset( $detail->issue ) && $detail->issue === $key ) {
return true;
}
}
return false;
}
);
if ( $improved_errors ) {
$improved_errors = array_values( $improved_errors );
return $improved_keys_messages[ $improved_errors[0] ];
}
return $json->message;
}
}

View file

@ -54,7 +54,7 @@ class ApplicationContextRepository {
$payment_preference = $this->settings->has( 'payee_preferred' ) && $this->settings->get( 'payee_preferred' ) ?
ApplicationContext::PAYMENT_METHOD_IMMEDIATE_PAYMENT_REQUIRED : ApplicationContext::PAYMENT_METHOD_UNRESTRICTED;
$context = new ApplicationContext(
network_home_url( \WC_AJAX::get_endpoint( ReturnUrlEndpoint::ENDPOINT ) ),
home_url( \WC_AJAX::get_endpoint( ReturnUrlEndpoint::ENDPOINT ) ),
(string) wc_get_checkout_url(),
(string) $brand_name,
$locale,