* Move is built to method

* Moved payment related logic into single controller class for better organization

* Only load assets on non-rest requests
This commit is contained in:
Mike Jolley 2020-04-27 16:51:50 +01:00 committed by GitHub
parent e5589727fc
commit 30ecea188f
8 changed files with 329 additions and 297 deletions

View File

@ -7,10 +7,10 @@
namespace Automattic\WooCommerce\Blocks; namespace Automattic\WooCommerce\Blocks;
use Automattic\WooCommerce\Blocks\Assets\PaymentMethodAssets;
defined( 'ABSPATH' ) || exit; defined( 'ABSPATH' ) || exit;
use Automattic\WooCommerce\Blocks\Package;
/** /**
* Assets class. * Assets class.
*/ */
@ -72,8 +72,7 @@ class Assets {
self::register_script( 'wc-price-filter', plugins_url( self::get_block_asset_build_path( 'price-filter' ), __DIR__ ), $block_dependencies ); self::register_script( 'wc-price-filter', plugins_url( self::get_block_asset_build_path( 'price-filter' ), __DIR__ ), $block_dependencies );
self::register_script( 'wc-attribute-filter', plugins_url( self::get_block_asset_build_path( 'attribute-filter' ), __DIR__ ), $block_dependencies ); self::register_script( 'wc-attribute-filter', plugins_url( self::get_block_asset_build_path( 'attribute-filter' ), __DIR__ ), $block_dependencies );
self::register_script( 'wc-active-filters', plugins_url( self::get_block_asset_build_path( 'active-filters' ), __DIR__ ), $block_dependencies ); self::register_script( 'wc-active-filters', plugins_url( self::get_block_asset_build_path( 'active-filters' ), __DIR__ ), $block_dependencies );
$payment_method_handles = Package::container()->get( PaymentMethodAssets::class )->get_all_registered_payment_method_script_handles(); self::register_script( 'wc-checkout-block', plugins_url( self::get_block_asset_build_path( 'checkout' ), __DIR__ ), $block_dependencies );
self::register_script( 'wc-checkout-block', plugins_url( self::get_block_asset_build_path( 'checkout' ), __DIR__ ), array_merge( $block_dependencies, $payment_method_handles ) );
self::register_script( 'wc-cart-block', plugins_url( self::get_block_asset_build_path( 'cart' ), __DIR__ ), $block_dependencies ); self::register_script( 'wc-cart-block', plugins_url( self::get_block_asset_build_path( 'cart' ), __DIR__ ), $block_dependencies );
} }
@ -141,7 +140,7 @@ class Assets {
'isShippingCostHidden' => filter_var( get_option( 'woocommerce_shipping_cost_requires_address' ), FILTER_VALIDATE_BOOLEAN ), 'isShippingCostHidden' => filter_var( get_option( 'woocommerce_shipping_cost_requires_address' ), FILTER_VALIDATE_BOOLEAN ),
'wcBlocksAssetUrl' => plugins_url( 'assets/', __DIR__ ), 'wcBlocksAssetUrl' => plugins_url( 'assets/', __DIR__ ),
'restApiRoutes' => [ 'restApiRoutes' => [
'/wc/store' => array_keys( \Automattic\WooCommerce\Blocks\RestApi::get_routes_from_namespace( 'wc/store' ) ), '/wc/store' => array_keys( Package::container()->get( RestApi::class )->get_routes_from_namespace( 'wc/store' ) ),
], ],
'storeApiNonce' => wp_create_nonce( 'wc_store_api' ), 'storeApiNonce' => wp_create_nonce( 'wc_store_api' ),
'homeUrl' => esc_url( home_url( '/' ) ), 'homeUrl' => esc_url( home_url( '/' ) ),
@ -215,7 +214,7 @@ class Assets {
$version = self::get_file_version( $relative_src ); $version = self::get_file_version( $relative_src );
} }
wp_register_script( $handle, $src, $dependencies, $version, true ); wp_register_script( $handle, $src, apply_filters( 'woocommerce_blocks_register_script_dependencies', $dependencies, $handle ), $version, true );
if ( $has_i18n && function_exists( 'wp_set_script_translations' ) ) { if ( $has_i18n && function_exists( 'wp_set_script_translations' ) ) {
wp_set_script_translations( $handle, 'woo-gutenberg-products-block', dirname( __DIR__ ) . '/languages' ); wp_set_script_translations( $handle, 'woo-gutenberg-products-block', dirname( __DIR__ ) . '/languages' );

View File

@ -1,83 +0,0 @@
<?php
/**
* Handles assets for registered payment types.
*
* @package WooCommerce/Blocks
*/
namespace Automattic\WooCommerce\Blocks\Assets;
use Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry;
/**
* PaymentMethodAssets class.
*
* @since $VID:$
*/
class PaymentMethodAssets {
/**
* Reference to the PaymentMethodRegistry instance
*
* @var PaymentMethodRegistry
*/
private $payment_method_registry;
/**
* An instance of the AssetDataRegistry
*
* @var AssetDataRegistry
*/
private $asset_registry;
/**
* Constructor for class
*
* @param PaymentMethodRegistry $payment_method_registry An instance of Payment Method Registry.
* @param AssetDataRegistry $asset_registry Used for registering data to pass along to the request.
*/
public function __construct( PaymentMethodRegistry $payment_method_registry, AssetDataRegistry $asset_registry ) {
$this->payment_method_registry = $payment_method_registry;
$this->asset_registry = $asset_registry;
}
/**
* Gets an array of all registered payment method script handles.
*
* @return string[]
*/
public function get_all_registered_payment_method_script_handles() {
$script_handles = [];
$payment_methods = $this->payment_method_registry->get_all_registered();
foreach ( $payment_methods as $payment_method ) {
if ( ! $payment_method->is_active() ) {
continue;
}
$script_handles = array_merge(
$script_handles,
is_admin() ? $payment_method->get_payment_method_script_handles_for_admin() : $payment_method->get_payment_method_script_handles()
);
}
return array_unique( array_filter( $script_handles ) );
}
/**
* Adds data from payment methods to the asset registry.
*/
public function register_payment_method_data() {
$payment_methods = $this->payment_method_registry->get_all_registered();
foreach ( $payment_methods as $payment_method ) {
if ( ! $payment_method->is_active() ) {
continue;
}
$asset_data_key = $payment_method->get_name() . '_data';
if ( ! $this->asset_registry->exists( $asset_data_key ) ) {
$this->asset_registry->add( $asset_data_key, $payment_method->get_payment_method_data() );
}
}
}
}

View File

@ -10,7 +10,6 @@ namespace Automattic\WooCommerce\Blocks\BlockTypes;
use Automattic\WooCommerce\Blocks\Package; use Automattic\WooCommerce\Blocks\Package;
use Automattic\WooCommerce\Blocks\Assets; use Automattic\WooCommerce\Blocks\Assets;
use Automattic\WooCommerce\Blocks\Assets\AssetDataRegistry; use Automattic\WooCommerce\Blocks\Assets\AssetDataRegistry;
use Automattic\WooCommerce\Blocks\Assets\PaymentMethodAssets;
defined( 'ABSPATH' ) || exit; defined( 'ABSPATH' ) || exit;
@ -116,7 +115,7 @@ class Checkout extends AbstractBlock {
$this->hydrate_customer_payment_methods( $data_registry ); $this->hydrate_customer_payment_methods( $data_registry );
} }
Package::container()->get( PaymentMethodAssets::class )->register_payment_method_data(); do_action( 'woocommerce_blocks_checkout_enqueue_data' );
} }
/** /**
@ -127,9 +126,7 @@ class Checkout extends AbstractBlock {
* not in the post content on editor load. * not in the post content on editor load.
*/ */
protected function enqueue_scripts( array $attributes = [] ) { protected function enqueue_scripts( array $attributes = [] ) {
$dependencies = Package::container()->get( PaymentMethodAssets::class )->get_all_registered_payment_method_script_handles(); Assets::register_block_script( $this->block_name . '-frontend', $this->block_name . '-block-frontend' );
Assets::register_block_script( $this->block_name . '-frontend', $this->block_name . '-block-frontend', $dependencies );
} }
/** /**

View File

@ -7,19 +7,18 @@
namespace Automattic\WooCommerce\Blocks\Domain; namespace Automattic\WooCommerce\Blocks\Domain;
use Automattic\WooCommerce\Blocks\Assets as OldAssets; use Automattic\WooCommerce\Blocks\Assets as BlockAssets;
use Automattic\WooCommerce\Blocks\Assets\Api as AssetApi; use Automattic\WooCommerce\Blocks\Assets\Api as AssetApi;
use Automattic\WooCommerce\Blocks\Assets\AssetDataRegistry; use Automattic\WooCommerce\Blocks\Assets\AssetDataRegistry;
use Automattic\WooCommerce\Blocks\Assets\BackCompatAssetDataRegistry; use Automattic\WooCommerce\Blocks\Assets\BackCompatAssetDataRegistry;
use Automattic\WooCommerce\Blocks\Assets\PaymentMethodAssets;
use Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry;
use Automattic\WooCommerce\Blocks\Library; use Automattic\WooCommerce\Blocks\Library;
use Automattic\WooCommerce\Blocks\Registry\Container; use Automattic\WooCommerce\Blocks\Registry\Container;
use Automattic\WooCommerce\Blocks\RestApi; use Automattic\WooCommerce\Blocks\RestApi;
use Automattic\WooCommerce\Blocks\Payments\Api as PaymentsApi;
use Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry;
use Automattic\WooCommerce\Blocks\Payments\Integrations\Stripe; use Automattic\WooCommerce\Blocks\Payments\Integrations\Stripe;
use Automattic\WooCommerce\Blocks\Payments\Integrations\Cheque; use Automattic\WooCommerce\Blocks\Payments\Integrations\Cheque;
/** /**
* Takes care of bootstrapping the plugin. * Takes care of bootstrapping the plugin.
* *
@ -59,20 +58,92 @@ class Bootstrap {
/** /**
* Init the package - load the blocks library and define constants. * Init the package - load the blocks library and define constants.
*/ */
public function init() { protected function init() {
if ( ! $this->has_dependencies() ) { if ( ! $this->has_core_dependencies() ) {
return; return;
} }
$this->register_dependencies();
$this->register_payment_methods();
$this->remove_core_blocks(); $is_rest = wc()->is_rest_api_request();
if ( ! $this->is_built() ) { // Load assets in admin and on the frontend.
if ( ! $is_rest ) {
$this->add_build_notice(); $this->add_build_notice();
$this->define_feature_flag();
$this->container->get( AssetDataRegistry::class );
BlockAssets::init();
} }
$this->define_feature_flag(); $this->container->get( PaymentsApi::class );
$this->container->get( RestApi::class );
Library::init();
}
// register core dependencies with the container. /**
* Check core dependencies exist.
*
* @return boolean
*/
protected function has_core_dependencies() {
return class_exists( 'WooCommerce' ) && function_exists( 'register_block_type' );
}
/**
* See if files have been built or not.
*
* @return bool
*/
protected function is_built() {
return file_exists(
$this->package->get_path( 'build/featured-product.js' )
);
}
/**
* Add a notice stating that the build has not been done yet.
*/
protected function add_build_notice() {
if ( $this->is_built() ) {
return;
}
add_action(
'admin_notices',
function() {
echo '<div class="error"><p>';
printf(
/* Translators: %1$s is the install command, %2$s is the build command, %3$s is the watch command. */
esc_html__( 'WooCommerce Blocks development mode requires files to be built. From the plugin directory, run %1$s to install dependencies, %2$s to build the files or %3$s to build the files and watch for changes.', 'woo-gutenberg-products-block' ),
'<code>npm install</code>',
'<code>npm run build</code>',
'<code>npm start</code>'
);
echo '</p></div>';
}
);
}
/**
* Define the global feature flag.
*/
protected function define_feature_flag() {
$allowed_flags = [ 'experimental', 'stable' ];
$flag = getenv( 'WOOCOMMERCE_BLOCKS_PHASE' );
if ( ! in_array( $flag, $allowed_flags, true ) ) {
if ( file_exists( __DIR__ . '/../../blocks.ini' ) ) {
$woo_options = parse_ini_file( __DIR__ . '/../../blocks.ini' );
$flag = is_array( $woo_options ) && 'experimental' === $woo_options['woocommerce_blocks_phase'] ? 'experimental' : 'stable';
} else {
$flag = 'stable';
}
}
define( 'WOOCOMMERCE_BLOCKS_PHASE', $flag );
}
/**
* Register core dependencies with the container.
*/
protected function register_dependencies() {
$this->container->register( $this->container->register(
AssetApi::class, AssetApi::class,
function ( Container $container ) { function ( Container $container ) {
@ -97,108 +168,28 @@ class Bootstrap {
} }
); );
$this->container->register( $this->container->register(
PaymentMethodAssets::class, PaymentsApi::class,
function( Container $container ) { function ( Container $container ) {
$payment_method_registry = $container->get( PaymentMethodRegistry::class ); $payment_method_registry = $container->get( PaymentMethodRegistry::class );
$asset_data_registry = $container->get( AssetDataRegistry::class ); $asset_data_registry = $container->get( AssetDataRegistry::class );
return new PaymentMethodAssets( $payment_method_registry, $asset_data_registry ); return new PaymentsApi( $payment_method_registry, $asset_data_registry );
} }
); );
$this->container->register(
// load AssetDataRegistry. RestApi::class,
$this->container->get( AssetDataRegistry::class ); function ( Container $container ) {
return new RestApi();
// load PaymentMethodAssets.
$this->container->get( PaymentMethodAssets::class );
$this->load_payment_method_integrations();
Library::init();
OldAssets::init();
RestApi::init();
}
/**
* Check dependencies exist.
*
* @return boolean
*/
protected function has_dependencies() {
return class_exists( 'WooCommerce' ) && function_exists( 'register_block_type' );
}
/**
* See if files have been built or not.
*
* @return bool
*/
protected function is_built() {
return file_exists(
$this->package->get_path( 'build/featured-product.js' )
);
}
/**
* Add a notice stating that the build has not been done yet.
*/
protected function add_build_notice() {
add_action(
'admin_notices',
function() {
echo '<div class="error"><p>';
printf(
/* Translators: %1$s is the install command, %2$s is the build command, %3$s is the watch command. */
esc_html__( 'WooCommerce Blocks development mode requires files to be built. From the plugin directory, run %1$s to install dependencies, %2$s to build the files or %3$s to build the files and watch for changes.', 'woo-gutenberg-products-block' ),
'<code>npm install</code>',
'<code>npm run build</code>',
'<code>npm start</code>'
);
echo '</p></div>';
} }
); );
} }
/** /**
* Remove core blocks. * Register payment method integrations with the container.
* *
* Older installs of WooCommerce (3.6 and below) did not use the blocks package and instead included classes directly. * @internal Stripe is a temporary method that is used for setting up payment method integrations with Cart and
* This code disables those core classes when running blocks as a feature plugin. Newer versions which use the Blocks package are unaffected. * Checkout blocks. This logic should get moved to the payment gateway extensions.
*
* When the feature plugin supports only WooCommerce 3.7+ this method can be removed.
*/ */
protected function remove_core_blocks() { protected function register_payment_methods() {
remove_action( 'init', array( 'WC_Block_Library', 'init' ) );
remove_action( 'init', array( 'WC_Block_Library', 'register_blocks' ) );
remove_action( 'init', array( 'WC_Block_Library', 'register_assets' ) );
remove_filter( 'block_categories', array( 'WC_Block_Library', 'add_block_category' ) );
remove_action( 'admin_print_footer_scripts', array( 'WC_Block_Library', 'print_script_settings' ), 1 );
remove_action( 'init', array( 'WGPB_Block_Library', 'init' ) );
}
/**
* Define the global feature flag
*/
protected function define_feature_flag() {
$allowed_flags = [ 'experimental', 'stable' ];
$flag = getenv( 'WOOCOMMERCE_BLOCKS_PHASE' );
if ( ! in_array( $flag, $allowed_flags, true ) ) {
if ( file_exists( __DIR__ . '/../../blocks.ini' ) ) {
$woo_options = parse_ini_file( __DIR__ . '/../../blocks.ini' );
$flag = is_array( $woo_options ) && 'experimental' === $woo_options['woocommerce_blocks_phase'] ? 'experimental' : 'stable';
} else {
$flag = 'stable';
}
}
define( 'WOOCOMMERCE_BLOCKS_PHASE', $flag );
}
/**
* This is a temporary method that is used for setting up payment method
* integrations with Cart and Checkout blocks. This logic should get moved
* to the payment gateway extensions.
*/
protected function load_payment_method_integrations() {
// stripe registration.
$this->container->register( $this->container->register(
Stripe::class, Stripe::class,
function( Container $container ) { function( Container $container ) {
@ -206,7 +197,6 @@ class Bootstrap {
return new Stripe( $asset_api ); return new Stripe( $asset_api );
} }
); );
// cheque registration.
$this->container->register( $this->container->register(
Cheque::class, Cheque::class,
function( Container $container ) { function( Container $container ) {
@ -214,19 +204,5 @@ class Bootstrap {
return new Cheque( $asset_api ); return new Cheque( $asset_api );
} }
); );
add_action(
'woocommerce_blocks_payment_method_type_registration',
function( $payment_method_registry ) {
// This is temporarily registering Stripe until it's moved to the extension.
if ( class_exists( 'WC_Stripe' ) && ! $payment_method_registry->is_registered( 'stripe' ) ) {
$payment_method_registry->register(
$this->container->get( Stripe::class )
);
}
$payment_method_registry->register(
$this->container->get( Cheque::class )
);
}
);
} }
} }

View File

@ -9,8 +9,6 @@ namespace Automattic\WooCommerce\Blocks;
defined( 'ABSPATH' ) || exit; defined( 'ABSPATH' ) || exit;
use Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry;
/** /**
* Library class. * Library class.
*/ */
@ -21,7 +19,6 @@ class Library {
*/ */
public static function init() { public static function init() {
add_action( 'init', array( __CLASS__, 'register_blocks' ) ); add_action( 'init', array( __CLASS__, 'register_blocks' ) );
add_action( 'init', array( __CLASS__, 'register_payment_methods' ) );
add_action( 'init', array( __CLASS__, 'define_tables' ) ); add_action( 'init', array( __CLASS__, 'define_tables' ) );
add_action( 'init', array( __CLASS__, 'maybe_create_tables' ) ); add_action( 'init', array( __CLASS__, 'maybe_create_tables' ) );
add_action( 'init', array( __CLASS__, 'maybe_create_cronjobs' ) ); add_action( 'init', array( __CLASS__, 'maybe_create_cronjobs' ) );
@ -133,13 +130,6 @@ class Library {
} }
} }
/**
* Register payment methods.
*/
public static function register_payment_methods() {
Package::container()->get( PaymentMethodRegistry::class )->initialize();
}
/** /**
* Register custom order status for orders created via the API during checkout. * Register custom order status for orders created via the API during checkout.
* *

View File

@ -0,0 +1,155 @@
<?php
/**
* Payment Api class.
*
* @package WooCommerce/Blocks
*/
namespace Automattic\WooCommerce\Blocks\Payments;
defined( 'ABSPATH' ) || exit;
use Automattic\WooCommerce\Blocks\Package;
use Automattic\WooCommerce\Blocks\Assets\AssetDataRegistry;
use Automattic\WooCommerce\Blocks\StoreApi\Utilities\NoticeHandler;
use Automattic\WooCommerce\Blocks\Payments\Integrations\Stripe;
use Automattic\WooCommerce\Blocks\Payments\Integrations\Cheque;
/**
* The Api class provides an interface to payment method registration.
*
* @since $VID:$
*/
class Api {
/**
* Reference to the PaymentMethodRegistry instance.
*
* @var PaymentMethodRegistry
*/
private $payment_method_registry;
/**
* Reference to the AssetDataRegistry instance.
*
* @var AssetDataRegistry
*/
private $asset_registry;
/**
* Constructor
*
* @param PaymentMethodRegistry $payment_method_registry An instance of Payment Method Registry.
* @param AssetDataRegistry $asset_registry Used for registering data to pass along to the request.
*/
public function __construct( PaymentMethodRegistry $payment_method_registry, AssetDataRegistry $asset_registry ) {
$this->payment_method_registry = $payment_method_registry;
$this->asset_registry = $asset_registry;
$this->init();
}
/**
* Initialize class features.
*/
protected function init() {
add_action( 'init', array( $this->payment_method_registry, 'initialize' ) );
add_filter( 'woocommerce_blocks_register_script_dependencies', array( $this, 'add_payment_method_script_dependencies' ), 10, 2 );
add_action( 'woocommerce_blocks_checkout_enqueue_data', array( $this, 'add_payment_method_script_data' ) );
add_action( 'woocommerce_blocks_payment_method_type_registration', array( $this, 'register_payment_method_integrations' ) );
add_action( 'woocommerce_rest_checkout_process_payment_with_context', array( $this, 'process_legacy_payment' ), 999, 2 );
}
/**
* Add payment method script handles as script dependencies.
*
* @param array $dependencies Array of script dependencies.
* @param string $handle Script handle.
* @return array
*/
public function add_payment_method_script_dependencies( $dependencies, $handle ) {
if ( ! in_array( $handle, [ 'wc-checkout-block', 'wc-checkout-block-frontend' ], true ) ) {
return $dependencies;
}
return array_merge( $dependencies, $this->payment_method_registry->get_all_registered_script_handles() );
}
/**
* Add payment method data to Asset Registry.
*/
public function add_payment_method_script_data() {
$script_data = $this->payment_method_registry->get_all_registered_script_data();
foreach ( $script_data as $asset_data_key => $asset_data_value ) {
if ( ! $this->asset_registry->exists( $asset_data_key ) ) {
$this->asset_registry->add( $asset_data_key, $asset_data_value );
}
}
}
/**
* Register payment method integrations bundled with blocks.
*
* @param PaymentMethodRegistry $payment_method_registry Payment method registry instance.
*/
public function register_payment_method_integrations( PaymentMethodRegistry $payment_method_registry ) {
// This is temporarily registering Stripe until it's moved to the extension.
if ( class_exists( '\WC_Stripe' ) && ! $payment_method_registry->is_registered( 'stripe' ) ) {
$payment_method_registry->register(
Package::container()->get( Stripe::class )
);
}
$payment_method_registry->register(
Package::container()->get( Cheque::class )
);
}
/**
* Attempt to process a payment for the checkout API if no payment methods support the
* woocommerce_rest_checkout_process_payment_with_context action.
*
* @param PaymentContext $context Holds context for the payment.
* @param PaymentResult $result Result of the payment.
*/
public function process_legacy_payment( PaymentContext $context, PaymentResult &$result ) {
if ( $result->status ) {
return;
}
// phpcs:ignore WordPress.Security.NonceVerification
$post_data = $_POST;
// Set constants.
wc_maybe_define_constant( 'WOOCOMMERCE_CHECKOUT', true );
// Add the payment data from the API to the POST global.
$_POST = $context->payment_data;
// Call the process payment method of the chosen gateway.
$payment_method_object = $context->get_payment_method_instance();
if ( ! $payment_method_object instanceof \WC_Payment_Gateway ) {
return;
}
$payment_method_object->validate_fields();
// If errors were thrown, we need to abort.
NoticeHandler::convert_notices_to_exceptions( 'woocommerce_rest_payment_error' );
// Process Payment.
$gateway_result = $payment_method_object->process_payment( $context->order->get_id() );
// Restore $_POST data.
$_POST = $post_data;
// If `process_payment` added notices, clear them. Notices are not displayed from the API -- payment should fail,
// and a generic notice will be shown instead if payment failed.
wc_clear_notices();
// Handle result.
$result->set_status( isset( $gateway_result['result'] ) && 'success' === $gateway_result['result'] ? 'success' : 'failure' );
// set payment_details from result.
$result->set_payment_details( array_merge( $result->payment_details, $gateway_result ) );
$result->set_redirect_url( $gateway_result['redirect'] );
}
}

View File

@ -115,4 +115,53 @@ final class PaymentMethodRegistry {
public function is_registered( $name ) { public function is_registered( $name ) {
return isset( $this->registered_payment_methods[ $name ] ); return isset( $this->registered_payment_methods[ $name ] );
} }
/**
* Retrieves all registered payment methods that are also active.
*
* @return PaymentMethodTypeInterface[]
*/
public function get_all_active_registered() {
return array_filter(
$this->get_all_registered(),
function( $payment_method ) {
return $payment_method->is_active();
}
);
}
/**
* Gets an array of all registered payment method script handles.
*
* @return string[]
*/
public function get_all_registered_script_handles() {
$script_handles = [];
$payment_methods = $this->get_all_active_registered();
foreach ( $payment_methods as $payment_method ) {
$script_handles = array_merge(
$script_handles,
is_admin() ? $payment_method->get_payment_method_script_handles_for_admin() : $payment_method->get_payment_method_script_handles()
);
}
return array_unique( array_filter( $script_handles ) );
}
/**
* Gets an array of all registered payment method script data.
*
* @return array
*/
public function get_all_registered_script_data() {
$script_data = [];
$payment_methods = $this->get_all_active_registered();
foreach ( $payment_methods as $payment_method ) {
$script_data[ $payment_method->get_name() . '_data' ] = $payment_method->get_payment_method_data();
}
return array_filter( $script_data );
}
} }

View File

@ -11,30 +11,30 @@ defined( 'ABSPATH' ) || exit;
use Automattic\WooCommerce\Blocks\StoreApi\RoutesController; use Automattic\WooCommerce\Blocks\StoreApi\RoutesController;
use Automattic\WooCommerce\Blocks\StoreApi\SchemaController; use Automattic\WooCommerce\Blocks\StoreApi\SchemaController;
use Automattic\WooCommerce\Blocks\Payments\PaymentResult;
use Automattic\WooCommerce\Blocks\Payments\PaymentContext;
use Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry;
use Automattic\WooCommerce\Blocks\StoreApi\Utilities\NoticeHandler;
/** /**
* RestApi class. * RestApi class.
*/ */
class RestApi { class RestApi {
/**
* Constructor
*/
public function __construct() {
$this->init();
}
/** /**
* Initialize class features. * Initialize class features.
*/ */
public static function init() { protected function init() {
add_action( 'rest_api_init', array( __CLASS__, 'register_rest_routes' ), 10 ); add_action( 'rest_api_init', array( $this, 'register_rest_routes' ), 10 );
add_filter( 'rest_authentication_errors', array( __CLASS__, 'store_api_authentication' ) ); add_filter( 'rest_authentication_errors', array( $this, 'store_api_authentication' ) );
add_action( 'woocommerce_rest_checkout_process_payment_with_context', array( __CLASS__, 'process_legacy_payment' ), 999, 2 );
} }
/** /**
* Register REST API routes. * Register REST API routes.
*/ */
public static function register_rest_routes() { public function register_rest_routes() {
// Init the Store API.
$schemas = new SchemaController(); $schemas = new SchemaController();
$routes = new RoutesController( $schemas ); $routes = new RoutesController( $schemas );
$routes->register_routes(); $routes->register_routes();
@ -46,7 +46,7 @@ class RestApi {
* @param string $namespace Namespace to retrieve. * @param string $namespace Namespace to retrieve.
* @return array|null * @return array|null
*/ */
public static function get_routes_from_namespace( $namespace ) { public function get_routes_from_namespace( $namespace ) {
$rest_server = rest_get_server(); $rest_server = rest_get_server();
$namespace_index = $rest_server->get_namespace_index( $namespace_index = $rest_server->get_namespace_index(
[ [
@ -60,12 +60,26 @@ class RestApi {
return isset( $response_data['routes'] ) ? $response_data['routes'] : null; return isset( $response_data['routes'] ) ? $response_data['routes'] : null;
} }
/**
* The Store API does not require authentication.
*
* @param \WP_Error|mixed $result Error from another authentication handler, null if we should handle it, or another value if not.
* @return \WP_Error|null|bool
*/
public function store_api_authentication( $result ) {
// Pass through errors from other authentication methods used before this one.
if ( ! empty( $result ) || ! self::is_request_to_store_api() ) {
return $result;
}
return true;
}
/** /**
* Check if is request to the Store API. * Check if is request to the Store API.
* *
* @return bool * @return bool
*/ */
protected static function is_request_to_store_api() { protected function is_request_to_store_api() {
if ( empty( $_SERVER['REQUEST_URI'] ) ) { if ( empty( $_SERVER['REQUEST_URI'] ) ) {
return false; return false;
} }
@ -75,69 +89,4 @@ class RestApi {
return false !== strpos( $request_uri, $rest_prefix . 'wc/store' ); return false !== strpos( $request_uri, $rest_prefix . 'wc/store' );
} }
/**
* The Store API does not require authentication.
*
* @param \WP_Error|mixed $result Error from another authentication handler, null if we should handle it, or another value if not.
* @return \WP_Error|null|bool
*/
public static function store_api_authentication( $result ) {
// Pass through errors from other authentication methods used before this one.
if ( ! empty( $result ) || ! self::is_request_to_store_api() ) {
return $result;
}
return true;
}
/**
* Attempt to process a payment for the checkout API if no payment methods support the
* woocommerce_rest_checkout_process_payment_with_context action.
*
* @param PaymentContext $context Holds context for the payment.
* @param PaymentResult $result Result of the payment.
*/
public static function process_legacy_payment( PaymentContext $context, PaymentResult &$result ) {
if ( $result->status ) {
return;
}
// phpcs:ignore WordPress.Security.NonceVerification
$post_data = $_POST;
// Set constants.
wc_maybe_define_constant( 'WOOCOMMERCE_CHECKOUT', true );
// Add the payment data from the API to the POST global.
$_POST = $context->payment_data;
// Call the process payment method of the chosen gatway.
$payment_method_object = $context->get_payment_method_instance();
if ( ! $payment_method_object instanceof \WC_Payment_Gateway ) {
return;
}
$payment_method_object->validate_fields();
// If errors were thrown, we need to abort.
NoticeHandler::convert_notices_to_exceptions( 'woocommerce_rest_payment_error' );
// Process Payment.
$gateway_result = $payment_method_object->process_payment( $context->order->get_id() );
// Restore $_POST data.
$_POST = $post_data;
// If `process_payment` added notices, clear them. Notices are not displayed from the API -- payment should fail,
// and a generic notice will be shown instead if payment failed.
wc_clear_notices();
// Handle result.
$result->set_status( isset( $gateway_result['result'] ) && 'success' === $gateway_result['result'] ? 'success' : 'failure' );
// set payment_details from result.
$result->set_payment_details( array_merge( $result->payment_details, $gateway_result ) );
$result->set_redirect_url( $gateway_result['redirect'] );
}
} }