Skip to content

Commit 26a84bc

Browse files
committed
Merge branch 'dev/develop' into dev/PCP-6704-woo-plugin-detection-for-product-customizations
2 parents 2f6deb4 + a6081df commit 26a84bc

32 files changed

Lines changed: 2586 additions & 910 deletions

modules/ppcp-api-client/services.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
use WooCommerce\PayPalCommerce\ApiClient\Factory\CardAuthenticationResultFactory;
3939
use WooCommerce\PayPalCommerce\ApiClient\Factory\ContactPreferenceFactory;
4040
use WooCommerce\PayPalCommerce\ApiClient\Factory\ExchangeRateFactory;
41+
use WooCommerce\PayPalCommerce\ApiClient\Factory\PartnersEndpointFactory;
42+
use WooCommerce\PayPalCommerce\ApiClient\Factory\PayPalBearerFactory;
4143
use WooCommerce\PayPalCommerce\ApiClient\Factory\FraudProcessorResponseFactory;
4244
use WooCommerce\PayPalCommerce\ApiClient\Factory\ItemFactory;
4345
use WooCommerce\PayPalCommerce\ApiClient\Factory\MoneyFactory;
@@ -172,6 +174,31 @@
172174
$container->get( 'api.partners-seller-status-cache' )
173175
);
174176
},
177+
/**
178+
* Factory for connection-aware bearers authenticated with explicit credentials.
179+
*/
180+
'api.factory.paypal-bearer' => static function ( ContainerInterface $container ): PayPalBearerFactory {
181+
return new PayPalBearerFactory(
182+
$container->get( 'api.token-rate-limiter' ),
183+
$container->get( 'woocommerce.logger.woocommerce' )
184+
);
185+
},
186+
/**
187+
* Factory for PartnersEndpoint instances.
188+
* Creates a fresh bearer on every call to reflect the current connection and
189+
* environment state.
190+
*/
191+
'api.factory.partners-endpoint' => static function ( ContainerInterface $container ): PartnersEndpointFactory {
192+
return new PartnersEndpointFactory(
193+
$container->get( 'api.env.paypal-host' ),
194+
$container->get( 'api.env.partner-id' ),
195+
$container->get( 'api.factory.sellerstatus' ),
196+
$container->get( 'api.helper.failure-registry' ),
197+
$container->get( 'api.partners-seller-status-cache' ),
198+
$container->get( 'api.factory.paypal-bearer' ),
199+
$container->get( 'woocommerce.logger.woocommerce' )
200+
);
201+
},
175202
'api.partners-seller-status-cache' => static function ( ContainerInterface $container ): Cache {
176203
return new Cache( 'ppcp-seller-status-' );
177204
},
@@ -944,6 +971,18 @@ static function ( ContainerInterface $container ): PurchaseUnitSanitizer {
944971
$container->get( 'api.paypal-host-sandbox' )
945972
);
946973
},
974+
'api.env.partner-id' => static function ( ContainerInterface $container ): EnvironmentConfig {
975+
/**
976+
* Environment specific partner ID.
977+
*
978+
* @type EnvironmentConfig<string>
979+
*/
980+
return EnvironmentConfig::create(
981+
'string',
982+
$container->get( 'api.partner_merchant_id-production' ),
983+
$container->get( 'api.partner_merchant_id-sandbox' )
984+
);
985+
},
947986
'api.env.endpoint.login-seller' => static function ( ContainerInterface $container ): EnvironmentConfig {
948987
/**
949988
* Environment specific LoginSeller API instances.
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
<?php
2+
/**
3+
* Builds a PartnersEndpoint with a dedicated bearer for given credentials.
4+
*
5+
* @package WooCommerce\PayPalCommerce\ApiClient\Factory
6+
*/
7+
8+
declare( strict_types = 1 );
9+
10+
namespace WooCommerce\PayPalCommerce\ApiClient\Factory;
11+
12+
use Psr\Log\LoggerInterface;
13+
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnersEndpoint;
14+
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
15+
use WooCommerce\PayPalCommerce\ApiClient\Helper\FailureRegistry;
16+
use WooCommerce\PayPalCommerce\WcGateway\Helper\EnvironmentConfig;
17+
18+
/**
19+
* Builds a PartnersEndpoint for an explicit set of merchant credentials, backed
20+
* by its own freshly minted bearer.
21+
*
22+
* The container's shared PartnersEndpoint binds its bearer, host and merchant ID
23+
* to the connection state that existed when it was first resolved during the
24+
* request. This factory takes the credentials as arguments instead, so a caller
25+
* can obtain a working endpoint for any credentials, regardless of the active
26+
* connection or when in the request it is called.
27+
*/
28+
class PartnersEndpointFactory {
29+
30+
/**
31+
* PayPal API host, per environment.
32+
*
33+
* @var EnvironmentConfig<string>
34+
*/
35+
private EnvironmentConfig $paypal_host;
36+
37+
/**
38+
* Partner merchant ID, per environment.
39+
*
40+
* @var EnvironmentConfig<string>
41+
*/
42+
private EnvironmentConfig $partner_id;
43+
44+
private SellerStatusFactory $seller_status_factory;
45+
46+
private FailureRegistry $failure_registry;
47+
48+
private Cache $cache;
49+
50+
private PayPalBearerFactory $bearer_factory;
51+
52+
private LoggerInterface $logger;
53+
54+
/**
55+
* @param EnvironmentConfig<string> $paypal_host
56+
* @param EnvironmentConfig<string> $partner_id
57+
* @param SellerStatusFactory $seller_status_factory
58+
* @param FailureRegistry $failure_registry
59+
* @param Cache $cache
60+
* @param PayPalBearerFactory $bearer_factory
61+
* @param LoggerInterface $logger
62+
*
63+
* phpcs:disable Squiz.Commenting.FunctionComment.IncorrectTypeHint
64+
*/
65+
public function __construct(
66+
EnvironmentConfig $paypal_host,
67+
EnvironmentConfig $partner_id,
68+
SellerStatusFactory $seller_status_factory,
69+
FailureRegistry $failure_registry,
70+
Cache $cache,
71+
PayPalBearerFactory $bearer_factory,
72+
LoggerInterface $logger
73+
) {
74+
$this->paypal_host = $paypal_host;
75+
$this->partner_id = $partner_id;
76+
$this->seller_status_factory = $seller_status_factory;
77+
$this->failure_registry = $failure_registry;
78+
$this->cache = $cache;
79+
$this->bearer_factory = $bearer_factory;
80+
$this->logger = $logger;
81+
}
82+
83+
/**
84+
* Builds a PartnersEndpoint for the given merchant credentials.
85+
*
86+
* @param bool $is_sandbox Whether the credentials are for the sandbox.
87+
* @param string $client_id The merchant client ID.
88+
* @param string $client_secret The merchant client secret.
89+
* @param string $merchant_id The merchant ID.
90+
*/
91+
public function create(
92+
bool $is_sandbox,
93+
string $client_id,
94+
string $client_secret,
95+
string $merchant_id
96+
): PartnersEndpoint {
97+
$host = (string) $this->paypal_host->get_value( $is_sandbox );
98+
99+
$bearer = $this->bearer_factory->create( $host, $client_id, $client_secret );
100+
101+
return new PartnersEndpoint(
102+
$host,
103+
$bearer,
104+
$this->logger,
105+
$this->seller_status_factory,
106+
(string) $this->partner_id->get_value( $is_sandbox ),
107+
$merchant_id,
108+
$this->failure_registry,
109+
$this->cache
110+
);
111+
}
112+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
/**
3+
* Builds the API bearer for a set of credentials.
4+
*
5+
* @package WooCommerce\PayPalCommerce\ApiClient\Factory
6+
*/
7+
8+
declare( strict_types = 1 );
9+
10+
namespace WooCommerce\PayPalCommerce\ApiClient\Factory;
11+
12+
use Psr\Log\LoggerInterface;
13+
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
14+
use WooCommerce\PayPalCommerce\ApiClient\Authentication\ConnectBearer;
15+
use WooCommerce\PayPalCommerce\ApiClient\Authentication\PayPalBearer;
16+
use WooCommerce\PayPalCommerce\ApiClient\Authentication\TokenRateLimiter;
17+
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
18+
use WooCommerce\PayPalCommerce\ApiClient\Helper\InMemoryCache;
19+
use WooCommerce\PayPalCommerce\Settings\Data\SettingsProvider;
20+
21+
/**
22+
* Produces the bearer that matches the supplied credentials.
23+
*
24+
* Credential presence is the connection signal: with both a client ID and secret
25+
* the factory builds an authenticated PayPalBearer, otherwise it returns a
26+
* login-only ConnectBearer (nothing is connected, so there is nothing to
27+
* authenticate with). This mirrors PayPalBearer itself, which cannot fetch a token
28+
* without credentials.
29+
*
30+
* By default the PayPalBearer gets an isolated in-memory token cache and static
31+
* credentials, scoping its token to the passed credentials so it never mixes with
32+
* another account's cached token. Pass a persistent cache and a settings provider
33+
* to reproduce the shared, connection-bound bearer instead; when the settings
34+
* provider resolves credentials dynamically, still pass the current client ID and
35+
* secret so the bearer-type decision stays correct.
36+
*/
37+
class PayPalBearerFactory {
38+
39+
private TokenRateLimiter $rate_limiter;
40+
41+
private LoggerInterface $logger;
42+
43+
public function __construct( TokenRateLimiter $rate_limiter, LoggerInterface $logger ) {
44+
$this->rate_limiter = $rate_limiter;
45+
$this->logger = $logger;
46+
}
47+
48+
/**
49+
* Builds the bearer for the given credentials.
50+
*
51+
* Returns an authenticated PayPalBearer when both credentials are present,
52+
* otherwise a login-only ConnectBearer.
53+
*
54+
* @param string $host The PayPal API host.
55+
* @param string $client_id The client ID.
56+
* @param string $client_secret The client secret.
57+
* @param ?Cache $cache Token cache; defaults to an isolated in-memory cache.
58+
* @param ?SettingsProvider $settings Resolves credentials dynamically when provided.
59+
*/
60+
public function create(
61+
string $host = '',
62+
string $client_id = '',
63+
string $client_secret = '',
64+
?Cache $cache = null,
65+
?SettingsProvider $settings = null
66+
): Bearer {
67+
if ( '' === $client_id || '' === $client_secret ) {
68+
return new ConnectBearer();
69+
}
70+
71+
return new PayPalBearer(
72+
$cache ?? new InMemoryCache(),
73+
$host,
74+
$client_id,
75+
$client_secret,
76+
$this->logger,
77+
$settings,
78+
$this->rate_limiter
79+
);
80+
}
81+
}

modules/ppcp-fraud-protection/services.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@
2929
$container->get( 'fraud-protection.asset_getter' ),
3030
$container->get( 'ppcp.asset-version' ),
3131
$container->get( 'woocommerce.logger.woocommerce' ),
32-
$container->get( 'fraud-protection.recaptcha.rejection-counter' )
32+
$container->get( 'fraud-protection.recaptcha.rejection-counter' ),
33+
$container->get( 'wcgateway.settings.status' )
3334
);
3435
},
3536
'fraud-protection.recaptcha.integration' => static function (): RecaptchaIntegration {

0 commit comments

Comments
 (0)