Fix merge conflict

This commit is contained in:
dinamiko 2022-09-14 12:22:46 +02:00
commit e4e968a823
57 changed files with 6080 additions and 1624 deletions

View file

@ -0,0 +1,439 @@
<?php
/**
* The services of the Gateway module.
*
* @package WooCommerce\PayPalCommerce\WcGateway
*/
// phpcs:disable WordPress.Security.NonceVerification.Recommended
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\WcGateway;
use Psr\Container\ContainerInterface;
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
use WooCommerce\PayPalCommerce\Onboarding\Environment;
use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingOptionsRenderer;
use WooCommerce\PayPalCommerce\Onboarding\State;
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
return function ( ContainerInterface $container, array $fields ): array {
$state = $container->get( 'onboarding.state' );
assert( $state instanceof State );
$dcc_applies = $container->get( 'api.helpers.dccapplies' );
assert( $dcc_applies instanceof DccApplies );
$is_shop_supports_dcc = $dcc_applies->for_country_currency() || $dcc_applies->for_wc_payments();
$onboarding_options_renderer = $container->get( 'onboarding.render-options' );
assert( $onboarding_options_renderer instanceof OnboardingOptionsRenderer );
$module_url = $container->get( 'wcgateway.url' );
$connection_fields = array(
'ppcp_onboarading_header' => array(
'type' => 'ppcp-text',
'classes' => array( 'ppcp-onboarding-element' ),
'text' => '
<div class="ppcp-onboarding-header">
<div class="ppcp-onboarding-header-left">
<img alt="PayPal" src="' . esc_url( $module_url ) . 'assets/images/paypal.png"/>
<h2>The all-in-one checkout solution</h2>
</div>
<div class="ppcp-onboarding-header-right">
<div class="ppcp-onboarding-header-paypal-logos">
<img alt="PayPal" src="' . esc_url( $module_url ) . 'assets/images/paypal-button.svg"/>
<img alt="Venmo" src="' . esc_url( $module_url ) . 'assets/images/venmo.svg"/>
<img alt="Pay Later" src="' . esc_url( $module_url ) . 'assets/images/paylater.svg"/>
</div>
<div class="ppcp-onboarding-header-cards">
<img alt="Visa" src="' . esc_url( $module_url ) . 'assets/images/visa-dark.svg"/>
<img alt="Mastercard" src="' . esc_url( $module_url ) . 'assets/images/mastercard-dark.svg"/>
<img alt="American Express" src="' . esc_url( $module_url ) . 'assets/images/amex.svg"/>
<img alt="Discover" src="' . esc_url( $module_url ) . 'assets/images/discover.svg"/>
<img alt="iDEAL" src="' . esc_url( $module_url ) . 'assets/images/ideal-dark.svg"/>
<img alt="Sofort" src="' . esc_url( $module_url ) . 'assets/images/sofort.svg"/>
</div>
</div>
</div>',
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'credentials_production_heading' => array(
'heading' => __( 'API Credentials', 'woocommerce-paypal-payments' ),
'type' => 'ppcp-heading',
'screens' => array(
State::STATE_ONBOARDED,
),
'state_from' => Environment::PRODUCTION,
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'credentials_sandbox_heading' => array(
'heading' => __( 'Sandbox API Credentials', 'woocommerce-paypal-payments' ),
'type' => 'ppcp-heading',
'screens' => array(
State::STATE_ONBOARDED,
),
'state_from' => Environment::SANDBOX,
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
'description' => __( 'Your account is connected to sandbox, no real charging takes place. To accept live payments, turn off sandbox mode and connect your live PayPal account.', 'woocommerce-paypal-payments' ),
),
'ppcp_onboarading_options' => array(
'type' => 'ppcp-text',
'classes' => array( 'ppcp-onboarding-element' ),
'text' => $onboarding_options_renderer->render( $is_shop_supports_dcc ),
'raw' => true,
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
// We need to have a button for each option (ppcp, express)
// because currently the only documented way to use the PayPal onboarding JS library
// is to have the buttons before loading the script.
'ppcp_onboarding_production_ppcp' => array(
'type' => 'ppcp_onboarding',
'classes' => array( 'ppcp-onboarding-element' ),
'screens' => array(
State::STATE_START,
),
'state_from' => Environment::PRODUCTION,
'env' => Environment::PRODUCTION,
'products' => array( 'PPCP' ),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'ppcp_onboarding_production_express' => array(
'type' => 'ppcp_onboarding',
'classes' => array( 'ppcp-onboarding-element' ),
'screens' => array(
State::STATE_START,
),
'state_from' => Environment::PRODUCTION,
'env' => Environment::PRODUCTION,
'products' => array( 'EXPRESS_CHECKOUT' ),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'ppcp_onboarding_sandbox_ppcp' => array(
'type' => 'ppcp_onboarding',
'classes' => array( 'ppcp-onboarding-element' ),
'screens' => array(
State::STATE_START,
),
'state_from' => Environment::SANDBOX,
'env' => Environment::SANDBOX,
'products' => array( 'PPCP' ),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
'description' => __( 'Prior to accepting live payments, you can test payments on your WooCommerce platform in a safe PayPal sandbox environment.', 'woocommerce-paypal-payments' ),
),
'ppcp_onboarding_sandbox_express' => array(
'type' => 'ppcp_onboarding',
'classes' => array( 'ppcp-onboarding-element' ),
'screens' => array(
State::STATE_START,
),
'state_from' => Environment::SANDBOX,
'env' => Environment::SANDBOX,
'products' => array( 'EXPRESS_CHECKOUT' ),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
'description' => __( 'Prior to accepting live payments, you can test payments on your WooCommerce platform in a safe PayPal sandbox environment.', 'woocommerce-paypal-payments' ),
),
'ppcp_disconnect_production' => array(
'title' => __( 'Disconnect from PayPal', 'woocommerce-paypal-payments' ),
'type' => 'ppcp-text',
'text' => sprintf(
'<p>%1$s <span class="dashicons dashicons-yes"></span></p><p><button type="button" class="button ppcp-disconnect production">%2$s</button></p>',
esc_html__( 'Status: Connected', 'woocommerce-paypal-payments' ),
esc_html__( 'Disconnect Account', 'woocommerce-paypal-payments' )
),
'screens' => array(
State::STATE_ONBOARDED,
),
'state_from' => Environment::PRODUCTION,
'env' => Environment::PRODUCTION,
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
'description' => __( 'Click to reset current credentials and use another account.', 'woocommerce-paypal-payments' ),
),
'ppcp_disconnect_sandbox' => array(
'title' => __( 'Disconnect from PayPal Sandbox', 'woocommerce-paypal-payments' ),
'type' => 'ppcp-text',
'text' => sprintf(
'<p>%1$s <span class="dashicons dashicons-yes"></span></p><p><button type="button" class="button ppcp-disconnect sandbox">%2$s</button></p>',
esc_html__( 'Status: Connected', 'woocommerce-paypal-payments' ),
esc_html__( 'Disconnect Account', 'woocommerce-paypal-payments' )
),
'screens' => array(
State::STATE_ONBOARDED,
),
'state_from' => Environment::SANDBOX,
'env' => Environment::SANDBOX,
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
'description' => __( 'Click to reset current credentials and use another account.', 'woocommerce-paypal-payments' ),
),
'toggle_manual_input' => array(
'type' => 'ppcp-text',
'text' => '<button type="button" id="ppcp[toggle_manual_input]">' . __( 'Toggle to manual credential input', 'woocommerce-paypal-payments' ) . '</button>',
'classes' => array( 'ppcp-onboarding-element' ),
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'error_label' => array(
'type' => 'ppcp-text',
'text' => '<label class="error" id="ppcp-form-errors-label"></label>',
'classes' => array( 'hide', 'ppcp-always-shown-element' ),
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'sandbox_on' => array(
'title' => __( 'Sandbox', 'woocommerce-paypal-payments' ),
'classes' => array( 'ppcp-onboarding-element', 'ppcp-always-shown-element' ),
'type' => 'checkbox',
'label' => __( 'To test your WooCommerce installation, you can use the sandbox mode.', 'woocommerce-paypal-payments' ),
'default' => 0,
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'merchant_email_production' => array(
'title' => __( 'Live Email address', 'woocommerce-paypal-payments' ),
'classes' => array( State::STATE_ONBOARDED === $state->production_state() ? 'onboarded' : '', 'ppcp-always-shown-element' ),
'type' => 'text',
'required' => true,
'desc_tip' => true,
'description' => __( 'The email address of your PayPal account.', 'woocommerce-paypal-payments' ),
'default' => '',
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'merchant_id_production' => array(
'title' => __( 'Live Merchant Id', 'woocommerce-paypal-payments' ),
'classes' => array( State::STATE_ONBOARDED === $state->production_state() ? 'onboarded' : '', 'ppcp-always-shown-element' ),
'type' => 'ppcp-text-input',
'desc_tip' => true,
'description' => __( 'The merchant id of your account ', 'woocommerce-paypal-payments' ),
'default' => false,
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'client_id_production' => array(
'title' => __( 'Live Client Id', 'woocommerce-paypal-payments' ),
'classes' => array( State::STATE_ONBOARDED === $state->production_state() ? 'onboarded' : '', 'ppcp-always-shown-element' ),
'type' => 'ppcp-text-input',
'desc_tip' => true,
'description' => __( 'The client id of your api ', 'woocommerce-paypal-payments' ),
'default' => false,
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'client_secret_production' => array(
'title' => __( 'Live Secret Key', 'woocommerce-paypal-payments' ),
'classes' => array( State::STATE_ONBOARDED === $state->production_state() ? 'onboarded' : '', 'ppcp-always-shown-element' ),
'type' => 'ppcp-password',
'desc_tip' => true,
'description' => __( 'The secret key of your api', 'woocommerce-paypal-payments' ),
'default' => false,
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'merchant_email_sandbox' => array(
'title' => __( 'Sandbox Email address', 'woocommerce-paypal-payments' ),
'classes' => array( State::STATE_ONBOARDED === $state->sandbox_state() ? 'onboarded' : '', 'ppcp-always-shown-element' ),
'type' => 'text',
'required' => true,
'desc_tip' => true,
'description' => __( 'The email address of your PayPal account.', 'woocommerce-paypal-payments' ),
'default' => '',
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'merchant_id_sandbox' => array(
'title' => __( 'Sandbox Merchant Id', 'woocommerce-paypal-payments' ),
'classes' => array( State::STATE_ONBOARDED === $state->sandbox_state() ? 'onboarded' : '', 'ppcp-always-shown-element' ),
'type' => 'ppcp-text-input',
'desc_tip' => true,
'description' => __( 'The merchant id of your account ', 'woocommerce-paypal-payments' ),
'default' => false,
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'client_id_sandbox' => array(
'title' => __( 'Sandbox Client Id', 'woocommerce-paypal-payments' ),
'classes' => array( State::STATE_ONBOARDED === $state->sandbox_state() ? 'onboarded' : '', 'ppcp-always-shown-element' ),
'type' => 'ppcp-text-input',
'desc_tip' => true,
'description' => __( 'The client id of your api ', 'woocommerce-paypal-payments' ),
'default' => false,
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'client_secret_sandbox' => array(
'title' => __( 'Sandbox Secret Key', 'woocommerce-paypal-payments' ),
'classes' => array( State::STATE_ONBOARDED === $state->sandbox_state() ? 'onboarded' : '', 'ppcp-always-shown-element' ),
'type' => 'ppcp-password',
'desc_tip' => true,
'description' => __( 'The secret key of your api', 'woocommerce-paypal-payments' ),
'default' => false,
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'credentials_feature_onboarding_heading' => array(
'heading' => __( 'Feature Onboarding', 'woocommerce-paypal-payments' ),
'type' => 'ppcp-heading',
'screens' => array(
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
'description' => __( 'See which features are available.', 'woocommerce-paypal-payments' ),
),
'ppcp_dcc_status' => array(
'title' => __( 'Advanced Credit and Debit Card Payments', 'woocommerce-paypal-payments' ),
'type' => 'ppcp-text',
'text' => $container->get( 'wcgateway.settings.connection.dcc-status-text' ),
'screens' => array(
State::STATE_ONBOARDED,
),
'requirements' => array( 'dcc' ),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'ppcp_pui_status' => array(
'title' => __( 'Pay Upon Invoice', 'woocommerce-paypal-payments' ),
'type' => 'ppcp-text',
'text' => $container->get( 'wcgateway.settings.connection.pui-status-text' ),
'screens' => array(
State::STATE_ONBOARDED,
),
'requirements' => array( 'pui_ready' ),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'tracking_enabled' => array(
'title' => __( 'Tracking', 'woocommerce-paypal-payments' ),
'type' => 'checkbox',
'desc_tip' => true,
'label' => $container->get( 'wcgateway.settings.tracking-label' ),
'description' => __( 'Allows to send shipment tracking numbers to PayPal for PayPal transactions.', 'woocommerce-paypal-payments' ),
'default' => false,
'screens' => array(
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
'input_class' => $container->get( 'wcgateway.settings.should-disable-tracking-checkbox' ) ? array( 'ppcp-disabled-checkbox' ) : array(),
),
'credentials_integration_configuration_heading' => array(
'heading' => __( 'Integration configuration', 'woocommerce-paypal-payments' ),
'type' => 'ppcp-heading',
'screens' => array(
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
'description' => __( 'See which features are available.', 'woocommerce-paypal-payments' ),
),
'prefix' => array(
'title' => __( 'Invoice prefix', 'woocommerce-paypal-payments' ),
'type' => 'text',
'desc_tip' => true,
'description' => __( 'If you use your PayPal account with more than one installation, please use a distinct prefix to separate those installations. Please use only English letters and "-", "_" characters.', 'woocommerce-paypal-payments' ),
'maxlength' => 15,
'custom_attributes' => array(
'pattern' => '[a-zA-Z_-]+',
),
'default' => ( static function (): string {
$site_url = get_site_url( get_current_blog_id() );
$hash = md5( $site_url );
$letters = preg_replace( '~\d~', '', $hash ) ?? '';
$prefix = substr( $letters, 0, 6 );
return $prefix ? $prefix . '-' : '';
} )(),
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
'logging_enabled' => array(
'title' => __( 'Logging', 'woocommerce-paypal-payments' ),
'type' => 'checkbox',
'desc_tip' => true,
'label' => __( 'Enable logging. ', 'woocommerce-paypal-payments' ) .
' <a href="' . admin_url( 'admin.php?page=wc-status&tab=logs' ) . '">' . __( 'View logs', 'woocommerce-paypal-payments' ) . '</a>',
'description' => __( 'Enable logging of unexpected behavior. This can also log private data and should only be enabled in a development or stage environment.', 'woocommerce-paypal-payments' ),
'default' => false,
'screens' => array(
State::STATE_START,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => Settings::CONNECTION_TAB_ID,
),
);
return array_merge( $fields, $connection_fields );
};

View file

@ -98,4 +98,6 @@ return array(
$source
);
},
'wcgateway.settings.fields' => require __DIR__ . '/connection-tab-settings.php',
);

File diff suppressed because it is too large Load diff

View file

@ -88,9 +88,12 @@ class DisableGateways {
* @return bool
*/
private function disable_all_gateways() : bool {
if ( ! $this->settings->has( 'enabled' ) || ! $this->settings->get( 'enabled' ) ) {
return true;
foreach ( WC()->payment_gateways->payment_gateways() as $gateway ) {
if ( PayPalGateway::ID === $gateway->id && $gateway->enabled !== 'yes' ) {
return true;
}
}
if ( ! $this->settings->has( 'merchant_email' ) || ! is_email( $this->settings->get( 'merchant_email' ) ) ) {
return true;
}

View file

@ -26,6 +26,7 @@ use WooCommerce\PayPalCommerce\WcGateway\FundingSource\FundingSourceRenderer;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayUponInvoice\PayUponInvoiceGateway;
use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderProcessor;
use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor;
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
use WooCommerce\PayPalCommerce\WcGateway\Settings\SettingsRenderer;
use Psr\Container\ContainerInterface;
use WooCommerce\PayPalCommerce\Webhooks\Status\WebhooksStatusPage;
@ -290,6 +291,9 @@ class PayPalGateway extends \WC_Payment_Gateway {
* @return string
*/
private function define_method_title(): string {
if ( $this->is_connection_tab() ) {
return __( 'Account Setup', 'woocommerce-paypal-payments' );
}
if ( $this->is_credit_card_tab() ) {
return __( 'PayPal Card Processing', 'woocommerce-paypal-payments' );
}
@ -312,6 +316,10 @@ class PayPalGateway extends \WC_Payment_Gateway {
* @return string
*/
private function define_method_description(): string {
if ( $this->is_connection_tab() ) {
return '';
}
if ( $this->is_credit_card_tab() ) {
return __(
'Accept debit and credit cards, and local payment methods.',
@ -374,6 +382,16 @@ class PayPalGateway extends \WC_Payment_Gateway {
&& WebhooksStatusPage::ID === $this->page_id;
}
/**
* Whether we are on the connection tab.
*
* @return bool true if is connection tab, otherwise false
*/
protected function is_connection_tab() : bool {
return is_admin()
&& Settings::CONNECTION_TAB_ID === $this->page_id;
}
/**
* Whether we are on the PayPal settings tab.
*

View file

@ -226,7 +226,7 @@ class PayUponInvoiceGateway extends WC_Payment_Gateway {
$payment_source = $this->payment_source_factory->from_wc_order( $wc_order, $birth_date );
try {
$order = $this->order_endpoint->create( array( $purchase_unit ), $payment_source );
$order = $this->order_endpoint->create( array( $purchase_unit ), $payment_source, $wc_order );
$this->add_paypal_meta( $wc_order, $order, $this->environment );
as_schedule_single_action(

View file

@ -9,9 +9,9 @@ declare( strict_types=1 );
namespace WooCommerce\PayPalCommerce\WcGateway\Helper;
use Throwable;
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnersEndpoint;
use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatusProduct;
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
/**
@ -22,7 +22,7 @@ class DCCProductStatus {
/**
* Caches the status for the current load.
*
* @var string|null
* @var bool|null
*/
private $current_status_cache;
/**
@ -57,12 +57,12 @@ class DCCProductStatus {
* Whether the active/subscribed products support DCC.
*
* @return bool
* @throws \WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException Should a setting not be found.
*/
public function dcc_is_active() : bool {
if ( is_bool( $this->current_status_cache ) ) {
return $this->current_status_cache;
}
if ( $this->settings->has( 'products_dcc_enabled' ) && $this->settings->get( 'products_dcc_enabled' ) ) {
$this->current_status_cache = true;
return true;
@ -70,7 +70,7 @@ class DCCProductStatus {
try {
$seller_status = $this->partners_endpoint->seller_status();
} catch ( RuntimeException $error ) {
} catch ( Throwable $error ) {
$this->current_status_cache = false;
return false;
}

View file

@ -10,6 +10,8 @@ declare( strict_types=1 );
namespace WooCommerce\PayPalCommerce\WcGateway\Helper;
use WC_Order;
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
/**
* Class PayUponInvoiceHelper
@ -23,13 +25,23 @@ class PayUponInvoiceHelper {
*/
protected $checkout_helper;
/**
* The settings.
*
* @var Settings
*/
protected $settings;
/**
* PayUponInvoiceHelper constructor.
*
* @param CheckoutHelper $checkout_helper The checkout helper.
* @param Settings $settings The Settings.
*/
public function __construct( CheckoutHelper $checkout_helper ) {
public function __construct( CheckoutHelper $checkout_helper, Settings $settings ) {
$this->checkout_helper = $checkout_helper;
$this->settings = $settings;
}
/**
@ -78,4 +90,14 @@ class PayUponInvoiceHelper {
return false;
}
/**
* Checks whether PUI is enabled.
*
* @return bool True if PUI is active, otherwise false.
* @throws NotFoundException If problem when checking the settings.
*/
public function is_pui_enabled(): bool {
return $this->settings->has( 'products_pui_enabled' ) && $this->settings->get( 'products_pui_enabled' );
}
}

View file

@ -9,11 +9,10 @@ declare( strict_types=1 );
namespace WooCommerce\PayPalCommerce\WcGateway\Helper;
use Throwable;
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnersEndpoint;
use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatusProduct;
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
/**
* Class PayUponInvoiceProductStatus
@ -70,7 +69,7 @@ class PayUponInvoiceProductStatus {
try {
$seller_status = $this->partners_endpoint->seller_status();
} catch ( RuntimeException $error ) {
} catch ( Throwable $error ) {
$this->current_status_cache = false;
return false;
}

View file

@ -0,0 +1,82 @@
<?php
/**
* Renders the settings page header.
*
* @package WooCommerce\PayPalCommerce\WcGateway\Settings
*/
declare( strict_types=1 );
namespace WooCommerce\PayPalCommerce\WcGateway\Settings;
/**
* Class HeaderRenderer
*/
class HeaderRenderer {
const KEY = 'ppcp-tab';
/**
* ID of the current PPCP gateway settings page, or empty if it is not such page.
*
* @var string
*/
private $page_id;
/**
* The URL to the module.
*
* @var string
*/
private $module_url;
/**
* HeaderRenderer constructor.
*
* @param string $page_id ID of the current PPCP gateway settings page, or empty if it is not such page.
* @param string $module_url The URL to the module.
*/
public function __construct( string $page_id, string $module_url ) {
$this->page_id = $page_id;
$this->module_url = $module_url;
}
/**
* Whether the sections tab should be rendered.
*
* @return bool
*/
public function should_render() : bool {
return ! empty( $this->page_id );
}
/**
* Renders the Sections tab.
*/
public function render(): string {
if ( ! $this->should_render() ) {
return '';
}
return '
<div class="ppcp-settings-page-header">
<img alt="PayPal" src="' . esc_url( $this->module_url ) . 'assets/images/paypal.png"/>
<h4> <span class="ppcp-inline-only">-</span> ' . __( 'The all-in-one checkout solution for WooCommerce', 'woocommerce-paypal-payments' ) . '</h4>
<a class="button" target="_blank" href="https://woocommerce.com/document/woocommerce-paypal-payments/">'
. __( 'Documentation', 'woocommerce-paypal-payments' ) .
'</a>
<a class="button" target="_blank" href="https://woocommerce.com/document/woocommerce-paypal-payments/#get-help">'
. __( 'Get Help', 'woocommerce-paypal-payments' ) .
'</a>
<span class="ppcp-right-align">
<a target="_blank" href="https://woocommerce.com/feature-requests/woocommerce-paypal-payments/">'
. __( 'Request a feature', 'woocommerce-paypal-payments' ) .
'</a>
<a target="_blank" href="https://github.com/woocommerce/woocommerce-paypal-payments/issues/new?assignees=&labels=type%3A+bug&template=bug_report.md">'
. __( 'Submit a bug', 'woocommerce-paypal-payments' ) .
'</a>
</span>
</div>
';
}
}

View file

@ -33,10 +33,11 @@ trait PageMatcherTrait {
}
$gateway_page_id_map = array(
PayPalGateway::ID => 'paypal',
CreditCardGateway::ID => 'dcc', // TODO: consider using just the gateway ID for PayPal and DCC too.
CardButtonGateway::ID => CardButtonGateway::ID,
WebhooksStatusPage::ID => WebhooksStatusPage::ID,
Settings::CONNECTION_TAB_ID => Settings::CONNECTION_TAB_ID,
PayPalGateway::ID => 'paypal',
CreditCardGateway::ID => 'dcc', // TODO: consider using just the gateway ID for PayPal and DCC too.
CardButtonGateway::ID => CardButtonGateway::ID,
WebhooksStatusPage::ID => WebhooksStatusPage::ID,
);
return array_key_exists( $current_page_id, $gateway_page_id_map )
&& in_array( $gateway_page_id_map[ $current_page_id ], $allowed_gateways, true );

View file

@ -9,6 +9,7 @@ declare( strict_types=1 );
namespace WooCommerce\PayPalCommerce\WcGateway\Settings;
use WooCommerce\PayPalCommerce\Onboarding\State;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
use WooCommerce\PayPalCommerce\Webhooks\Status\WebhooksStatusPage;
@ -33,15 +34,24 @@ class SectionsRenderer {
*/
protected $sections;
/**
* The onboarding state.
*
* @var State
*/
private $state;
/**
* SectionsRenderer constructor.
*
* @param string $page_id ID of the current PPCP gateway settings page, or empty if it is not such page.
* @param array<string, string> $sections Key - page/gateway ID, value - displayed text.
* @param State $state The onboarding state.
*/
public function __construct( string $page_id, array $sections ) {
public function __construct( string $page_id, array $sections, State $state ) {
$this->page_id = $page_id;
$this->sections = $sections;
$this->state = $state;
}
/**
@ -50,7 +60,9 @@ class SectionsRenderer {
* @return bool
*/
public function should_render() : bool {
return ! empty( $this->page_id );
return ! empty( $this->page_id ) &&
( $this->state->production_state() === State::STATE_ONBOARDED ||
$this->state->sandbox_state() === State::STATE_ONBOARDED );
}
/**
@ -65,7 +77,7 @@ class SectionsRenderer {
foreach ( $this->sections as $id => $label ) {
$url = admin_url( 'admin.php?page=wc-settings&tab=checkout&section=' . $id );
if ( in_array( $id, array( CreditCardGateway::ID, WebhooksStatusPage::ID ), true ) ) {
if ( in_array( $id, array( Settings::CONNECTION_TAB_ID, CreditCardGateway::ID, WebhooksStatusPage::ID ), true ) ) {
// We need section=ppcp-gateway for the webhooks page because it is not a gateway,
// and for DCC because otherwise it will not render the page if gateway is not available (country/currency).
// Other gateways render fields differently, and their pages are not expected to work when gateway is not available.

View file

@ -17,7 +17,8 @@ use Psr\Container\ContainerInterface;
*/
class Settings implements ContainerInterface {
const KEY = 'woocommerce-ppcp-settings';
const KEY = 'woocommerce-ppcp-settings';
const CONNECTION_TAB_ID = 'ppcp-connection';
/**
* The settings.

View file

@ -174,7 +174,7 @@ class SettingsListener {
/**
* The URL opened at the end of onboarding after saving the merchant ID/email.
*/
$redirect_url = apply_filters( 'woocommerce_paypal_payments_onboarding_redirect_url', admin_url( 'admin.php?page=wc-settings&tab=checkout&section=ppcp-gateway' ) );
$redirect_url = apply_filters( 'woocommerce_paypal_payments_onboarding_redirect_url', admin_url( 'admin.php?page=wc-settings&tab=checkout&section=ppcp-gateway&ppcp-tab=ppcp-connection' ) );
if ( ! $this->settings->has( 'client_id' ) || ! $this->settings->get( 'client_id' ) ) {
$redirect_url = add_query_arg( 'ppcp-onboarding-error', '1', $redirect_url );
}
@ -235,7 +235,7 @@ class SettingsListener {
*
* @throws \WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException When a setting was not found.
*/
public function listen() {
public function listen(): void {
if ( ! $this->is_valid_update_request() ) {
return;
@ -259,7 +259,7 @@ class SettingsListener {
$credentials_change_status = null; // Cannot detect on Card Processing page.
if ( PayPalGateway::ID === $this->page_id ) {
if ( PayPalGateway::ID === $this->page_id || Settings::CONNECTION_TAB_ID === $this->page_id ) {
$settings['enabled'] = isset( $_POST['woocommerce_ppcp-gateway_enabled'] )
&& 1 === absint( $_POST['woocommerce_ppcp-gateway_enabled'] );
@ -267,7 +267,6 @@ class SettingsListener {
}
// phpcs:enable phpcs:disable WordPress.Security.NonceVerification.Missing
// phpcs:enable phpcs:disable WordPress.Security.NonceVerification.Missing
if ( $credentials_change_status ) {
if ( self::CREDENTIALS_UNCHANGED !== $credentials_change_status ) {
$this->settings->set( 'products_dcc_enabled', null );
@ -473,4 +472,36 @@ class SettingsListener {
}
return true;
}
/**
* Prevent enabling tracking if it is not enabled for merchant account.
*/
public function listen_for_tracking_enabled(): void {
if ( State::STATE_ONBOARDED !== $this->state->current_state() ) {
return;
}
try {
$token = $this->bearer->bearer();
if ( ! $token->is_tracking_available() ) {
$this->settings->set( 'tracking_enabled', false );
$this->settings->persist();
return;
}
} catch ( RuntimeException $exception ) {
$this->settings->set( 'tracking_enabled', false );
$this->settings->persist();
add_action(
'admin_notices',
function () use ( $exception ) {
printf(
'<div class="notice notice-error"><p>%1$s</p><p>%2$s</p></div>',
esc_html__( 'Authentication with PayPal failed: ', 'woocommerce-paypal-payments' ) . esc_attr( $exception->getMessage() ),
wp_kses_post( __( 'Please verify your API Credentials and try again to connect your PayPal business account. Visit the <a href="https://docs.woocommerce.com/document/woocommerce-paypal-payments/" target="_blank">plugin documentation</a> for more information about the setup.', 'woocommerce-paypal-payments' ) )
);
}
);
}
}
}

View file

@ -33,6 +33,13 @@ class SettingsRenderer {
*/
protected $settings_status;
/**
* The api shop country.
*
* @var string
*/
protected $api_shop_country;
/**
* The settings.
*
@ -93,6 +100,7 @@ class SettingsRenderer {
* @param DCCProductStatus $dcc_product_status The product status.
* @param SettingsStatus $settings_status The Settings status helper.
* @param string $page_id ID of the current PPCP gateway settings page, or empty if it is not such page.
* @param string $api_shop_country The api shop country.
*/
public function __construct(
ContainerInterface $settings,
@ -102,7 +110,8 @@ class SettingsRenderer {
MessagesApply $messages_apply,
DCCProductStatus $dcc_product_status,
SettingsStatus $settings_status,
string $page_id
string $page_id,
string $api_shop_country
) {
$this->settings = $settings;
@ -113,6 +122,7 @@ class SettingsRenderer {
$this->dcc_product_status = $dcc_product_status;
$this->settings_status = $settings_status;
$this->page_id = $page_id;
$this->api_shop_country = $api_shop_country;
}
/**
@ -348,7 +358,7 @@ $data_rows_html
/**
* Renders the settings.
*/
public function render() {
public function render(): void {
$is_dcc = CreditCardGateway::ID === $this->page_id;
//phpcs:enable WordPress.Security.NonceVerification.Recommended
@ -381,14 +391,14 @@ $data_rows_html
continue;
}
if (
in_array( 'dcc', $config['requirements'], true )
&& ! $this->dcc_product_status->dcc_is_active()
in_array( 'messages', $config['requirements'], true )
&& ! $this->messages_apply->for_country()
) {
continue;
}
if (
in_array( 'messages', $config['requirements'], true )
&& ! $this->messages_apply->for_country()
in_array( 'pui_ready', $config['requirements'], true )
&& $this->api_shop_country !== 'DE'
) {
continue;
}

View file

@ -17,6 +17,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\Capture;
use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus;
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
use WooCommerce\PayPalCommerce\ApiClient\Repository\PayPalRequestIdRepository;
use WooCommerce\PayPalCommerce\Onboarding\State;
use WooCommerce\PayPalCommerce\WcGateway\Admin\FeesRenderer;
use WooCommerce\PayPalCommerce\WcGateway\Admin\OrderTablePaymentStatusColumn;
use WooCommerce\PayPalCommerce\WcGateway\Admin\PaymentStatusOrderDetail;
@ -28,9 +29,12 @@ use WooCommerce\PayPalCommerce\WcGateway\Endpoint\ReturnUrlEndpoint;
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
use WooCommerce\PayPalCommerce\WcGateway\Helper\DCCProductStatus;
use WooCommerce\PayPalCommerce\WcGateway\Helper\PayUponInvoiceProductStatus;
use WooCommerce\PayPalCommerce\WcGateway\Notice\ConnectAdminNotice;
use WooCommerce\PayPalCommerce\WcGateway\Notice\GatewayWithoutPayPalAdminNotice;
use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor;
use WooCommerce\PayPalCommerce\WcGateway\Settings\HeaderRenderer;
use WooCommerce\PayPalCommerce\WcGateway\Settings\SectionsRenderer;
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
use WooCommerce\PayPalCommerce\WcGateway\Settings\SettingsListener;
@ -65,11 +69,14 @@ class WCGatewayModule implements ModuleInterface {
add_action(
'woocommerce_sections_checkout',
function() use ( $c ) {
$header_renderer = $c->get( 'wcgateway.settings.header-renderer' );
assert( $header_renderer instanceof HeaderRenderer );
$section_renderer = $c->get( 'wcgateway.settings.sections-renderer' );
assert( $section_renderer instanceof SectionsRenderer );
// phpcs:ignore WordPress.Security.EscapeOutput
echo $section_renderer->render();
echo $header_renderer->render() . $section_renderer->render();
},
20
);
@ -297,15 +304,36 @@ class WCGatewayModule implements ModuleInterface {
$paypal_gateway_enabled = wc_string_to_bool( $paypal_gateway->get_option( 'enabled' ) );
$methods[] = $paypal_gateway;
$dcc_applies = $container->get( 'api.helpers.dccapplies' );
$methods[] = $paypal_gateway;
/**
* The DCC Applies object.
*
* @var DccApplies $dcc_applies
*/
if ( $dcc_applies->for_country_currency() ) {
$onboarding_state = $container->get( 'onboarding.state' );
assert( $onboarding_state instanceof State );
$settings = $container->get( 'wcgateway.settings' );
assert( $settings instanceof ContainerInterface );
$is_our_page = $container->get( 'wcgateway.is-ppcp-settings-page' );
$is_gateways_list_page = $container->get( 'wcgateway.is-wc-gateways-list-page' );
if ( $onboarding_state->current_state() !== State::STATE_ONBOARDED ) {
return $methods;
}
$dcc_applies = $container->get( 'api.helpers.dccapplies' );
assert( $dcc_applies instanceof DccApplies );
$dcc_product_status = $container->get( 'wcgateway.helper.dcc-product-status' );
assert( $dcc_product_status instanceof DCCProductStatus );
if ( $dcc_applies->for_country_currency() &&
// Show only if allowed in PayPal account, except when on our settings pages.
// Performing the full DCCProductStatus check only when on the gateway list page
// to avoid sending the API requests all the time.
( $is_our_page ||
( $is_gateways_list_page && $dcc_product_status->dcc_is_active() ) ||
( $settings->has( 'products_dcc_enabled' ) && $settings->get( 'products_dcc_enabled' ) )
)
) {
$methods[] = $container->get( 'wcgateway.credit-card-gateway' );
}
@ -313,11 +341,21 @@ class WCGatewayModule implements ModuleInterface {
$methods[] = $container->get( 'wcgateway.card-button-gateway' );
}
if ( 'DE' === $container->get( 'api.shop.country' ) ) {
$pui_product_status = $container->get( 'wcgateway.pay-upon-invoice-product-status' );
assert( $pui_product_status instanceof PayUponInvoiceProductStatus );
$shop_country = $container->get( 'api.shop.country' );
if ( 'DE' === $shop_country &&
( $is_our_page ||
( $is_gateways_list_page && $pui_product_status->pui_is_active() ) ||
( $settings->has( 'products_pui_enabled' ) && $settings->get( 'products_pui_enabled' ) )
)
) {
$methods[] = $container->get( 'wcgateway.pay-upon-invoice-gateway' );
}
if ( defined( 'PPCP_FLAG_OXXO' ) && PPCP_FLAG_OXXO === true ) {
if ( defined( 'PPCP_FLAG_OXXO' ) && PPCP_FLAG_OXXO === true && 'MX' === $shop_country ) {
$methods[] = $container->get( 'wcgateway.oxxo-gateway' );
}
@ -349,6 +387,7 @@ class WCGatewayModule implements ModuleInterface {
*/
$listener->listen_for_merchant_id();
$listener->listen_for_vaulting_enabled();
$listener->listen_for_tracking_enabled();
}
);