🚧 non-working version of internal REST service

This commit is contained in:
Philipp Stracker 2025-02-26 10:35:43 +01:00
parent 79e4f9cdd4
commit 6dd0034c0a
No known key found for this signature in database
4 changed files with 154 additions and 37 deletions

View file

@ -49,6 +49,7 @@ use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
use WooCommerce\PayPalCommerce\PayLaterConfigurator\Endpoint\SaveConfig;
use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment;
use WooCommerce\PayPalCommerce\WcGateway\Helper\ConnectionState;
use WooCommerce\PayPalCommerce\Settings\Service\InternalRestService;
return array(
'settings.url' => static function ( ContainerInterface $container ) : string {
@ -172,7 +173,10 @@ return array(
return new OnboardingRestEndpoint( $container->get( 'settings.data.onboarding' ) );
},
'settings.rest.common' => static function ( ContainerInterface $container ) : CommonRestEndpoint {
return new CommonRestEndpoint( $container->get( 'settings.data.general' ) );
return new CommonRestEndpoint(
$container->get( 'settings.data.general' ),
$container->get( 'settings.service.rest-service' )
);
},
'settings.rest.payment' => static function ( ContainerInterface $container ) : PaymentRestEndpoint {
return new PaymentRestEndpoint(
@ -313,10 +317,13 @@ return array(
$container->get( 'api.env.endpoint.login-seller' ),
$container->get( 'api.repository.partner-referrals-data' ),
$container->get( 'settings.connection-state' ),
$container->get( 'api.endpoint.partners' ),
$container->get( 'settings.service.rest-service' ),
$container->get( 'woocommerce.logger.woocommerce' )
);
},
'settings.service.rest-service' => static function ( ContainerInterface $container ) : InternalRestService {
return new InternalRestService();
},
'settings.service.sanitizer' => static function ( ContainerInterface $container ) : DataSanitizer {
return new DataSanitizer();
},

View file

@ -13,6 +13,7 @@ use WP_REST_Server;
use WP_REST_Response;
use WP_REST_Request;
use WooCommerce\PayPalCommerce\Settings\Data\GeneralSettings;
use WooCommerce\PayPalCommerce\Settings\Service\InternalRestService;
/**
* REST controller for "common" settings, which are used and modified by
@ -22,6 +23,11 @@ use WooCommerce\PayPalCommerce\Settings\Data\GeneralSettings;
* internal data model.
*/
class CommonRestEndpoint extends RestEndpoint {
/**
* Full REST path to the merchant-details endpoint, relative to the namespace.
*/
protected const SELLER_ACCOUNT_PATH = 'common/seller-account';
/**
* The base path for this REST controller.
*
@ -36,6 +42,13 @@ class CommonRestEndpoint extends RestEndpoint {
*/
protected GeneralSettings $settings;
/**
* Internal REST handler, used to authenticate internal requests.
*
* @var InternalRestService
*/
protected InternalRestService $rest_service;
/**
* Field mapping for request to profile transformation.
*
@ -104,10 +117,27 @@ class CommonRestEndpoint extends RestEndpoint {
/**
* Constructor.
*
* @param GeneralSettings $settings The settings instance.
* @param GeneralSettings $settings The settings instance.
* @param InternalRestService $rest_service Internal REST handler, for authentication.
*/
public function __construct( GeneralSettings $settings ) {
$this->settings = $settings;
public function __construct( GeneralSettings $settings, InternalRestService $rest_service ) {
$this->settings = $settings;
$this->rest_service = $rest_service;
}
/**
* Returns the path to the "Get Seller Account Details" REST route.
* This is an internal route which is consumed by the plugin itself during onboarding.
*
* @param bool $full_route Whether to return the full endpoint path or just the route name.
* @return string The full path to the REST endpoint.
*/
public static function seller_account_route( bool $full_route = false ) : string {
if ( $full_route ) {
return '/' . static::NAMESPACE . '/' . self::SELLER_ACCOUNT_PATH;
}
return self::SELLER_ACCOUNT_PATH;
}
/**
@ -155,6 +185,24 @@ class CommonRestEndpoint extends RestEndpoint {
'permission_callback' => array( $this, 'check_permission' ),
)
);
/**
* GET /wp-json/wc/v3/wc_paypal/common/seller-account
*/
register_rest_route(
static::NAMESPACE,
self::seller_account_route(),
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_seller_account_info' ),
'permission_callback' => function ( WP_REST_Request $request ) {
$token = $request->get_header( 'X-Internal-Token' );
$endpoint = self::seller_account_route();
return $this->rest_service->verify_token( $token, $endpoint );
},
)
);
}
/**
@ -205,6 +253,17 @@ class CommonRestEndpoint extends RestEndpoint {
return $this->return_success( $js_data, $extra_data );
}
/**
* Requests details from the PayPal API.
*
* Used during onboarding to enrich the merchant details in the DB.
*
* @return WP_REST_Response Seller details, provided by PayPal's API.
*/
public function get_seller_account_info() : WP_REST_Response {
return $this->return_success( array( 'country' => 'XY' ) );
}
/**
* Appends the "merchant" attribute to the extra_data collection, which
* contains details about the merchant's PayPal account, like the merchant ID.

View file

@ -27,6 +27,7 @@ use WooCommerce\PayPalCommerce\Settings\DTO\MerchantConnectionDTO;
use WooCommerce\PayPalCommerce\Webhooks\WebhookRegistrar;
use WooCommerce\PayPalCommerce\Settings\Enum\SellerTypeEnum;
use WooCommerce\PayPalCommerce\WcGateway\Helper\ConnectionState;
use WooCommerce\PayPalCommerce\Settings\Endpoint\CommonRestEndpoint;
/**
* Class that manages the connection to PayPal.
@ -75,22 +76,22 @@ class AuthenticationManager {
private ConnectionState $connection_state;
/**
* Partners endpoint.
* Internal REST service, to consume own REST handlers in a separate request.
*
* @var PartnersEndpoint
* @var InternalRestService
*/
private PartnersEndpoint $partners_endpoint;
private InternalRestService $rest_service;
/**
* Constructor.
*
* @param GeneralSettings $common_settings Data model that stores the connection details.
* @param EnvironmentConfig $connection_host API host for direct authentication.
* @param EnvironmentConfig $login_endpoint API handler to fetch merchant credentials.
* @param PartnerReferralsData $referrals_data Partner referrals data.
* @param ConnectionState $connection_state Connection state manager.
* @param PartnersEndpoint $partners_endpoint Partners endpoint.
* @param ?LoggerInterface $logger Logging instance.
* @param GeneralSettings $common_settings Data model that stores the connection details.
* @param EnvironmentConfig $connection_host API host for direct authentication.
* @param EnvironmentConfig $login_endpoint API handler to fetch merchant credentials.
* @param PartnerReferralsData $referrals_data Partner referrals data.
* @param ConnectionState $connection_state Connection state manager.
* @param InternalRestService $rest_service Allows calling internal REST endpoints.
* @param ?LoggerInterface $logger Logging instance.
*/
public function __construct(
GeneralSettings $common_settings,
@ -98,16 +99,16 @@ class AuthenticationManager {
EnvironmentConfig $login_endpoint,
PartnerReferralsData $referrals_data,
ConnectionState $connection_state,
PartnersEndpoint $partners_endpoint,
InternalRestService $rest_service,
?LoggerInterface $logger = null
) {
$this->common_settings = $common_settings;
$this->connection_host = $connection_host;
$this->login_endpoint = $login_endpoint;
$this->referrals_data = $referrals_data;
$this->connection_state = $connection_state;
$this->partners_endpoint = $partners_endpoint;
$this->logger = $logger ?: new NullLogger();
$this->common_settings = $common_settings;
$this->connection_host = $connection_host;
$this->login_endpoint = $login_endpoint;
$this->referrals_data = $referrals_data;
$this->connection_state = $connection_state;
$this->rest_service = $rest_service;
$this->logger = $logger ?: new NullLogger();
}
/**
@ -281,17 +282,10 @@ class AuthenticationManager {
*/
$connection = $this->common_settings->get_merchant_data();
try {
$seller_status = $this->partners_endpoint->seller_status();
} catch ( PayPalApiException $exception ) {
$seller_status = null;
}
$connection->is_sandbox = $use_sandbox;
$connection->client_id = $credentials['client_id'];
$connection->client_secret = $credentials['client_secret'];
$connection->merchant_id = $credentials['merchant_id'];
$connection->merchant_country = ! is_null( $seller_status ) ? $seller_status->country() : '';
$connection->is_sandbox = $use_sandbox;
$connection->client_id = $credentials['client_id'];
$connection->client_secret = $credentials['client_secret'];
$connection->merchant_id = $credentials['merchant_id'];
$this->update_connection_details( $connection );
}
@ -451,14 +445,14 @@ class AuthenticationManager {
}
try {
// TODO: this call only reliably works in the _next_ request, because in the current request the PartnersEndpoint instance might be initialized with an empty merchant_id.
$seller_status = $this->partners_endpoint->seller_status();
$endpoint = CommonRestEndpoint::seller_account_route( true );
$details = $this->rest_service->get_data( $endpoint );
// Request the merchant details via a PayPal API request.
$connection = $this->common_settings->get_merchant_data();
// Enrich the connection details with additional details.
$connection->merchant_country = $seller_status->country();
$connection->merchant_country = $details['country'];
// Persist the changes.
$this->common_settings->set_merchant_data( $connection );

View file

@ -0,0 +1,57 @@
<?php
/**
* Service that allows calling internal REST endpoints from server-side.
*
* @package WooCommerce\PayPalCommerce\Settings\Service
*/
declare( strict_types = 1 );
namespace WooCommerce\PayPalCommerce\Settings\Service;
use Throwable;
class InternalRestService {
public function get_data( string $endpoint ) : array {
$token = $this->generate_token( $endpoint );
$rest_url = rest_url( $endpoint );
$response = wp_remote_get(
$rest_url,
array(
'headers' => array(
'X-Internal-Token' => $token,
'Content-Type' => 'application/json',
),
)
);
if ( is_wp_error( $response ) ) {
return array();
}
$body = wp_remote_retrieve_body( $response );
try {
$json = json_decode( $body, true, 512, JSON_THROW_ON_ERROR );
} catch ( Throwable $exception ) {
return array();
}
if ( ! $json || empty( $json['success'] ) ) {
return array();
}
return $json['data'];
}
public function verify_token( string $token, string $endpoint ) : bool {
$expected_token = $this->generate_token( $endpoint );
return $expected_token === $token;
}
private function generate_token( string $token_id ) : string {
return base64_encode( $token_id );
}
}