Skip to content

Commit 8f856e5

Browse files
authored
Merge pull request #4084 from woocommerce/dev/PCP-4891-agentic-commerce
Agentic Commerce (4891)
2 parents afe6cc8 + 4a0cd5d commit 8f856e5

204 files changed

Lines changed: 28346 additions & 4902 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

composer.json

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
"psr/log": "^1.1",
1919
"ralouphie/getallheaders": "^3.0",
2020
"wikimedia/composer-merge-plugin": "^2.0",
21-
"symfony/polyfill-php80": "^1.19"
21+
"symfony/polyfill-php80": "^1.19",
22+
"firebase/php-jwt": "^6"
2223
},
2324
"require-dev": {
2425
"inpsyde/composer-assets-compiler": "^2.5",
@@ -112,6 +113,11 @@
112113
"dealerdirect/phpcodesniffer-composer-installer": true,
113114
"wikimedia/composer-merge-plugin": true,
114115
"composer/installers": true
116+
},
117+
"audit": {
118+
"ignore": {
119+
"PKSA-y2cr-5h3j-g3ys": "Disputed CVE. Only affects applications generating weak keys, which is not relevant for this plugin."
120+
}
115121
}
116122
}
117123
}

composer.lock

Lines changed: 72 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

modules.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@
1010
use WooCommerce\PayPalCommerce\PayLaterBlock\PayLaterBlockModule;
1111
use WooCommerce\PayPalCommerce\PayLaterWCBlocks\PayLaterWCBlocksModule;
1212
use WooCommerce\PayPalCommerce\PayLaterConfigurator\PayLaterConfiguratorModule;
13+
use WooCommerce\PayPalCommerce\Settings\SettingsModule;
1314

14-
return function ( string $root_dir ): iterable {
15+
return static function ( string $root_dir ): iterable {
1516
$modules_dir = "$root_dir/modules";
1617

1718
$modules = array(
@@ -85,5 +86,12 @@
8586
$modules[] = ( require "$modules_dir/ppcp-axo-block/module.php" )();
8687
}
8788

89+
if ( apply_filters(
90+
'woocommerce.feature-flags.woocommerce_paypal_payments.store_sync_enabled',
91+
getenv( 'PCP_STORE_SYNC_ENABLED' ) === '1'
92+
) ) {
93+
$modules[] = ( require "$modules_dir/ppcp-store-sync/module.php" )();
94+
}
95+
8896
return $modules;
8997
};

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

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,4 +203,50 @@ public function order( string $id ): array {
203203

204204
return $response;
205205
}
206+
207+
/**
208+
* Patch a PayPal order.
209+
*
210+
* @param string $id PayPal order ID.
211+
* @param array $patch_data The PATCH operations array.
212+
* @return array
213+
* @throws RuntimeException If something went wrong with the request.
214+
* @throws PayPalApiException If something went wrong with the PayPal API request.
215+
*/
216+
public function patch_order( string $id, array $patch_data ): array {
217+
$bearer = $this->bearer->bearer();
218+
$url = trailingslashit( $this->host ) . 'v2/checkout/orders/' . $id;
219+
220+
$args = array(
221+
'method' => 'PATCH',
222+
'headers' => array(
223+
'Authorization' => 'Bearer ' . $bearer->token(),
224+
'Content-Type' => 'application/json',
225+
'PayPal-Request-Id' => uniqid( 'ppcp-', true ),
226+
),
227+
'body' => wp_json_encode( $patch_data ),
228+
);
229+
230+
$response = $this->request( $url, $args );
231+
if ( $response instanceof WP_Error ) {
232+
throw new RuntimeException( $response->get_error_message() );
233+
}
234+
235+
$status_code = (int) wp_remote_retrieve_response_code( $response );
236+
if ( $status_code !== 204 ) {
237+
$body = json_decode( $response['body'] );
238+
239+
$message = $body->details[0]->description ?? '';
240+
if ( $message ) {
241+
throw new RuntimeException( $message );
242+
}
243+
244+
throw new PayPalApiException(
245+
$body,
246+
$status_code
247+
);
248+
}
249+
250+
return $response;
251+
}
206252
}

modules/ppcp-blocks/src/BlocksModule.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ static function () use ( $c ) {
143143
add_filter(
144144
'woocommerce_paypal_payments_sdk_components_hook',
145145
function ( array $components, string $context ) {
146-
if ( str_ends_with( $context, '-block' ) ) {
146+
if ( substr( $context, -6 ) === '-block' ) {
147147
$components[] = 'buttons';
148148
}
149149

modules/ppcp-button/src/Endpoint/CreateOrderEndpoint.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,7 @@ private function create_paypal_order( ?WC_Order $wc_order = null, string $paymen
563563
&& array_filter(
564564
$exception->details(),
565565
function ( stdClass $detail ): bool {
566-
return isset( $detail->field ) && str_contains( (string) $detail->field, 'shipping/address' );
566+
return isset( $detail->field ) && strpos( (string) $detail->field, 'shipping/address' ) !== false;
567567
}
568568
) ) {
569569
$this->logger->info( 'Invalid shipping address for order creation, retrying without it.' );

modules/ppcp-button/src/Helper/WooCommerceOrderCreator.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,11 @@ function ( $option ) {
443443
$shipping = $this->shipping_factory->from_paypal_response( $shipping_address_data );
444444
}
445445

446-
return $shipping;
446+
return apply_filters(
447+
'woocommerce_paypal_payments_order_creator_get_shipping',
448+
$shipping,
449+
$order,
450+
$paypal_data
451+
);
447452
}
448453
}

modules/ppcp-card-fields/src/CardFieldsModule.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,8 +187,15 @@ function ( Order $order ) use ( $c ) {
187187

188188
$logger->warning( "Could not capture order {$order->id()}" );
189189

190-
if ( apply_filters( 'woocommerce_paypal_payments_force_delete_wc_order_on_failed_capture', true ) ) {
191-
// Add delete order flag in WC session to force delete on process payment failure handler.
190+
// Only set session flag if WC session exists (not in API/agentic context).
191+
/**
192+
* Fires to add a delete order flag in WC session.
193+
*/
194+
if ( apply_filters( 'woocommerce_paypal_payments_force_delete_wc_order_on_failed_capture', true )
195+
&& function_exists( 'WC' ) && WC()->session instanceof \WC_Session ) {
196+
/**
197+
* Add delete order flag in WC session to force delete on process payment failure handler.
198+
*/
192199
WC()->session->set( 'ppcp_delete_wc_order_on_payment_failure', true );
193200
}
194201

modules/ppcp-local-alternative-payment-methods/src/LocalAlternativePaymentMethodsModule.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,7 @@ private function is_rest_request(): bool {
542542
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
543543
$request_uri = wp_unslash( $_SERVER['REQUEST_URI'] ?? '' );
544544

545-
return str_contains( $request_uri, '/wp-json/wc/' );
545+
return is_string( $request_uri ) && strpos( $request_uri, '/wp-json/wc/' ) !== false;
546546
}
547547

548548
/**

modules/ppcp-settings/resources/js/Components/Screens/Settings/Components/Settings/Blocks/PaypalSettings.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,10 @@ import SettingsBlock from '@ppcp-settings/Components/ReusableComponents/Settings
1010
import Accordion from '@ppcp-settings/Components/ReusableComponents/AccordionSection';
1111
import { SettingsHooks } from '@ppcp-settings/data';
1212
import SoftDescriptorInput from '@ppcp-settings/Components/ReusableComponents/Controls/SoftdescriptorInput';
13+
import { useRegisteredSettings, SLOTS } from '@ppcp-settings/extensions';
1314

1415
const PaypalSettings = ( { hasContactModule } ) => {
1516
const {
16-
savePaypalAndVenmo,
17-
setSavePaypalAndVenmo,
1817
contactModule,
1918
setContactModule,
2019
subtotalAdjustment,
@@ -34,6 +33,9 @@ const PaypalSettings = ( { hasContactModule } ) => {
3433
const siteTitle = siteData?.title;
3534
const buttonLanguageChoices = window.ppcpSettings.buttonLanguageChoices;
3635

36+
// Get registered settings for this slot
37+
const footerSettings = useRegisteredSettings( SLOTS.PAYPAL_SETTINGS_END );
38+
3739
return (
3840
<Accordion
3941
className="ppcp--paypal-settings"
@@ -158,6 +160,11 @@ const PaypalSettings = ( { hasContactModule } ) => {
158160
) }
159161
/>
160162
</SettingsBlock>
163+
164+
{ /* Extension point */ }
165+
{ footerSettings.map( ( { component: Component, id } ) => (
166+
<Component key={ id } />
167+
) ) }
161168
</Accordion>
162169
);
163170
};

0 commit comments

Comments
 (0)