2020-04-02 08:38:00 +03:00
< ? php
2020-08-31 11:12:46 +03:00
/**
* Registers and configures the necessary Javascript for the button , credit messaging and DCC fields .
*
2020-09-11 14:11:10 +03:00
* @ package WooCommerce\PayPalCommerce\Button\Assets
2020-08-31 11:12:46 +03:00
*/
2020-04-28 12:31:12 +03:00
2020-04-02 08:38:00 +03:00
declare ( strict_types = 1 );
2020-09-11 14:11:10 +03:00
namespace WooCommerce\PayPalCommerce\Button\Assets ;
2022-04-12 14:59:07 +03:00
use Exception ;
use Psr\Log\LoggerInterface ;
2023-05-10 08:05:44 +03:00
use WC_Order ;
2024-07-24 17:00:58 +02:00
use WC_Payment_Tokens ;
2022-05-11 18:16:50 +03:00
use WC_Product ;
2022-06-01 18:17:51 +04:00
use WC_Product_Variation ;
2024-04-04 16:52:08 +02:00
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokensEndpoint ;
2023-10-13 17:57:03 +01:00
use WooCommerce\PayPalCommerce\ApiClient\Entity\Money ;
2022-04-12 14:59:07 +03:00
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken ;
2020-09-11 14:11:10 +03:00
use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory ;
2024-10-03 10:10:50 +03:00
use WooCommerce\PayPalCommerce\ApiClient\Helper\CurrencyGetter ;
2020-09-11 14:11:10 +03:00
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies ;
2025-03-21 18:06:50 +04:00
use WooCommerce\PayPalCommerce\ApiClient\Helper\PartnerAttribution ;
2024-05-06 18:44:24 +04:00
use WooCommerce\PayPalCommerce\Blocks\Endpoint\UpdateShippingEndpoint ;
2020-09-11 14:11:10 +03:00
use WooCommerce\PayPalCommerce\Button\Endpoint\ApproveOrderEndpoint ;
2023-01-05 14:53:23 +01:00
use WooCommerce\PayPalCommerce\Button\Endpoint\ApproveSubscriptionEndpoint ;
2023-02-15 16:50:34 +02:00
use WooCommerce\PayPalCommerce\Button\Endpoint\CartScriptParamsEndpoint ;
2020-09-11 14:11:10 +03:00
use WooCommerce\PayPalCommerce\Button\Endpoint\ChangeCartEndpoint ;
use WooCommerce\PayPalCommerce\Button\Endpoint\CreateOrderEndpoint ;
use WooCommerce\PayPalCommerce\Button\Endpoint\DataClientIdEndpoint ;
2025-07-03 22:55:49 -04:00
use WooCommerce\PayPalCommerce\Button\Endpoint\GetOrderEndpoint ;
2020-09-11 14:11:10 +03:00
use WooCommerce\PayPalCommerce\Button\Endpoint\RequestData ;
2023-01-25 09:42:31 +02:00
use WooCommerce\PayPalCommerce\Button\Endpoint\SaveCheckoutFormEndpoint ;
2023-07-18 15:58:15 +01:00
use WooCommerce\PayPalCommerce\Button\Endpoint\SimulateCartEndpoint ;
2022-04-12 14:59:07 +03:00
use WooCommerce\PayPalCommerce\Button\Endpoint\StartPayPalVaultingEndpoint ;
2023-02-07 15:29:53 +02:00
use WooCommerce\PayPalCommerce\Button\Endpoint\ValidateCheckoutEndpoint ;
2023-02-13 11:01:51 +01:00
use WooCommerce\PayPalCommerce\Button\Helper\ContextTrait ;
2024-06-28 14:47:23 +02:00
use WooCommerce\PayPalCommerce\Button\Helper\DisabledFundingSources ;
2020-09-11 14:11:10 +03:00
use WooCommerce\PayPalCommerce\Button\Helper\MessagesApply ;
2025-02-03 13:34:30 +01:00
use WooCommerce\PayPalCommerce\WcGateway\Helper\Environment ;
2023-12-20 09:00:16 +02:00
use WooCommerce\PayPalCommerce\PayLaterBlock\PayLaterBlockModule ;
2024-04-16 00:59:10 +02:00
use WooCommerce\PayPalCommerce\PayLaterWCBlocks\PayLaterWCBlocksModule ;
2024-04-06 17:31:57 +02:00
use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CreatePaymentToken ;
use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CreateSetupToken ;
2024-04-09 17:34:51 +02:00
use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CreatePaymentTokenForGuest ;
2020-09-11 14:11:10 +03:00
use WooCommerce\PayPalCommerce\Session\SessionHandler ;
2023-10-17 16:29:56 +02:00
use WooCommerce\PayPalCommerce\WcSubscriptions\FreeTrialHandlerTrait ;
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper ;
2021-09-17 17:11:36 +02:00
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository ;
2022-10-31 15:59:17 +04:00
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException ;
2022-07-19 09:20:26 +03:00
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway ;
2021-05-19 15:39:33 +02:00
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway ;
2022-07-19 09:20:26 +03:00
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway ;
2021-10-08 10:23:19 +03:00
use WooCommerce\PayPalCommerce\WcGateway\Helper\SettingsStatus ;
2020-09-11 14:11:10 +03:00
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings ;
2024-08-26 13:38:45 +02:00
use WC_Shipping_Method ;
use WC_Cart ;
2025-03-14 16:15:23 +01:00
use WooCommerce\PayPalCommerce\WcGateway\Helper\CardPaymentsConfiguration ;
2020-04-02 08:38:00 +03:00
2020-08-31 11:12:46 +03:00
/**
* Class SmartButton
*/
2020-08-27 11:08:36 +03:00
class SmartButton implements SmartButtonInterface {
2023-02-13 11:01:51 +01:00
use FreeTrialHandlerTrait , ContextTrait ;
2022-04-12 14:59:07 +03:00
2021-06-17 11:51:43 +02:00
/**
* The Settings status helper .
*
* @ var SettingsStatus
*/
protected $settings_status ;
2020-08-31 11:12:46 +03:00
/**
* The URL to the module .
*
* @ var string
*/
private $module_url ;
2022-02-17 18:51:24 +02:00
/**
* The assets version .
*
* @ var string
*/
private $version ;
2020-08-31 11:12:46 +03:00
/**
* The settings .
*
* @ var Settings
*/
2020-08-27 11:08:36 +03:00
private $settings ;
2020-08-31 11:12:46 +03:00
/**
* The Payer Factory .
*
* @ var PayerFactory
*/
private $payer_factory ;
/**
* The client ID .
*
* @ var string
*/
private $client_id ;
/**
* The Request Data .
*
* @ var RequestData
*/
private $request_data ;
/**
* The DCC Applies helper .
*
* @ var DccApplies
*/
private $dcc_applies ;
/**
* The Subscription Helper .
*
* @ var SubscriptionHelper
*/
private $subscription_helper ;
/**
* The Messages apply helper .
*
* @ var MessagesApply
*/
private $messages_apply ;
2020-10-16 13:32:26 +03:00
/**
* The environment object .
*
* @ var Environment
*/
private $environment ;
2021-03-25 16:57:42 +01:00
/**
* The payment token repository .
*
* @ var PaymentTokenRepository
*/
private $payment_token_repository ;
2021-03-25 16:11:45 +01:00
2021-11-30 10:40:38 +02:00
/**
2024-10-03 10:10:50 +03:00
* The getter of the 3 - letter currency code of the shop .
2021-11-30 10:40:38 +02:00
*
2024-10-03 10:10:50 +03:00
* @ var CurrencyGetter
2021-11-30 10:40:38 +02:00
*/
2024-10-03 10:10:50 +03:00
private CurrencyGetter $currency ;
2021-11-30 10:40:38 +02:00
2022-04-12 15:29:23 +03:00
/**
* All existing funding sources .
*
* @ var array
*/
private $all_funding_sources ;
2022-06-28 12:09:18 +03:00
/**
* Whether the basic JS validation of the form iss enabled .
*
* @ var bool
*/
private $basic_checkout_validation_enabled ;
2023-02-07 15:29:53 +02:00
/**
* Whether to execute WC validation of the checkout form .
*
* @ var bool
*/
protected $early_validation_enabled ;
2023-01-04 12:40:24 +01:00
/**
* Cached payment tokens .
*
* @ var PaymentToken [] | null
*/
private $payment_tokens = null ;
2023-04-24 08:15:22 +03:00
/**
* The contexts that should have the Pay Now button .
*
* @ var string []
*/
private $pay_now_contexts ;
2023-06-14 12:44:06 +03:00
/**
* The sources that do not cause issues about redirecting ( on mobile , ... ) and sometimes not returning back .
*
* @ var string []
*/
private $funding_sources_without_redirect ;
2023-01-04 12:40:24 +01:00
/**
2024-04-03 09:59:40 +02:00
* Session handler .
2023-01-04 12:40:24 +01:00
*
2024-04-03 09:59:40 +02:00
* @ var SessionHandler
2023-01-04 12:40:24 +01:00
*/
2024-04-03 09:59:40 +02:00
private $session_handler ;
2023-05-02 14:28:36 +02:00
2022-04-12 14:59:07 +03:00
/**
2024-04-03 09:59:40 +02:00
* Whether Vault v3 module is enabled .
2023-05-02 14:28:36 +02:00
*
2024-04-03 09:59:40 +02:00
* @ var bool
2022-04-12 14:59:07 +03:00
*/
2024-04-03 09:59:40 +02:00
private $vault_v3_enabled ;
2024-04-04 16:52:08 +02:00
/**
* Payment tokens endpoint .
*
* @ var PaymentTokensEndpoint
*/
private $payment_tokens_endpoint ;
2024-04-03 09:59:40 +02:00
/**
* The logger .
*
* @ var LoggerInterface
*/
private $logger ;
2022-04-12 14:59:07 +03:00
2024-05-06 18:44:24 +04:00
/**
* Whether the shipping should be handled in PayPal .
*
* @ var bool
*/
private $should_handle_shipping_in_paypal ;
2024-06-28 14:47:23 +02:00
/**
* List of funding sources to be disabled .
*
* @ var DisabledFundingSources
*/
private $disabled_funding_sources ;
2025-03-12 18:39:45 +01:00
/**
* Provides details about the DCC configuration .
*
2025-03-14 16:15:23 +01:00
* @ var CardPaymentsConfiguration
2025-03-12 18:39:45 +01:00
*/
2025-03-14 16:15:23 +01:00
private CardPaymentsConfiguration $dcc_configuration ;
2025-03-12 18:39:45 +01:00
2025-03-21 18:06:50 +04:00
/**
* The PayPal Partner Attribution Helper .
*
* @ var PartnerAttribution
*/
protected PartnerAttribution $partner_attribution ;
2025-06-20 15:14:11 +03:00
/**
* Whether the server - side shipping callback is enabled ( feature flag ) .
*/
private bool $server_side_shipping_callback_enabled ;
2025-07-15 10:49:12 -04:00
/**
* Whether the AppSwitch is enabled ( feature flag ) .
*/
private bool $appswitch_enabled ;
2025-07-08 11:55:50 -04:00
/**
* Whether the final review is enabled in blocks settings .
*/
private bool $final_review_enabled ;
2021-03-25 16:57:42 +01:00
/**
2020-08-31 11:12:46 +03:00
* SmartButton constructor .
*
2025-03-14 16:15:23 +01:00
* @ param string $module_url The URL to the module .
* @ param string $version The assets version .
* @ param SessionHandler $session_handler The Session handler .
* @ param Settings $settings The Settings .
* @ param PayerFactory $payer_factory The Payer factory .
* @ param string $client_id The client ID .
* @ param RequestData $request_data The Request Data helper .
* @ param DccApplies $dcc_applies The DCC applies helper .
* @ param SubscriptionHelper $subscription_helper The subscription helper .
* @ param MessagesApply $messages_apply The Messages apply helper .
* @ param Environment $environment The environment object .
* @ param PaymentTokenRepository $payment_token_repository The payment token repository .
* @ param SettingsStatus $settings_status The Settings status helper .
* @ param CurrencyGetter $currency The getter of the 3 - letter currency code of the shop .
* @ param array $all_funding_sources All existing funding sources .
* @ param bool $basic_checkout_validation_enabled Whether the basic JS validation of the form iss enabled .
* @ param bool $early_validation_enabled Whether to execute WC validation of the checkout form .
* @ param array $pay_now_contexts The contexts that should have the Pay Now button .
* @ param string [] $funding_sources_without_redirect The sources that do not cause issues about redirecting ( on mobile , ... ) and sometimes not returning back .
* @ param bool $vault_v3_enabled Whether Vault v3 module is enabled .
* @ param PaymentTokensEndpoint $payment_tokens_endpoint Payment tokens endpoint .
* @ param LoggerInterface $logger The logger .
* @ param bool $should_handle_shipping_in_paypal Whether the shipping should be handled in PayPal .
2025-06-20 15:14:11 +03:00
* @ param bool $server_side_shipping_callback_enabled Whether the server - side shipping callback is enabled ( feature flag ) .
2025-07-15 10:49:12 -04:00
* @ param bool $appswitch_enabled Whether the AppSwitch is enabled ( feature flag ) .
2025-03-14 16:15:23 +01:00
* @ param DisabledFundingSources $disabled_funding_sources List of funding sources to be disabled .
* @ param CardPaymentsConfiguration $dcc_configuration The DCC Gateway Configuration .
2025-03-21 18:06:50 +04:00
* @ param PartnerAttribution $partner_attribution The PayPal Partner Attribution Helper .
2025-07-08 11:55:50 -04:00
* @ param bool $final_review_enabled Whether the final review is enabled in blocks settings .
2020-08-31 11:12:46 +03:00
*/
2020-08-27 11:08:36 +03:00
public function __construct (
2020-08-31 11:12:46 +03:00
string $module_url ,
2022-02-17 18:51:24 +02:00
string $version ,
2020-08-31 11:12:46 +03:00
SessionHandler $session_handler ,
2020-08-27 11:08:36 +03:00
Settings $settings ,
2020-08-31 11:12:46 +03:00
PayerFactory $payer_factory ,
string $client_id ,
RequestData $request_data ,
DccApplies $dcc_applies ,
SubscriptionHelper $subscription_helper ,
2020-10-16 13:32:26 +03:00
MessagesApply $messages_apply ,
2021-03-25 16:11:45 +01:00
Environment $environment ,
2021-06-17 11:51:43 +02:00
PaymentTokenRepository $payment_token_repository ,
2021-11-30 10:40:38 +02:00
SettingsStatus $settings_status ,
2024-10-03 10:10:50 +03:00
CurrencyGetter $currency ,
2022-04-12 15:29:23 +03:00
array $all_funding_sources ,
2022-06-28 12:09:18 +03:00
bool $basic_checkout_validation_enabled ,
2023-02-07 15:29:53 +02:00
bool $early_validation_enabled ,
2023-04-24 08:15:22 +03:00
array $pay_now_contexts ,
2023-06-14 12:44:06 +03:00
array $funding_sources_without_redirect ,
2024-04-03 09:59:40 +02:00
bool $vault_v3_enabled ,
2024-04-04 16:52:08 +02:00
PaymentTokensEndpoint $payment_tokens_endpoint ,
2024-05-06 18:44:24 +04:00
LoggerInterface $logger ,
2024-06-28 14:47:23 +02:00
bool $should_handle_shipping_in_paypal ,
2025-06-20 15:14:11 +03:00
bool $server_side_shipping_callback_enabled ,
2025-07-15 10:49:12 -04:00
bool $appswitch_enabled ,
2025-03-12 18:39:45 +01:00
DisabledFundingSources $disabled_funding_sources ,
2025-03-21 18:06:50 +04:00
CardPaymentsConfiguration $dcc_configuration ,
2025-07-08 11:55:50 -04:00
PartnerAttribution $partner_attribution ,
bool $final_review_enabled
2020-08-27 11:08:36 +03:00
) {
2025-06-20 15:14:11 +03:00
$this -> module_url = $module_url ;
$this -> version = $version ;
$this -> session_handler = $session_handler ;
$this -> settings = $settings ;
$this -> payer_factory = $payer_factory ;
$this -> client_id = $client_id ;
$this -> request_data = $request_data ;
$this -> dcc_applies = $dcc_applies ;
$this -> subscription_helper = $subscription_helper ;
$this -> messages_apply = $messages_apply ;
$this -> environment = $environment ;
$this -> payment_token_repository = $payment_token_repository ;
$this -> settings_status = $settings_status ;
$this -> currency = $currency ;
$this -> all_funding_sources = $all_funding_sources ;
$this -> basic_checkout_validation_enabled = $basic_checkout_validation_enabled ;
$this -> early_validation_enabled = $early_validation_enabled ;
$this -> pay_now_contexts = $pay_now_contexts ;
$this -> funding_sources_without_redirect = $funding_sources_without_redirect ;
$this -> vault_v3_enabled = $vault_v3_enabled ;
$this -> logger = $logger ;
$this -> payment_tokens_endpoint = $payment_tokens_endpoint ;
$this -> should_handle_shipping_in_paypal = $should_handle_shipping_in_paypal ;
$this -> server_side_shipping_callback_enabled = $server_side_shipping_callback_enabled ;
2025-07-15 10:49:12 -04:00
$this -> appswitch_enabled = $appswitch_enabled ;
2025-06-20 15:14:11 +03:00
$this -> disabled_funding_sources = $disabled_funding_sources ;
$this -> dcc_configuration = $dcc_configuration ;
$this -> partner_attribution = $partner_attribution ;
2025-07-08 11:55:50 -04:00
$this -> final_review_enabled = $final_review_enabled ;
2021-03-25 16:57:42 +01:00
}
2020-08-27 11:08:36 +03:00
/**
2020-08-31 11:12:46 +03:00
* Registers the necessary action hooks to render the HTML depending on the settings .
*
2020-08-27 11:08:36 +03:00
* @ return bool
*/
2020-08-31 11:12:46 +03:00
public function render_wrapper () : bool {
2023-12-05 17:57:07 +00:00
$this -> init_context ();
2020-08-27 11:08:36 +03:00
if ( $this -> settings -> has ( 'enabled' ) && $this -> settings -> get ( 'enabled' ) ) {
2020-08-31 11:12:46 +03:00
$this -> render_button_wrapper_registrar ();
$this -> render_message_wrapper_registrar ();
2020-08-27 11:08:36 +03:00
}
2025-03-12 18:39:45 +01:00
if ( $this -> dcc_configuration -> is_enabled () ) {
2025-03-17 15:23:29 +01:00
$this -> render_dcc_wrapper ();
2020-08-27 11:08:36 +03:00
}
2022-04-12 14:59:07 +03:00
if ( $this -> is_free_trial_cart () ) {
add_action (
'woocommerce_review_order_after_submit' ,
function () {
$vaulted_email = $this -> get_vaulted_paypal_email ();
if ( ! $vaulted_email ) {
return ;
}
?>
< div class = " ppcp-vaulted-paypal-details " >
< ? php
echo wp_kses_post (
sprintf (
// translators: %1$s - email, %2$s, %3$s - HTML tags for a link.
esc_html__ (
'Using %2$s%1$s%3$s PayPal.' ,
'woocommerce-paypal-payments'
),
$vaulted_email ,
'<b>' ,
'</b>'
)
);
?>
</ div >
< ? php
}
);
}
2023-07-24 17:09:45 +01:00
$this -> sanitize_woocommerce_filters ();
2020-08-27 11:08:36 +03:00
return true ;
}
2025-03-17 15:23:29 +01:00
/**
* Registers hooks and callbacks that are only relevant for DCC ( ACDC ) payments .
*
* @ return void
*/
private function render_dcc_wrapper () : void {
add_action (
$this -> checkout_dcc_button_renderer_hook (),
array ( $this , 'dcc_renderer' ),
11
);
add_action (
$this -> pay_order_renderer_hook (),
array ( $this , 'dcc_renderer' ),
11
);
$subscription_helper = $this -> subscription_helper ;
add_filter (
'woocommerce_credit_card_form_fields' ,
function ( array $default_fields , $id ) use ( $subscription_helper ) : array {
if (
CreditCardGateway :: ID === $id
&& is_user_logged_in ()
&& $this -> settings -> has ( 'vault_enabled_dcc' )
&& $this -> settings -> get ( 'vault_enabled_dcc' )
&& apply_filters ( 'woocommerce_paypal_payments_should_render_card_custom_fields' , true )
) {
$default_fields [ 'card-vault' ] = sprintf (
'<p class="form-row form-row-wide"><label for="ppcp-credit-card-vault"><input class="ppcp-credit-card-vault" type="checkbox" id="ppcp-credit-card-vault" name="vault">%s</label></p>' ,
esc_html__ ( 'Save your Credit Card' , 'woocommerce-paypal-payments' )
);
if ( $subscription_helper -> cart_contains_subscription () || $subscription_helper -> order_pay_contains_subscription () ) {
$default_fields [ 'card-vault' ] = '' ;
}
$tokens = $this -> payment_token_repository -> all_for_user_id ( get_current_user_id () );
if ( $tokens && $this -> payment_token_repository -> tokens_contains_card ( $tokens ) ) {
$output = sprintf (
'<p class="form-row form-row-wide"><label>%1$s</label><select id="saved-credit-card" name="saved_credit_card"><option value="">%2$s</option>' ,
esc_html__ ( 'Or select a saved Credit Card payment' , 'woocommerce-paypal-payments' ),
esc_html__ ( 'Choose a saved payment' , 'woocommerce-paypal-payments' )
);
foreach ( $tokens as $token ) {
if ( isset ( $token -> source () -> card ) ) {
$output .= sprintf (
'<option value="%1$s">%2$s ...%3$s</option>' ,
$token -> id (),
$token -> source () -> card -> brand ,
$token -> source () -> card -> last_digits
);
}
}
$output .= '</select></p>' ;
$default_fields [ 'saved-credit-card' ] = $output ;
}
}
return $default_fields ;
},
10 ,
2
);
}
2020-08-31 11:12:46 +03:00
/**
* Registers the hooks to render the credit messaging HTML depending on the settings .
*
* @ return bool
*/
private function render_message_wrapper_registrar () : bool {
2025-03-31 12:47:40 +02:00
if ( ! apply_filters ( 'woocommerce_paypal_payments_should_render_pay_later_messaging' , true ) ) {
return false ;
}
2023-12-20 15:17:07 +02:00
if ( ! $this -> settings_status -> is_pay_later_messaging_enabled () || ! $this -> settings_status -> has_pay_later_messaging_locations () ) {
2023-07-13 11:59:31 +01:00
return false ;
}
2023-10-16 21:41:17 +03:00
$location = $this -> location ();
2022-10-31 15:59:17 +04:00
2023-10-16 21:41:17 +03:00
if ( ! $this -> settings_status -> is_pay_later_messaging_enabled_for_location ( $location ) ) {
return false ;
}
2022-05-06 18:22:11 +04:00
2023-10-31 11:42:35 +02:00
$default_pay_order_hook = 'woocommerce_pay_order_before_submit' ;
2023-11-21 11:55:50 +00:00
/**
* The filter returning if the current theme is a block theme or not .
*/
$is_block_theme = ( bool ) apply_filters (
'woocommerce_paypal_payments_messages_renderer_is_block' ,
wp_is_block_theme ()
);
2024-04-08 23:35:53 +02:00
$has_paylater_block =
2024-04-16 00:59:10 +02:00
(
PayLaterBlockModule :: is_block_enabled ( $this -> settings_status ) &&
has_block ( 'woocommerce-paypal-payments/paylater-messages' )
) ||
(
PayLaterWCBlocksModule :: is_block_enabled ( $this -> settings_status , $location ) &&
(
has_block ( 'woocommerce-paypal-payments/checkout-paylater-messages' ) ||
has_block ( 'woocommerce-paypal-payments/cart-paylater-messages' )
)
);
2024-04-08 23:35:53 +02:00
$get_hook = function ( string $location ) use ( $default_pay_order_hook , $is_block_theme , $has_paylater_block ) : ? array {
2023-10-16 21:41:17 +03:00
switch ( $location ) {
case 'checkout' :
2023-10-17 08:44:35 +03:00
return $this -> messages_renderer_hook ( $location , 'woocommerce_review_order_before_payment' , 10 );
2023-10-16 21:41:17 +03:00
case 'cart' :
return $this -> messages_renderer_hook ( $location , $this -> proceed_to_checkout_button_renderer_hook (), 19 );
case 'pay-now' :
2023-10-31 11:31:25 +02:00
return $this -> messages_renderer_hook ( $location , $default_pay_order_hook , 10 );
2023-10-16 21:41:17 +03:00
case 'product' :
return $this -> messages_renderer_hook ( $location , $this -> single_product_renderer_hook (), 30 );
case 'shop' :
2023-11-21 11:55:50 +00:00
return $is_block_theme
? $this -> messages_renderer_block ( $location , 'core/query-title' , 10 )
: $this -> messages_renderer_hook ( $location , 'woocommerce_archive_description' , 10 );
2023-10-16 21:41:17 +03:00
case 'home' :
2023-11-21 11:55:50 +00:00
return $is_block_theme
? $this -> messages_renderer_block ( $location , 'core/navigation' , 10 )
: $this -> messages_renderer_hook ( $location , 'loop_start' , 20 );
2023-10-16 21:41:17 +03:00
default :
2024-04-08 23:35:53 +02:00
return $has_paylater_block
? $this -> messages_renderer_hook ( $location , 'ppcp_paylater_message_block' , 10 )
: null ;
2023-10-16 21:41:17 +03:00
}
};
2020-08-27 11:08:36 +03:00
2023-10-16 21:41:17 +03:00
$hook = $get_hook ( $location );
2024-04-08 23:35:53 +02:00
2023-10-16 21:41:17 +03:00
if ( ! $hook ) {
return false ;
2020-08-27 11:08:36 +03:00
}
2023-11-21 11:55:50 +00:00
if ( $hook [ 'blockName' ] ? ? false ) {
$this -> message_renderer ( $hook );
} else {
add_action (
$hook [ 'name' ],
array ( $this , 'message_renderer' ),
$hook [ 'priority' ]
);
}
2023-10-16 21:41:17 +03:00
2023-10-31 11:42:35 +02:00
// Looks like there are no hooks like woocommerce_review_order_before_payment on the pay for order page, so have to move using JS.
if ( $location === 'pay-now' && $hook [ 'name' ] === $default_pay_order_hook &&
/**
* The filter returning true if Pay Later messages should be displayed before payment methods
* on the pay for order page , like in checkout .
*/
apply_filters (
'woocommerce_paypal_payments_put_pay_order_messages_before_payment_methods' ,
true
)
) {
add_action (
'ppcp_after_pay_order_message_wrapper' ,
function () {
echo '
< script >
2024-04-08 23:35:53 +02:00
document . querySelector ( " #payment " ) . before ( document . querySelector ( " .ppcp-messages " ))
2023-10-31 11:42:35 +02:00
</ script > ' ;
}
);
}
2020-08-27 11:08:36 +03:00
return true ;
}
2020-08-31 11:12:46 +03:00
/**
* Registers the hooks where to render the button HTML according to the settings .
*
* @ return bool
2022-10-31 15:59:17 +04:00
* @ throws NotFoundException When a setting was not found .
2020-08-31 11:12:46 +03:00
*/
private function render_button_wrapper_registrar () : bool {
2020-08-27 11:08:36 +03:00
if (
2022-02-18 18:06:55 +04:00
( is_product () || wc_post_content_has_shortcode ( 'product_page' ) )
2022-12-05 16:53:30 +04:00
&& $this -> settings_status -> is_smart_button_enabled_for_location ( 'product' )
2022-04-12 15:00:11 +03:00
// TODO: it seems like there is no easy way to properly handle vaulted PayPal free trial,
// so disable the buttons for now everywhere except checkout for free trial.
&& ! $this -> is_free_trial_product ()
2022-10-20 14:20:11 -03:00
&& ! is_checkout ()
2020-08-27 11:08:36 +03:00
) {
add_action (
2022-02-18 18:06:55 +04:00
$this -> single_product_renderer_hook (),
2022-07-19 09:20:26 +03:00
function () {
2022-06-27 15:47:21 +04:00
$product = wc_get_product ();
if (
is_a ( $product , WC_Product :: class )
&& ! $this -> product_supports_payment ( $product )
) {
return ;
}
2023-09-07 09:13:57 +01:00
$this -> button_renderer ( PayPalGateway :: ID , 'woocommerce_paypal_payments_single_product_button_render' );
2022-07-19 09:20:26 +03:00
},
2022-02-18 18:06:55 +04:00
31
2020-08-27 11:08:36 +03:00
);
}
2022-04-06 17:57:59 +04:00
if (
2022-12-05 16:53:30 +04:00
$this -> settings_status -> is_smart_button_enabled_for_location ( 'mini-cart' )
2022-04-12 15:00:11 +03:00
&& ! $this -> is_free_trial_cart ()
2022-04-06 17:57:59 +04:00
) {
add_action (
$this -> mini_cart_button_renderer_hook (),
2022-04-06 18:18:05 +04:00
function () {
2022-04-12 17:20:32 +03:00
if ( $this -> is_cart_price_total_zero () || $this -> is_free_trial_cart () ) {
2022-04-06 17:57:59 +04:00
return ;
}
2022-04-06 18:18:05 +04:00
2023-08-29 15:26:59 +01:00
echo '<p class="woocommerce-mini-cart__buttons buttons">' ;
echo '<span id="ppc-button-minicart"></span>' ;
2023-08-24 16:17:29 +01:00
do_action ( 'woocommerce_paypal_payments_minicart_button_render' );
2023-09-28 10:19:51 +01:00
echo '</p>' ;
2022-04-06 17:57:59 +04:00
},
30
);
}
2022-06-27 15:47:21 +04:00
$available_gateways = WC () -> payment_gateways -> get_available_payment_gateways ();
2022-02-18 18:06:55 +04:00
2022-06-27 15:47:21 +04:00
if ( isset ( $available_gateways [ 'ppcp-gateway' ] ) ) {
2022-07-26 19:11:07 +04:00
add_action (
$this -> pay_order_renderer_hook (),
function () : void {
2023-09-07 09:13:57 +01:00
$this -> button_renderer ( PayPalGateway :: ID , 'woocommerce_paypal_payments_payorder_button_render' );
2022-07-26 19:11:07 +04:00
$this -> button_renderer ( CardButtonGateway :: ID );
2023-02-27 12:03:32 +02:00
},
20
2022-07-26 19:11:07 +04:00
);
add_action (
$this -> checkout_button_renderer_hook (),
function () : void {
2023-09-07 09:13:57 +01:00
$this -> button_renderer ( PayPalGateway :: ID , 'woocommerce_paypal_payments_checkout_button_render' );
2022-07-26 19:11:07 +04:00
$this -> button_renderer ( CardButtonGateway :: ID );
2022-04-18 18:16:22 +04:00
}
2022-07-26 19:11:07 +04:00
);
2020-08-27 11:08:36 +03:00
2022-12-05 16:53:30 +04:00
$enabled_on_cart = $this -> settings_status -> is_smart_button_enabled_for_location ( 'cart' );
2022-06-27 15:47:21 +04:00
add_action (
$this -> proceed_to_checkout_button_renderer_hook (),
2022-12-05 16:53:30 +04:00
function () use ( $enabled_on_cart ) {
2025-04-24 08:59:45 +02:00
if ( ! is_cart () || ! $enabled_on_cart || $this -> is_free_trial_cart () || $this -> is_cart_price_total_zero () || isset ( reset ( WC () -> cart -> cart_contents )[ 'subscription_switch' ] ) ) {
2022-06-27 15:47:21 +04:00
return ;
}
2023-09-07 09:13:57 +01:00
$this -> button_renderer ( PayPalGateway :: ID , 'woocommerce_paypal_payments_cart_button_render' );
2022-07-26 19:11:07 +04:00
},
20
);
}
2020-08-27 11:08:36 +03:00
return true ;
}
2020-08-31 11:12:46 +03:00
/**
2023-03-29 20:12:39 +03:00
* Whether any of our scripts ( for DCC or product , mini - cart , non - block cart / checkout ) should be loaded .
2020-08-31 11:12:46 +03:00
*/
2023-03-29 20:12:39 +03:00
public function should_load_ppcp_script () : bool {
2023-10-16 21:39:54 +03:00
$pcp_gateway_enabled = $this -> settings -> has ( 'enabled' ) && $this -> settings -> get ( 'enabled' );
if ( ! $pcp_gateway_enabled ) {
2020-08-27 11:08:36 +03:00
return false ;
}
2020-09-03 11:40:44 +03:00
2023-10-16 21:39:54 +03:00
return $this -> should_load_buttons () || $this -> should_load_messages () || $this -> can_render_dcc ();
2023-02-15 16:03:49 +02:00
}
/**
2023-03-29 20:12:39 +03:00
* Determines whether the button component should be loaded .
2023-02-15 16:03:49 +02:00
*/
2023-03-29 20:12:39 +03:00
public function should_load_buttons () : bool {
2023-10-16 21:39:54 +03:00
$pcp_gateway_enabled = $this -> settings -> has ( 'enabled' ) && $this -> settings -> get ( 'enabled' );
if ( ! $pcp_gateway_enabled ) {
2023-03-29 20:12:39 +03:00
return false ;
2023-02-15 16:03:49 +02:00
}
2023-03-29 20:12:39 +03:00
$smart_button_enabled_for_current_location = $this -> settings_status -> is_smart_button_enabled_for_location ( $this -> context () );
$smart_button_enabled_for_mini_cart = $this -> settings_status -> is_smart_button_enabled_for_location ( 'mini-cart' );
switch ( $this -> context () ) {
case 'checkout' :
case 'cart' :
case 'pay-now' :
2023-03-29 20:15:42 +03:00
case 'checkout-block' :
case 'cart-block' :
return $smart_button_enabled_for_current_location ;
2023-03-29 20:12:39 +03:00
case 'product' :
2023-10-16 21:39:54 +03:00
return $smart_button_enabled_for_current_location || $smart_button_enabled_for_mini_cart ;
2023-03-29 20:12:39 +03:00
default :
2024-01-05 09:28:57 +02:00
return $smart_button_enabled_for_mini_cart || $this -> is_block_editor ();
2020-09-03 11:48:25 +03:00
}
2023-03-29 20:12:39 +03:00
}
2023-10-16 21:39:54 +03:00
/**
* Determines whether the Pay Later messages component should be loaded .
*/
public function should_load_messages () : bool {
$pcp_gateway_enabled = $this -> settings -> has ( 'enabled' ) && $this -> settings -> get ( 'enabled' );
if ( ! $pcp_gateway_enabled ) {
return false ;
}
2023-12-20 15:18:39 +02:00
if ( ! $this -> settings_status -> is_pay_later_messaging_enabled () ) {
return false ;
}
2023-10-16 21:39:54 +03:00
if ( ! $this -> messages_apply -> for_country () || $this -> is_free_trial_cart () ) {
return false ;
}
$location = $this -> location ();
$messaging_enabled_for_current_location = $this -> settings_status -> is_pay_later_messaging_enabled_for_location ( $location );
2024-04-17 02:06:41 +02:00
$has_paylater_block = PayLaterBlockModule :: is_block_enabled ( $this -> settings_status ) && has_block ( 'woocommerce-paypal-payments/paylater-messages' );
if ( 'cart-block' === $location || 'checkout-block' === $location ) {
return true ;
}
2023-12-20 08:59:47 +02:00
2023-10-16 21:39:54 +03:00
switch ( $location ) {
case 'checkout' :
case 'cart' :
case 'pay-now' :
case 'product' :
case 'shop' :
case 'home' :
return $messaging_enabled_for_current_location ;
2023-12-12 10:52:33 +02:00
case 'block-editor' :
return true ;
2023-10-16 21:39:54 +03:00
default :
2023-12-20 08:59:47 +02:00
return $has_paylater_block ;
2023-10-16 21:39:54 +03:00
}
}
2023-03-29 20:12:39 +03:00
/**
* Whether DCC fields can be rendered .
*/
public function can_render_dcc () : bool {
2025-03-14 16:27:01 +01:00
return $this -> dcc_configuration -> is_acdc_enabled ()
2024-06-14 17:34:57 +02:00
&& in_array (
$this -> context (),
apply_filters ( 'woocommerce_paypal_payments_can_render_dcc_contexts' , array ( 'checkout' , 'pay-now' , 'add-payment-method' ) ),
true
);
2023-03-29 20:12:39 +03:00
}
/**
* Enqueues our scripts / styles ( for DCC and product , mini - cart and non - block cart / checkout )
*/
public function enqueue () : void {
if ( $this -> can_render_dcc () ) {
wp_enqueue_style (
'ppcp-hosted-fields' ,
untrailingslashit ( $this -> module_url ) . '/assets/css/hosted-fields.css' ,
array (),
$this -> version
);
2020-09-03 11:48:25 +03:00
}
2023-09-11 10:47:08 +03:00
wp_enqueue_style (
'gateway' ,
untrailingslashit ( $this -> module_url ) . '/assets/css/gateway.css' ,
array (),
$this -> version
);
2020-09-03 11:48:25 +03:00
2023-03-29 20:12:39 +03:00
wp_enqueue_script (
'ppcp-smart-button' ,
untrailingslashit ( $this -> module_url ) . '/assets/js/button.js' ,
array ( 'jquery' ),
$this -> version ,
true
);
wp_localize_script (
'ppcp-smart-button' ,
'PayPalCommerceGateway' ,
$this -> script_data ()
);
2020-08-27 11:08:36 +03:00
}
2020-08-31 11:12:46 +03:00
/**
* Renders the HTML for the buttons .
2022-07-19 09:20:26 +03:00
*
2023-09-07 09:13:57 +01:00
* @ param string $gateway_id The gateway ID , like 'ppcp-gateway' .
* @ param string | null $action_name The action name to be called .
2020-08-31 11:12:46 +03:00
*/
2023-09-07 09:13:57 +01:00
public function button_renderer ( string $gateway_id , string $action_name = null ) {
2022-05-02 17:48:14 +04:00
2022-08-05 17:12:51 +03:00
$available_gateways = WC () -> payment_gateways -> get_available_payment_gateways ();
if ( ! isset ( $available_gateways [ $gateway_id ] ) ) {
return ;
}
2022-03-17 15:59:19 +02:00
// The wrapper is needed for the loading spinner,
// otherwise jQuery block() prevents buttons rendering.
2023-09-07 09:13:57 +01:00
echo '<div class="ppc-button-wrapper">' ;
2023-10-17 09:21:33 +03:00
$hook_gateway_id = str_replace ( '-' , '_' , $gateway_id );
/**
* A hook executed after rendering of the opening tag for the PCP wrapper ( before the inner wrapper for the buttons ) .
*
* For the PayPal gateway the hook name is ppcp_start_button_wrapper_ppcp_gateway .
*/
do_action ( 'ppcp_start_button_wrapper_' . $hook_gateway_id );
2023-09-07 09:13:57 +01:00
echo '<div id="ppc-button-' . esc_attr ( $gateway_id ) . '"></div>' ;
2023-10-17 09:21:33 +03:00
/**
* A hook executed before rendering of the closing tag for the PCP wrapper ( before the inner wrapper for the buttons ) .
*
* For the PayPal gateway the hook name is ppcp_end_button_wrapper_ppcp_gateway .
*/
do_action ( 'ppcp_end_button_wrapper_' . $hook_gateway_id );
2023-09-07 09:13:57 +01:00
if ( null !== $action_name ) {
do_action ( $action_name );
}
echo '</div>' ;
2020-08-27 11:08:36 +03:00
}
2020-08-31 11:12:46 +03:00
/**
* Renders the HTML for the credit messaging .
2023-11-21 11:55:50 +00:00
*
* @ param array | null $block_params If it ' s to be rendered after a block , contains the block params .
* @ return void
2020-08-31 11:12:46 +03:00
*/
2023-11-21 11:55:50 +00:00
public function message_renderer ( $block_params = array () ) : void {
2021-11-08 14:58:25 -05:00
$product = wc_get_product ();
2023-10-31 11:32:19 +02:00
$location = $this -> location ();
$location_hook = $this -> location_to_hook ( $location );
2023-10-17 09:59:12 +03:00
2021-11-08 14:58:25 -05:00
if (
2023-10-17 09:59:12 +03:00
$location === 'product' && is_a ( $product , WC_Product :: class )
2022-05-11 18:16:50 +03:00
/**
* The filter returning true if PayPal buttons can be rendered , or false otherwise .
*/
&& ! $this -> product_supports_payment ( $product )
2021-11-08 14:58:25 -05:00
) {
return ;
}
2020-08-27 11:08:36 +03:00
2023-10-31 11:32:19 +02:00
/**
* A hook executed before rendering of the PCP Pay Later messages wrapper .
*/
do_action ( " ppcp_before_ { $location_hook } _message_wrapper " );
2025-03-21 18:06:50 +04:00
$messages_placeholder = '<div class="ppcp-messages" data-partner-attribution-id="' . esc_attr ( $this -> partner_attribution -> get_bn_code () ) . '"></div>' ;
2023-11-21 11:55:50 +00:00
if ( is_array ( $block_params ) && ( $block_params [ 'blockName' ] ? ? false ) ) {
$this -> render_after_block (
$block_params [ 'blockName' ],
'<div class="wp-block-group alignwide">' . $messages_placeholder . '</div>' ,
$block_params [ 'priority' ] ? ? 10
);
} else {
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo $messages_placeholder ;
}
2023-10-31 11:32:19 +02:00
/**
* A hook executed after rendering of the PCP Pay Later messages wrapper .
*/
do_action ( " ppcp_after_ { $location_hook } _message_wrapper " );
2020-08-27 11:08:36 +03:00
}
2020-08-19 05:19:29 +03:00
2023-11-21 11:55:50 +00:00
/**
* Renders content after a given block .
*
* @ param string $name The name of the block to render after .
* @ param string $content The content to be rendered .
* @ param int $priority The 'render_block' hook priority .
* @ return void
*/
private function render_after_block ( string $name , string $content , int $priority = 10 ) : void {
add_filter (
'render_block' ,
/**
* Adds content after a given block .
*
* @ param string $block_content The block content .
* @ param array | mixed $block_params The block params .
* @ return string
*
* @ psalm - suppress MissingClosureParamType
*/
function ( $block_content , $block_params ) use ( $name , $content , $priority ) {
if (
is_array ( $block_params )
&& ( $block_params [ 'blockName' ] ? ? null ) === $name
) {
$block_content .= $content ;
}
return $block_content ;
},
$priority ,
2
);
}
2020-08-31 11:12:46 +03:00
/**
* The values for the credit messaging .
*
* @ return array
*/
private function message_values () : array {
2023-07-27 09:57:19 +01:00
if ( ! $this -> settings_status -> is_pay_later_messaging_enabled () ) {
2020-08-27 11:08:36 +03:00
return array ();
}
2023-10-17 10:00:20 +03:00
$location = $this -> location ();
switch ( $location ) {
case 'checkout' :
case 'checkout-block' :
case 'pay-now' :
$placement = 'payment' ;
break ;
case 'cart' :
case 'cart-block' :
$placement = 'cart' ;
break ;
case 'product' :
$placement = 'product' ;
break ;
case 'shop' :
$placement = 'product-list' ;
break ;
case 'home' :
$placement = 'home' ;
break ;
default :
$placement = 'payment' ;
break ;
}
$product = wc_get_product ();
2023-12-20 15:04:09 +02:00
$amount = 0 ;
if ( is_a ( $product , WC_Product :: class ) ) {
$amount = wc_get_price_including_tax ( $product );
} elseif ( isset ( WC () -> cart ) ) {
2022-10-31 15:59:17 +04:00
$amount = WC () -> cart -> get_total ( 'raw' );
2020-08-27 11:08:36 +03:00
}
2022-10-31 15:59:17 +04:00
$styling_per_location = $this -> settings -> has ( 'pay_later_enable_styling_per_messaging_location' ) && $this -> settings -> get ( 'pay_later_enable_styling_per_messaging_location' );
2023-10-17 10:00:20 +03:00
$location = $styling_per_location ? $location : 'general' ;
2024-04-08 23:35:53 +02:00
// Map checkout-block and cart-block message options to checkout and cart options.
switch ( $location ) {
case 'checkout-block' :
$location = 'checkout' ;
break ;
case 'cart-block' :
$location = 'cart' ;
break ;
default :
break ;
}
2024-04-09 23:44:51 +02:00
$setting_name_prefix = " pay_later_ { $location } _message " ;
2022-10-31 15:59:17 +04:00
$layout = $this -> settings -> has ( " { $setting_name_prefix } _layout " ) ? $this -> settings -> get ( " { $setting_name_prefix } _layout " ) : 'text' ;
$logo_type = $this -> settings -> has ( " { $setting_name_prefix } _logo " ) ? $this -> settings -> get ( " { $setting_name_prefix } _logo " ) : 'primary' ;
$logo_position = $this -> settings -> has ( " { $setting_name_prefix } _position " ) ? $this -> settings -> get ( " { $setting_name_prefix } _position " ) : 'left' ;
$text_color = $this -> settings -> has ( " { $setting_name_prefix } _color " ) ? $this -> settings -> get ( " { $setting_name_prefix } _color " ) : 'black' ;
$style_color = $this -> settings -> has ( " { $setting_name_prefix } _flex_color " ) ? $this -> settings -> get ( " { $setting_name_prefix } _flex_color " ) : 'blue' ;
$ratio = $this -> settings -> has ( " { $setting_name_prefix } _flex_ratio " ) ? $this -> settings -> get ( " { $setting_name_prefix } _flex_ratio " ) : '1x1' ;
2024-02-23 15:42:00 +04:00
$text_size = $this -> settings -> has ( " { $setting_name_prefix } _text_size " ) ? $this -> settings -> get ( " { $setting_name_prefix } _text_size " ) : '12' ;
2022-10-31 15:59:17 +04:00
return array (
2024-04-08 23:35:53 +02:00
'wrapper' => '.ppcp-messages' ,
2023-07-27 09:57:19 +01:00
'is_hidden' => ! $this -> is_pay_later_filter_enabled_for_location ( $this -> context () ),
2023-12-20 09:00:16 +02:00
'block' => array (
2024-03-05 17:08:10 +04:00
'enabled' => PayLaterBlockModule :: is_block_enabled ( $this -> settings_status ),
2023-12-20 09:00:16 +02:00
),
2020-08-27 11:08:36 +03:00
'amount' => $amount ,
'placement' => $placement ,
'style' => array (
'layout' => $layout ,
'logo' => array (
2020-08-31 11:12:46 +03:00
'type' => $logo_type ,
'position' => $logo_position ,
2020-08-27 11:08:36 +03:00
),
'text' => array (
2020-08-31 11:12:46 +03:00
'color' => $text_color ,
2024-02-23 15:42:00 +04:00
'size' => $text_size ,
2020-08-27 11:08:36 +03:00
),
2020-08-31 11:12:46 +03:00
'color' => $style_color ,
2020-08-27 11:08:36 +03:00
'ratio' => $ratio ,
),
);
}
2020-08-19 05:19:29 +03:00
2020-09-18 15:38:38 +03:00
/**
* Renders the HTML for the DCC fields .
2020-08-31 11:12:46 +03:00
*/
public function dcc_renderer () {
2020-07-23 14:28:16 +03:00
2020-09-18 15:38:38 +03:00
if ( ! $this -> can_render_dcc () ) {
2020-08-27 11:08:36 +03:00
return ;
}
2020-07-23 14:28:16 +03:00
2022-06-15 16:20:43 +03:00
/**
* The WC filter returning the WC order button text .
* phpcs : disable WordPress . WP . I18n . TextDomainMismatch
*/
2023-05-17 11:29:29 +02:00
$label = 'checkout' === $this -> context () ? apply_filters ( 'woocommerce_order_button_text' , __ ( 'Place order' , 'woocommerce' ) ) : __ ( 'Pay for order' , 'woocommerce' );
2022-06-15 16:20:43 +03:00
// phpcs:enable WordPress.WP.I18n.TextDomainMismatch
2020-09-30 14:24:31 +03:00
2020-08-27 11:08:36 +03:00
printf (
2024-07-02 13:07:39 +02:00
' < div id = " ppcp-hosted-fields " style = " display:none; " >
< button id = " place_order " type = " submit " class = " button alt ppcp-dcc-order-button wp-element-button " style = " display: none; " >% 1 $s </ button >
2022-03-30 16:09:30 +03:00
</ div >
< div id = " payments-sdk__contingency-lightbox " ></ div >
< style id = " ppcp-hide-dcc " >. payment_method_ppcp - credit - card - gateway { display : none ;} </ style > ' ,
2020-09-30 14:24:31 +03:00
esc_html ( $label )
2020-08-27 11:08:36 +03:00
);
}
2020-07-23 14:28:16 +03:00
2020-08-31 11:12:46 +03:00
/**
* Whether we can store vault tokens or not .
*
* @ return bool
*/
public function can_save_vault_token () : bool {
2020-08-27 11:08:36 +03:00
if ( ! $this -> settings -> has ( 'client_id' ) || ! $this -> settings -> get ( 'client_id' ) ) {
return false ;
}
2021-04-22 11:41:05 +02:00
2021-04-23 10:33:28 +02:00
if ( ! $this -> settings -> has ( 'vault_enabled' ) || ! $this -> settings -> get ( 'vault_enabled' ) ) {
2020-08-27 11:08:36 +03:00
return false ;
}
2021-04-22 11:41:05 +02:00
2021-12-24 12:37:06 +01:00
return true ;
2020-08-27 11:08:36 +03:00
}
2020-08-31 11:12:46 +03:00
/**
* Whether we need to initialize the script to enable tokenization for subscriptions or not .
*
* @ return bool
*/
private function has_subscriptions () : bool {
2024-10-21 09:45:09 +03:00
if ( ! $this -> subscription_helper -> plugin_is_active () ) {
return false ;
}
2024-02-26 15:45:23 +01:00
if (
2024-10-21 09:45:09 +03:00
$this -> subscription_helper -> accept_manual_renewals ()
2024-02-26 15:45:23 +01:00
&& $this -> paypal_subscriptions_enabled () !== true
) {
2020-08-27 11:08:36 +03:00
return false ;
}
if ( is_product () ) {
2020-08-31 11:12:46 +03:00
return $this -> subscription_helper -> current_product_is_subscription ();
2020-08-27 11:08:36 +03:00
}
2022-01-04 11:01:34 +01:00
if ( is_wc_endpoint_url ( 'order-pay' ) ) {
return $this -> subscription_helper -> order_pay_contains_subscription ();
}
2020-08-31 11:12:46 +03:00
return $this -> subscription_helper -> cart_contains_subscription ();
2020-08-27 11:08:36 +03:00
}
2020-07-23 14:12:29 +03:00
2023-01-16 12:37:16 +01:00
/**
* Whether PayPal subscriptions is enabled or not .
*
* @ return bool
*/
private function paypal_subscriptions_enabled () : bool {
try {
2023-02-01 16:30:39 +01:00
$subscriptions_mode = $this -> settings -> get ( 'subscriptions_mode' );
2023-01-16 12:37:16 +01:00
} catch ( NotFoundException $exception ) {
return false ;
}
2023-02-01 16:30:39 +01:00
return $subscriptions_mode === 'subscriptions_api' ;
2023-01-16 12:37:16 +01:00
}
2021-08-20 17:47:32 +03:00
/**
* Retrieves the 3 D Secure contingency settings .
*
* @ return string
*/
private function get_3ds_contingency () : string {
if ( $this -> settings -> has ( '3d_secure_contingency' ) ) {
2021-10-06 12:45:51 +03:00
$value = $this -> settings -> get ( '3d_secure_contingency' );
if ( $value ) {
2024-03-27 11:50:40 +00:00
return $this -> return_3ds_contingency ( $value );
2021-10-06 12:45:51 +03:00
}
2021-08-20 17:47:32 +03:00
}
2024-03-27 11:50:40 +00:00
return $this -> return_3ds_contingency ( 'SCA_WHEN_REQUIRED' );
}
/**
* Processes and returns the 3 D Secure contingency .
*
* @ param string $contingency The ThreeD secure contingency .
* @ return string
*/
private function return_3ds_contingency ( string $contingency ) : string {
return apply_filters ( 'woocommerce_paypal_payments_three_d_secure_contingency' , $contingency );
2021-08-20 17:47:32 +03:00
}
2024-08-26 13:38:45 +02:00
/**
* Whether the current cart contains a product that requires physical shipping .
*
* @ return bool True , if any cart item requires shipping .
*/
private function need_shipping () : bool {
/**
* Cart instance ; might be null , esp . in customizer or in Block Editor .
*
* @ var null | WC_Cart $cart
*/
$cart = WC () -> cart ;
return $cart && $cart -> needs_shipping ();
}
2020-08-31 11:12:46 +03:00
/**
2023-02-15 16:03:49 +02:00
* The configuration for the smart buttons .
2020-08-31 11:12:46 +03:00
*
* @ return array
*/
2023-02-15 16:03:49 +02:00
public function script_data () : array {
2022-04-12 14:59:07 +03:00
$is_free_trial_cart = $this -> is_free_trial_cart ();
2025-03-14 18:28:12 +01:00
$is_acdc_enabled = $this -> dcc_configuration -> is_acdc_enabled ();
2022-04-12 14:59:07 +03:00
2023-02-15 16:03:49 +02:00
$url_params = $this -> url_params ();
2020-08-31 11:12:46 +03:00
$this -> request_data -> enqueue_nonce_fix ();
2020-08-27 11:08:36 +03:00
$localize = array (
2023-07-13 16:22:57 +02:00
'url' => add_query_arg ( $url_params , 'https://www.paypal.com/sdk/js' ),
'url_params' => $url_params ,
'script_attributes' => $this -> attributes (),
'client_id' => $this -> client_id ,
2024-10-03 10:10:50 +03:00
'currency' => $this -> currency -> get (),
2023-07-13 16:22:57 +02:00
'data_client_id' => array (
2025-03-14 18:28:12 +01:00
'set_attribute' => ( is_checkout () && $is_acdc_enabled ) || $this -> can_save_vault_token (),
2023-01-16 12:37:16 +01:00
'endpoint' => \WC_AJAX :: get_endpoint ( DataClientIdEndpoint :: ENDPOINT ),
'nonce' => wp_create_nonce ( DataClientIdEndpoint :: nonce () ),
'user' => get_current_user_id (),
'has_subscriptions' => $this -> has_subscriptions (),
'paypal_subscriptions_enabled' => $this -> paypal_subscriptions_enabled (),
2020-08-27 11:08:36 +03:00
),
2023-08-09 15:38:46 +02:00
'redirect' => wc_get_checkout_url (),
'context' => $this -> context (),
'ajax' => array (
2024-04-10 17:05:33 +02:00
'simulate_cart' => array (
2023-07-18 15:58:15 +01:00
'endpoint' => \WC_AJAX :: get_endpoint ( SimulateCartEndpoint :: ENDPOINT ),
'nonce' => wp_create_nonce ( SimulateCartEndpoint :: nonce () ),
),
2024-04-10 17:05:33 +02:00
'change_cart' => array (
2022-03-09 16:24:11 +02:00
'endpoint' => \WC_AJAX :: get_endpoint ( ChangeCartEndpoint :: ENDPOINT ),
2020-08-27 11:08:36 +03:00
'nonce' => wp_create_nonce ( ChangeCartEndpoint :: nonce () ),
),
2024-04-10 17:05:33 +02:00
'create_order' => array (
2022-03-09 16:24:11 +02:00
'endpoint' => \WC_AJAX :: get_endpoint ( CreateOrderEndpoint :: ENDPOINT ),
2020-08-27 11:08:36 +03:00
'nonce' => wp_create_nonce ( CreateOrderEndpoint :: nonce () ),
),
2024-04-10 17:05:33 +02:00
'approve_order' => array (
2022-03-09 16:24:11 +02:00
'endpoint' => \WC_AJAX :: get_endpoint ( ApproveOrderEndpoint :: ENDPOINT ),
2020-08-27 11:08:36 +03:00
'nonce' => wp_create_nonce ( ApproveOrderEndpoint :: nonce () ),
),
2025-07-03 22:55:49 -04:00
'get_order' => array (
'endpoint' => \WC_AJAX :: get_endpoint ( GetOrderEndpoint :: ENDPOINT ),
'nonce' => wp_create_nonce ( GetOrderEndpoint :: nonce () ),
),
2024-04-10 17:05:33 +02:00
'approve_subscription' => array (
2023-01-05 14:53:23 +01:00
'endpoint' => \WC_AJAX :: get_endpoint ( ApproveSubscriptionEndpoint :: ENDPOINT ),
'nonce' => wp_create_nonce ( ApproveSubscriptionEndpoint :: nonce () ),
),
2024-04-10 17:05:33 +02:00
'vault_paypal' => array (
2022-04-12 14:59:07 +03:00
'endpoint' => \WC_AJAX :: get_endpoint ( StartPayPalVaultingEndpoint :: ENDPOINT ),
'nonce' => wp_create_nonce ( StartPayPalVaultingEndpoint :: nonce () ),
),
2024-04-10 17:05:33 +02:00
'save_checkout_form' => array (
2023-01-25 09:42:31 +02:00
'endpoint' => \WC_AJAX :: get_endpoint ( SaveCheckoutFormEndpoint :: ENDPOINT ),
'nonce' => wp_create_nonce ( SaveCheckoutFormEndpoint :: nonce () ),
),
2024-04-10 17:05:33 +02:00
'validate_checkout' => array (
2023-02-07 15:29:53 +02:00
'endpoint' => \WC_AJAX :: get_endpoint ( ValidateCheckoutEndpoint :: ENDPOINT ),
'nonce' => wp_create_nonce ( ValidateCheckoutEndpoint :: nonce () ),
),
2024-04-10 17:05:33 +02:00
'cart_script_params' => array (
2023-02-15 16:50:34 +02:00
'endpoint' => \WC_AJAX :: get_endpoint ( CartScriptParamsEndpoint :: ENDPOINT ),
),
2024-04-10 17:05:33 +02:00
'create_setup_token' => array (
2024-04-06 17:31:57 +02:00
'endpoint' => \WC_AJAX :: get_endpoint ( CreateSetupToken :: ENDPOINT ),
'nonce' => wp_create_nonce ( CreateSetupToken :: nonce () ),
),
2024-04-10 17:05:33 +02:00
'create_payment_token' => array (
2024-04-06 17:31:57 +02:00
'endpoint' => \WC_AJAX :: get_endpoint ( CreatePaymentToken :: ENDPOINT ),
'nonce' => wp_create_nonce ( CreatePaymentToken :: nonce () ),
),
2024-04-09 17:34:51 +02:00
'create_payment_token_for_guest' => array (
'endpoint' => \WC_AJAX :: get_endpoint ( CreatePaymentTokenForGuest :: ENDPOINT ),
'nonce' => wp_create_nonce ( CreatePaymentTokenForGuest :: nonce () ),
),
2024-05-06 18:44:24 +04:00
'update_shipping' => array (
'endpoint' => \WC_AJAX :: get_endpoint ( UpdateShippingEndpoint :: ENDPOINT ),
'nonce' => wp_create_nonce ( UpdateShippingEndpoint :: nonce () ),
),
'update_customer_shipping' => array (
'shipping_options' => array (
2024-07-15 19:38:10 +04:00
'endpoint' => home_url ( UpdateShippingEndpoint :: WC_STORE_API_ENDPOINT . 'select-shipping-rate' ),
2024-05-06 18:44:24 +04:00
),
'shipping_address' => array (
2024-07-15 19:19:32 +04:00
'cart_endpoint' => home_url ( UpdateShippingEndpoint :: WC_STORE_API_ENDPOINT ),
2024-07-15 19:38:10 +04:00
'update_customer_endpoint' => home_url ( UpdateShippingEndpoint :: WC_STORE_API_ENDPOINT . 'update-customer' ),
2024-05-06 18:44:24 +04:00
),
'wp_rest_nonce' => wp_create_nonce ( 'wc_store_api' ),
'update_shipping_method' => \WC_AJAX :: get_endpoint ( 'update_shipping_method' ),
),
2020-08-27 11:08:36 +03:00
),
2024-01-11 12:29:36 +01:00
'cart_contains_subscription' => $this -> subscription_helper -> cart_contains_subscription (),
2023-07-13 16:22:57 +02:00
'subscription_plan_id' => $this -> subscription_helper -> paypal_subscription_id (),
2024-04-03 09:59:40 +02:00
'vault_v3_enabled' => $this -> vault_v3_enabled ,
2023-06-28 17:17:22 +02:00
'variable_paypal_subscription_variations' => $this -> subscription_helper -> variable_paypal_subscription_variations (),
2024-04-12 16:07:39 +02:00
'variable_paypal_subscription_variation_from_cart' => $this -> subscription_helper -> paypal_subscription_variation_from_cart (),
2023-08-09 15:38:46 +02:00
'subscription_product_allowed' => $this -> subscription_helper -> checkout_subscription_product_allowed (),
2023-11-13 17:36:18 +00:00
'locations_with_subscription_product' => $this -> subscription_helper -> locations_with_subscription_product (),
2023-07-13 16:22:57 +02:00
'enforce_vault' => $this -> has_subscriptions (),
'can_save_vault_token' => $this -> can_save_vault_token (),
'is_free_trial_cart' => $is_free_trial_cart ,
'vaulted_paypal_email' => ( is_checkout () && $is_free_trial_cart ) ? $this -> get_vaulted_paypal_email () : '' ,
'bn_codes' => $this -> bn_codes (),
'payer' => $this -> payerData (),
'button' => array (
2023-07-03 17:35:01 +01:00
'wrapper' => '#ppc-button-' . PayPalGateway :: ID ,
'is_disabled' => $this -> is_button_disabled (),
'mini_cart_wrapper' => '#ppc-button-minicart' ,
'is_mini_cart_disabled' => $this -> is_button_disabled ( 'mini-cart' ),
'cancel_wrapper' => '#ppcp-cancel' ,
2023-11-22 10:08:36 +02:00
'mini_cart_style' => $this -> normalize_style (
array (
'layout' => $this -> style_for_context ( 'layout' , 'mini-cart' ),
'color' => $this -> style_for_context ( 'color' , 'mini-cart' ),
'shape' => $this -> style_for_context ( 'shape' , 'mini-cart' ),
'label' => $this -> style_for_context ( 'label' , 'mini-cart' ),
'tagline' => $this -> style_for_context ( 'tagline' , 'mini-cart' ),
'height' => $this -> normalize_height ( $this -> style_for_context ( 'height' , 'mini-cart' , 35 ), 25 , 55 ),
)
2020-08-27 11:08:36 +03:00
),
2023-11-22 10:08:36 +02:00
'style' => $this -> normalize_style (
array (
'layout' => $this -> style_for_context ( 'layout' , $this -> context () ),
'color' => $this -> style_for_context ( 'color' , $this -> context () ),
'shape' => $this -> style_for_context ( 'shape' , $this -> context () ),
'label' => $this -> style_for_context ( 'label' , $this -> context () ),
'tagline' => $this -> style_for_context ( 'tagline' , $this -> context () ),
2023-11-22 17:25:24 +02:00
'height' => in_array ( $this -> context (), array ( 'cart-block' , 'checkout-block' ), true )
? $this -> normalize_height ( $this -> style_for_context ( 'height' , $this -> context (), 48 ), 40 , 55 )
: null ,
2023-11-22 10:08:36 +02:00
)
2020-08-27 11:08:36 +03:00
),
),
2023-07-13 16:22:57 +02:00
'separate_buttons' => array (
2022-07-19 09:20:26 +03:00
'card' => array (
'id' => CardButtonGateway :: ID ,
'wrapper' => '#ppc-button-' . CardButtonGateway :: ID ,
2023-11-22 10:08:36 +02:00
'style' => $this -> normalize_style (
array (
'shape' => $this -> style_for_apm ( 'shape' , 'card' ),
'color' => $this -> style_for_apm ( 'color' , 'card' , 'black' ),
'layout' => $this -> style_for_apm ( 'poweredby_tagline' , 'card' , false ) === $this -> normalize_style_value ( true ) ? 'vertical' : 'horizontal' ,
)
2022-07-19 09:20:26 +03:00
),
),
),
2023-07-13 16:22:57 +02:00
'hosted_fields' => array (
2022-07-18 16:27:06 +03:00
'wrapper' => '#ppcp-hosted-fields' ,
'labels' => array (
2021-11-30 11:11:02 +01:00
'credit_card_number' => '' ,
'cvv' => '' ,
'mm_yy' => __ ( 'MM/YY' , 'woocommerce-paypal-payments' ),
2023-05-09 12:01:26 +03:00
'fields_empty' => __ (
'Card payment details are missing. Please fill in all required fields.' ,
'woocommerce-paypal-payments'
),
2021-11-30 11:11:02 +01:00
'fields_not_valid' => __ (
2021-04-15 14:52:26 +02:00
'Unfortunately, your credit card details are not valid.' ,
2020-10-08 20:03:07 -03:00
'woocommerce-paypal-payments'
2020-08-27 11:08:36 +03:00
),
2021-11-30 11:11:02 +01:00
'card_not_supported' => __ (
2021-04-15 14:52:26 +02:00
'Unfortunately, we do not support your credit card.' ,
2020-10-08 20:03:07 -03:00
'woocommerce-paypal-payments'
2020-09-29 09:59:22 +03:00
),
2021-11-30 14:23:21 +01:00
'cardholder_name_required' => __ ( 'Cardholder\'s first and last name are required, please fill the checkout form required fields.' , 'woocommerce-paypal-payments' ),
2020-08-27 11:08:36 +03:00
),
2022-07-18 16:27:06 +03:00
'valid_cards' => $this -> dcc_applies -> valid_cards (),
'contingency' => $this -> get_3ds_contingency (),
2020-08-27 11:08:36 +03:00
),
2023-07-13 16:22:57 +02:00
'messages' => $this -> message_values (),
'labels' => array (
2022-07-22 11:48:53 +03:00
'error' => array (
'generic' => __ (
2020-08-27 11:08:36 +03:00
'Something went wrong. Please try again or choose another payment source.' ,
2020-10-08 20:03:07 -03:00
'woocommerce-paypal-payments'
2020-08-27 11:08:36 +03:00
),
2022-07-22 11:48:53 +03:00
'required' => array (
'generic' => __ (
'Required form fields are not filled.' ,
'woocommerce-paypal-payments'
),
// phpcs:ignore WordPress.WP.I18n
'field' => __ ( '%s is a required field.' , 'woocommerce' ),
'elements' => array ( // Map <form element name> => text for error messages.
'terms' => __ (
'Please read and accept the terms and conditions to proceed with your order.' ,
// phpcs:ignore WordPress.WP.I18n.TextDomainMismatch
'woocommerce'
),
),
2022-06-03 10:50:54 +03:00
),
2020-08-27 11:08:36 +03:00
),
2022-07-22 11:48:53 +03:00
// phpcs:ignore WordPress.WP.I18n
'billing_field' => _x ( 'Billing %s' , 'checkout-validation' , 'woocommerce' ),
// phpcs:ignore WordPress.WP.I18n
'shipping_field' => _x ( 'Shipping %s' , 'checkout-validation' , 'woocommerce' ),
2020-08-27 11:08:36 +03:00
),
2023-10-12 18:22:55 +01:00
'simulate_cart' => array (
'enabled' => apply_filters ( 'woocommerce_paypal_payments_simulate_cart_enabled' , true ),
'throttling' => apply_filters ( 'woocommerce_paypal_payments_simulate_cart_throttling' , 5000 ),
),
2023-07-13 16:22:57 +02:00
'order_id' => 'pay-now' === $this -> context () ? $this -> get_order_pay_id () : 0 ,
'single_product_buttons_enabled' => $this -> settings_status -> is_smart_button_enabled_for_location ( 'product' ),
'mini_cart_buttons_enabled' => $this -> settings_status -> is_smart_button_enabled_for_location ( 'mini-cart' ),
'basic_checkout_validation_enabled' => $this -> basic_checkout_validation_enabled ,
'early_checkout_validation_enabled' => $this -> early_validation_enabled ,
'funding_sources_without_redirect' => $this -> funding_sources_without_redirect ,
2024-01-16 16:05:03 +00:00
'user' => array (
2024-08-02 15:24:26 +02:00
'is_logged' => is_user_logged_in (),
'has_wc_card_payment_tokens' => $this -> user_has_wc_card_payment_tokens ( get_current_user_id () ),
2024-01-16 16:05:03 +00:00
),
2024-05-14 15:28:14 +04:00
'should_handle_shipping_in_paypal' => $this -> should_handle_shipping_in_paypal && ! $this -> is_checkout (),
2025-06-20 15:14:11 +03:00
'server_side_shipping_callback' => array (
'enabled' => $this -> server_side_shipping_callback_enabled ,
),
2025-07-15 10:49:12 -04:00
'appswitch' => array (
'enabled' => $this -> appswitch_enabled ,
),
2024-08-26 13:38:45 +02:00
'needShipping' => $this -> need_shipping (),
2024-05-17 00:07:13 +04:00
'vaultingEnabled' => $this -> settings -> has ( 'vault_enabled' ) && $this -> settings -> get ( 'vault_enabled' ),
2024-10-11 13:58:25 +02:00
'productType' => null ,
2024-10-22 17:00:46 +03:00
'manualRenewalEnabled' => $this -> subscription_helper -> accept_manual_renewals (),
2025-07-08 11:55:50 -04:00
'final_review_enabled' => $this -> final_review_enabled ,
2020-08-27 11:08:36 +03:00
);
2024-10-11 13:58:25 +02:00
if ( is_product () ) {
$product = wc_get_product ( get_the_ID () );
if ( is_a ( $product , \WC_Product :: class ) ) {
$localize [ 'productType' ] = $product -> get_type ();
}
}
2023-10-13 17:57:03 +01:00
if ( 'pay-now' === $this -> context () ) {
$localize [ 'pay_now' ] = $this -> pay_now_script_data ();
}
2023-04-07 15:58:59 +03:00
if ( $this -> is_paypal_continuation () ) {
$order = $this -> session_handler -> order ();
assert ( $order !== null );
$localize [ 'continuation' ] = array (
'order_id' => $order -> id (),
);
}
2020-08-31 11:12:46 +03:00
$this -> request_data -> dequeue_nonce_fix ();
2023-10-19 16:15:20 +02:00
return apply_filters ( 'woocommerce_paypal_payments_localized_script_data' , $localize );
2020-08-27 11:08:36 +03:00
}
2020-04-13 09:07:20 +03:00
2023-10-13 17:57:03 +01:00
/**
* Returns pay - now payment data .
*
* @ return array
*/
private function pay_now_script_data () : array {
$order_id = $this -> get_order_pay_id ();
$base_location = wc_get_base_location ();
$shop_country_code = $base_location [ 'country' ] ? ? '' ;
$currency_code = get_woocommerce_currency ();
$wc_order = wc_get_order ( $order_id );
if ( ! $wc_order instanceof WC_Order ) {
return array ();
}
$total = ( float ) $wc_order -> get_total ( 'numeric' );
return array (
'total' => $total ,
'total_str' => ( new Money ( $total , $currency_code ) ) -> value_str (),
'currency_code' => $currency_code ,
'country_code' => $shop_country_code ,
);
}
2020-08-31 11:12:46 +03:00
/**
* If we can find the payer data for a current customer , we will return it .
*
* @ return array | null
*/
2020-09-11 13:38:02 +03:00
private function payerData () {
2020-08-27 11:08:36 +03:00
$customer = WC () -> customer ;
2021-11-03 10:20:39 +02:00
if ( ! is_user_logged_in () || ! ( $customer instanceof \WC_Customer ) ) {
2020-08-27 11:08:36 +03:00
return null ;
}
2020-09-01 09:00:45 +03:00
return $this -> payer_factory -> from_customer ( $customer ) -> to_array ();
2020-08-27 11:08:36 +03:00
}
2020-08-31 11:12:46 +03:00
/**
2023-02-15 16:03:49 +02:00
* The JavaScript SDK url parameters .
2020-08-31 11:12:46 +03:00
*
2023-02-15 16:03:49 +02:00
* @ return array
2020-08-31 11:12:46 +03:00
*/
2023-02-15 16:03:49 +02:00
private function url_params () : array {
2023-05-17 11:29:29 +02:00
$context = $this -> context ();
try {
$intent = $this -> intent ();
} catch ( NotFoundException $exception ) {
$intent = 'capture' ;
}
2021-10-05 12:12:19 +02:00
2023-05-18 16:46:25 +02:00
$subscription_mode = $this -> settings -> has ( 'subscriptions_mode' ) ? $this -> settings -> get ( 'subscriptions_mode' ) : '' ;
$params = array (
2020-08-31 11:12:46 +03:00
'client-id' => $this -> client_id ,
2024-10-03 10:10:50 +03:00
'currency' => $this -> currency -> get (),
2020-10-08 07:28:43 +03:00
'integration-date' => PAYPAL_INTEGRATION_DATE ,
2020-08-27 11:08:36 +03:00
'components' => implode ( ',' , $this -> components () ),
2023-05-18 16:46:25 +02:00
'vault' => ( $this -> can_save_vault_token () || $this -> subscription_helper -> need_subscription_intent ( $subscription_mode ) ) ? 'true' : 'false' ,
2024-05-21 20:48:13 +04:00
'commit' => in_array ( $context , $this -> pay_now_contexts , true ) ? 'true' : 'false' ,
2023-05-17 11:29:29 +02:00
'intent' => $intent ,
2020-08-27 11:08:36 +03:00
);
2024-01-15 16:55:36 +00:00
if (
$this -> settings -> has ( 'subscriptions_mode' )
&& $this -> settings -> get ( 'subscriptions_mode' ) === 'vaulting_api'
&& apply_filters ( 'woocommerce_paypal_payments_save_payment_methods_eligible' , false )
) {
// Remove vault parameter to allow for Venmo with Save Payment Methods (Vault V3).
unset ( $params [ 'vault' ] );
}
2020-08-27 11:08:36 +03:00
if (
2020-10-16 13:32:26 +03:00
$this -> environment -> current_environment_is ( Environment :: SANDBOX )
2023-06-13 12:31:59 +03:00
&& defined ( 'WP_DEBUG' ) && \WP_DEBUG
2021-11-03 10:20:39 +02:00
&& WC () -> customer instanceof \WC_Customer && WC () -> customer -> get_billing_country ()
2020-10-21 08:58:02 +03:00
&& 2 === strlen ( WC () -> customer -> get_billing_country () )
2020-08-27 11:08:36 +03:00
) {
$params [ 'buyer-country' ] = WC () -> customer -> get_billing_country ();
}
2021-09-09 12:20:43 +02:00
2023-05-10 08:05:44 +03:00
if ( 'pay-now' === $this -> context () ) {
$wc_order_id = $this -> get_order_pay_id ();
if ( $wc_order_id ) {
$wc_order = wc_get_order ( $wc_order_id );
if ( $wc_order instanceof WC_Order ) {
$currency = $wc_order -> get_currency ();
if ( $currency ) {
$params [ 'currency' ] = $currency ;
}
}
}
}
2024-06-28 14:47:23 +02:00
$disabled_funding_sources = $this -> disabled_funding_sources -> sources ( $context );
2022-04-12 15:29:23 +03:00
2023-02-27 12:02:47 +02:00
$enable_funding = array ( 'venmo' );
2023-09-01 09:42:23 +03:00
if ( $this -> is_pay_later_button_enabled_for_location ( $context ) ) {
2023-02-27 12:02:47 +02:00
$enable_funding [] = 'paylater' ;
} else {
2024-06-28 14:47:23 +02:00
$disabled_funding_sources [] = 'paylater' ;
2022-10-31 15:59:17 +04:00
}
2024-06-28 14:47:23 +02:00
if ( count ( $disabled_funding_sources ) > 0 ) {
$params [ 'disable-funding' ] = implode ( ',' , array_unique ( $disabled_funding_sources ) );
2020-09-10 10:58:41 +03:00
}
2020-09-18 11:55:25 +03:00
2022-04-12 15:29:23 +03:00
if ( $this -> is_free_trial_cart () ) {
$enable_funding = array ();
}
2021-06-17 11:51:43 +02:00
if ( count ( $enable_funding ) > 0 ) {
$params [ 'enable-funding' ] = implode ( ',' , array_unique ( $enable_funding ) );
}
2023-10-31 18:03:55 +04:00
$locale = $this -> settings -> has ( 'smart_button_language' ) ? $this -> settings -> get ( 'smart_button_language' ) : '' ;
2023-11-01 19:47:58 +04:00
$locale = ( string ) apply_filters ( 'woocommerce_paypal_payments_smart_buttons_locale' , $locale );
2023-10-31 18:03:55 +04:00
if ( $locale ) {
$params [ 'locale' ] = $locale ;
2022-12-19 19:27:39 +04:00
}
2023-02-15 16:03:49 +02:00
return $params ;
2020-08-27 11:08:36 +03:00
}
2020-08-31 11:12:46 +03:00
/**
* The attributes we need to load for the JS SDK .
*
* @ return array
*/
2020-08-27 11:08:36 +03:00
private function attributes () : array {
2024-04-16 17:12:28 +04:00
$attributes = array (
2023-05-17 11:29:29 +02:00
'data-partner-attribution-id' => $this -> bn_code_for_context ( $this -> context () ),
2020-08-27 11:08:36 +03:00
);
2024-04-16 17:12:28 +04:00
$page_type_attribute = $this -> page_type_attribute ();
if ( $page_type_attribute ) {
$attributes [ 'data-page-type' ] = $page_type_attribute ;
}
return $attributes ;
}
/**
* Retrieves the value for page type attribute ( data - page - type ) used for the JS SDK .
*
* @ return string
*/
protected function page_type_attribute () : string {
if ( is_search () ) {
return 'search-results' ;
}
switch ( $this -> location () ) {
case 'product' :
return 'product-details' ;
case 'shop' :
return 'product-listing' ;
case 'home' :
return 'mini-cart' ;
case 'cart-block' :
case 'cart' :
return 'cart' ;
case 'checkout-block' :
case 'checkout' :
case 'pay-now' :
return 'checkout' ;
default :
return '' ;
}
2020-08-27 11:08:36 +03:00
}
/**
2020-08-31 11:12:46 +03:00
* What BN Code to use in a given context .
*
* @ param string $context The context .
2020-08-27 11:08:36 +03:00
* @ return string
*/
2020-08-31 11:12:46 +03:00
private function bn_code_for_context ( string $context ) : string {
$codes = $this -> bn_codes ();
2024-07-02 16:10:10 +02:00
2025-03-21 18:06:50 +04:00
return ( isset ( $codes [ $context ] ) ) ? $codes [ $context ] : $this -> partner_attribution -> get_bn_code ();
2020-08-27 11:08:36 +03:00
}
/**
2020-08-31 11:12:46 +03:00
* BN Codes to use .
2020-08-27 11:08:36 +03:00
*
* @ return array
*/
2024-07-02 16:10:10 +02:00
private function bn_codes () : array {
2024-07-02 17:38:25 +02:00
2025-03-21 18:06:50 +04:00
$bn_code = $this -> partner_attribution -> get_bn_code ();
2020-08-27 11:08:36 +03:00
return array (
2024-07-02 16:10:10 +02:00
'checkout' => $bn_code ,
'cart' => $bn_code ,
'mini-cart' => $bn_code ,
'product' => $bn_code ,
2020-08-27 11:08:36 +03:00
);
}
2020-08-31 11:12:46 +03:00
/**
* The JS SKD components we need to load .
*
* @ return array
*/
2020-08-27 11:08:36 +03:00
private function components () : array {
2020-09-03 11:40:44 +03:00
$components = array ();
2023-03-29 20:12:39 +03:00
if ( $this -> should_load_buttons () ) {
2020-09-03 11:48:25 +03:00
$components [] = 'buttons' ;
2022-07-19 09:20:26 +03:00
$components [] = 'funding-eligibility' ;
2020-09-03 11:48:25 +03:00
}
2023-10-16 21:39:54 +03:00
if ( $this -> should_load_messages () ) {
2020-09-03 11:48:25 +03:00
$components [] = 'messages' ;
}
2025-03-14 18:28:12 +01:00
// Card payments are only available on a checkout page.
if ( is_checkout () && $this -> dcc_configuration -> is_bcdc_enabled () ) {
2020-09-03 11:48:25 +03:00
$components [] = 'hosted-fields' ;
}
2025-03-12 17:04:38 +01:00
2023-08-24 10:58:42 +02:00
/**
* Filter to add further components from the extensions .
*
* @ internal Matches filter name in APM extension .
*
2024-11-27 17:35:07 +01:00
* @ param array $components The array of components already registered .
* @ param string $context The SmartButton context .
2023-08-24 10:58:42 +02:00
*/
2024-11-27 17:19:56 +01:00
return array_unique (
2024-11-27 17:35:07 +01:00
( array ) apply_filters (
'woocommerce_paypal_payments_sdk_components_hook' ,
$components ,
$this -> context ()
)
2024-11-27 17:19:56 +01:00
);
2020-09-03 11:48:25 +03:00
}
2020-08-31 11:12:46 +03:00
/**
2023-11-08 08:17:25 +02:00
* Determines the style for a given property in a given context .
2020-08-31 11:12:46 +03:00
*
2023-11-08 08:17:25 +02:00
* @ param string $style The name of the style property .
2020-08-31 11:12:46 +03:00
* @ param string $context The context .
2023-11-22 10:08:36 +02:00
* @ param ? mixed $default The default value .
2020-08-31 11:12:46 +03:00
*
2023-11-22 10:08:36 +02:00
* @ return string | int
2020-08-31 11:12:46 +03:00
*/
2023-11-22 10:08:36 +02:00
private function style_for_context ( string $style , string $context , $default = null ) {
2023-11-22 17:25:24 +02:00
if ( $context === 'checkout-block' ) {
$context = 'checkout-block-express' ;
}
2023-05-10 11:26:45 +03:00
2020-08-27 11:08:36 +03:00
$defaults = array (
'layout' => 'vertical' ,
'size' => 'responsive' ,
'color' => 'gold' ,
'shape' => 'pill' ,
'label' => 'paypal' ,
'tagline' => true ,
);
2022-12-05 18:12:15 +04:00
$enable_styling_per_location = $this -> settings -> has ( 'smart_button_enable_styling_per_location' ) && $this -> settings -> get ( 'smart_button_enable_styling_per_location' );
if ( ! $enable_styling_per_location ) {
$context = 'general' ;
}
2024-01-03 17:34:58 +00:00
return $this -> get_style_value ( " button_ { $context } _ { $style } " )
? ? $this -> get_style_value ( " button_ { $style } " )
2023-11-22 10:08:36 +02:00
? ? ( $default ? $this -> normalize_style_value ( $default ) : null )
2023-11-08 08:17:25 +02:00
? ? $this -> normalize_style_value ( $defaults [ $style ] ? ? '' );
}
2023-11-08 08:39:53 +02:00
/**
* Determines the style for a given property in a given APM .
*
* @ param string $style The name of the style property .
* @ param string $apm The APM name , such as 'card' .
* @ param ? mixed $default The default value .
*
2023-11-22 10:08:36 +02:00
* @ return string | int
2023-11-08 08:39:53 +02:00
*/
2023-11-22 10:08:36 +02:00
private function style_for_apm ( string $style , string $apm , $default = null ) {
2024-01-03 17:34:58 +00:00
return $this -> get_style_value ( " { $apm } _button_ { $style } " )
2023-11-08 08:39:53 +02:00
? ? ( $default ? $this -> normalize_style_value ( $default ) : null )
? ? $this -> style_for_context ( $style , 'checkout' );
}
2020-08-27 11:08:36 +03:00
2023-11-08 08:17:25 +02:00
/**
* Returns the style property value or null .
*
* @ param string $key The style property key in the settings .
2023-11-22 10:08:36 +02:00
* @ return string | int | null
2023-11-08 08:17:25 +02:00
*/
2023-11-22 10:08:36 +02:00
private function get_style_value ( string $key ) {
2023-11-08 08:17:25 +02:00
if ( ! $this -> settings -> has ( $key ) ) {
return null ;
}
return $this -> normalize_style_value ( $this -> settings -> get ( $key ) );
}
2020-08-27 11:08:36 +03:00
2023-11-08 08:17:25 +02:00
/**
* Converts the style property value to string .
*
* @ param mixed $value The style property value .
2023-11-22 10:08:36 +02:00
* @ return string | int
2023-11-08 08:17:25 +02:00
*/
2023-11-22 10:08:36 +02:00
private function normalize_style_value ( $value ) {
2020-08-27 11:08:36 +03:00
if ( is_bool ( $value ) ) {
$value = $value ? 'true' : 'false' ;
}
2023-11-22 10:08:36 +02:00
if ( is_int ( $value ) ) {
return $value ;
}
2020-09-02 12:47:53 +03:00
return ( string ) $value ;
2020-08-27 11:08:36 +03:00
}
2021-06-17 17:04:02 +02:00
/**
2023-11-22 10:08:36 +02:00
* Fixes the style .
*
* @ param array $style The style properties .
* @ return array
*/
private function normalize_style ( array $style ) : array {
if ( array_key_exists ( 'tagline' , $style ) && ( ! array_key_exists ( 'layout' , $style ) || $style [ 'layout' ] !== 'horizontal' ) ) {
$style [ 'tagline' ] = false ;
}
if ( array_key_exists ( 'height' , $style ) && ! $style [ 'height' ] ) {
unset ( $style [ 'height' ] );
}
return $style ;
}
/**
* Returns a number between min and max .
2021-06-17 17:04:02 +02:00
*
2023-11-22 10:08:36 +02:00
* @ param mixed $height The input value .
* @ param int $min The minimum value .
* @ param int $max The maximum value .
2021-06-17 17:04:02 +02:00
* @ return int The normalized output value .
*/
2023-11-22 10:08:36 +02:00
private function normalize_height ( $height , int $min , int $max ) : int {
$height = ( int ) $height ;
if ( $height < $min ) {
return $min ;
2021-06-17 17:04:02 +02:00
}
2023-11-22 10:08:36 +02:00
if ( $height > $max ) {
return $max ;
2021-06-17 17:04:02 +02:00
}
return $height ;
}
2021-07-26 20:13:05 +03:00
2021-07-26 09:58:54 +03:00
/**
2022-02-17 18:19:55 +02:00
* Returns the action name that PayPal button will use for rendering on the checkout page .
2021-07-26 09:58:54 +03:00
*
* @ return string Action name .
*/
2021-07-26 20:13:05 +03:00
private function checkout_button_renderer_hook () : string {
2022-02-17 18:19:55 +02:00
/**
* The filter returning the action name that PayPal button will use for rendering on the checkout page .
*/
2021-07-26 20:13:05 +03:00
return ( string ) apply_filters ( 'woocommerce_paypal_payments_checkout_button_renderer_hook' , 'woocommerce_review_order_after_payment' );
2021-07-26 09:58:54 +03:00
}
2021-07-26 20:13:05 +03:00
2021-07-26 10:27:34 +03:00
/**
2022-02-17 18:19:55 +02:00
* Returns the action name that PayPal DCC button will use for rendering on the checkout page .
2021-07-26 10:27:34 +03:00
*
* @ return string
*/
2021-07-26 20:13:05 +03:00
private function checkout_dcc_button_renderer_hook () : string {
2022-02-17 18:19:55 +02:00
/**
* The filter returning the action name that PayPal DCC button will use for rendering on the checkout page .
*/
2021-07-26 20:13:05 +03:00
return ( string ) apply_filters ( 'woocommerce_paypal_payments_checkout_dcc_renderer_hook' , 'woocommerce_review_order_after_submit' );
2021-07-26 10:27:34 +03:00
}
2021-07-26 20:13:05 +03:00
2021-07-26 10:31:11 +03:00
/**
2022-02-17 18:19:55 +02:00
* Returns the action name that PayPal button and Pay Later message will use for rendering on the pay - order page .
2021-07-26 10:31:11 +03:00
*
* @ return string
*/
2021-07-26 20:13:05 +03:00
private function pay_order_renderer_hook () : string {
2022-02-17 18:19:55 +02:00
/**
* The filter returning the action name that PayPal button and Pay Later message will use for rendering on the pay - order page .
*/
2021-07-26 20:13:05 +03:00
return ( string ) apply_filters ( 'woocommerce_paypal_payments_pay_order_dcc_renderer_hook' , 'woocommerce_pay_order_after_submit' );
2021-07-26 10:31:11 +03:00
}
2021-07-26 20:13:05 +03:00
2023-10-16 21:41:17 +03:00
/**
* Returns the action name that will be used for rendering Pay Later messages .
*
* @ param string $location The location name like 'checkout' , 'shop' . See render_message_wrapper_registrar .
* @ param string $default_hook The default name of the hook .
* @ param int $default_priority The default priority of the hook .
* @ return array An array with 'name' and 'priority' keys .
*/
private function messages_renderer_hook ( string $location , string $default_hook , int $default_priority ) : array {
2023-10-31 11:31:25 +02:00
$location_hook = $this -> location_to_hook ( $location );
2023-10-16 21:41:17 +03:00
/**
* The filter returning the action name that will be used for rendering Pay Later messages .
*/
$hook = ( string ) apply_filters (
2024-01-03 17:34:58 +00:00
" woocommerce_paypal_payments_ { $location_hook } _messages_renderer_hook " ,
2023-10-16 21:41:17 +03:00
$default_hook
);
/**
* The filter returning the action priority that will be used for rendering Pay Later messages .
*/
$priority = ( int ) apply_filters (
2024-01-03 17:34:58 +00:00
" woocommerce_paypal_payments_ { $location_hook } _messages_renderer_priority " ,
2023-10-16 21:41:17 +03:00
$default_priority
);
return array (
'name' => $hook ,
'priority' => $priority ,
);
}
2023-11-21 11:55:50 +00:00
/**
* Returns the block name that will be used for rendering Pay Later messages after .
*
* @ param string $location The location name like 'checkout' , 'shop' . See render_message_wrapper_registrar .
* @ param string $default_block The default name of the block .
* @ param int $default_priority The default priority of the 'render_block' hook .
* @ return array An array with 'blockName' and 'priority' keys .
*/
private function messages_renderer_block ( string $location , string $default_block , int $default_priority ) : array {
$location_hook = $this -> location_to_hook ( $location );
/**
* The filter returning the action name that will be used for rendering Pay Later messages .
*/
$block_name = ( string ) apply_filters (
2024-01-03 17:34:58 +00:00
" woocommerce_paypal_payments_ { $location_hook } _messages_renderer_block " ,
2023-11-21 11:55:50 +00:00
$default_block
);
/**
* The filter returning the action priority that will be used for rendering Pay Later messages .
*/
$priority = ( int ) apply_filters (
2024-01-03 17:34:58 +00:00
" woocommerce_paypal_payments_ { $location_hook } _messages_renderer_block_priority " ,
2023-11-21 11:55:50 +00:00
$default_priority
);
return array (
'blockName' => $block_name ,
'priority' => $priority ,
);
}
2021-07-26 10:18:43 +03:00
/**
2022-02-17 18:19:55 +02:00
* Returns action name that PayPal button will use for rendering next to Proceed to checkout button ( normally displayed in cart ) .
2021-07-26 10:18:43 +03:00
*
* @ return string
*/
2021-07-26 20:13:05 +03:00
private function proceed_to_checkout_button_renderer_hook () : string {
2022-02-17 18:19:55 +02:00
/**
* The filter returning the action name that PayPal button will use for rendering next to Proceed to checkout button ( normally displayed in cart ) .
*/
2021-07-26 10:18:43 +03:00
return ( string ) apply_filters (
2021-07-26 19:06:23 +03:00
'woocommerce_paypal_payments_proceed_to_checkout_button_renderer_hook' ,
2021-07-26 10:18:43 +03:00
'woocommerce_proceed_to_checkout'
);
}
2021-07-26 20:13:05 +03:00
2021-07-26 10:50:52 +03:00
/**
2022-02-17 18:19:55 +02:00
* Returns the action name that PayPal button will use for rendering in the WC mini cart .
2021-07-26 10:50:52 +03:00
*
* @ return string
*/
2021-07-26 20:13:05 +03:00
private function mini_cart_button_renderer_hook () : string {
2022-02-17 18:19:55 +02:00
/**
* The filter returning the action name that PayPal button will use for rendering in the WC mini cart .
*/
2021-07-26 10:50:52 +03:00
return ( string ) apply_filters (
'woocommerce_paypal_payments_mini_cart_button_renderer_hook' ,
'woocommerce_widget_shopping_cart_after_buttons'
);
}
2021-07-26 20:13:05 +03:00
2021-07-26 18:36:29 +03:00
/**
2022-02-17 18:19:55 +02:00
* Returns the action name that PayPal button and Pay Later message will use for rendering on the single product page .
2021-07-26 18:36:29 +03:00
*
* @ return string
*/
2021-07-26 20:13:05 +03:00
private function single_product_renderer_hook () : string {
2022-02-17 18:19:55 +02:00
/**
* The filter returning the action name that PayPal button and Pay Later message will use for rendering on the single product page .
*/
2021-07-26 20:13:05 +03:00
return ( string ) apply_filters ( 'woocommerce_paypal_payments_single_product_renderer_hook' , 'woocommerce_single_product_summary' );
2021-07-26 18:36:29 +03:00
}
2022-02-17 20:01:47 +04:00
/**
* Check if cart product price total is 0.
*
* @ return bool true if is 0 , otherwise false .
2022-04-18 18:16:22 +04:00
* @ psalm - suppress RedundantConditionGivenDocblockType
2022-02-17 20:01:47 +04:00
*/
protected function is_cart_price_total_zero () : bool {
2022-02-18 17:56:33 +04:00
// phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
2022-04-18 18:16:22 +04:00
return WC () -> cart && WC () -> cart -> get_total ( 'numeric' ) == 0 ;
2022-02-17 20:01:47 +04:00
}
2022-04-12 14:59:07 +03:00
2022-05-11 18:16:50 +03:00
/**
* Checks if PayPal buttons / messages can be rendered for the given product .
*
* @ param WC_Product $product The product .
*
* @ return bool
*/
protected function product_supports_payment ( WC_Product $product ) : bool {
/**
* The filter returning true if PayPal buttons / messages can be rendered for this product , or false otherwise .
*/
2022-06-01 18:17:51 +04:00
$in_stock = $product -> is_in_stock ();
2024-12-10 13:23:20 +01:00
if ( ! $in_stock && $product -> is_type ( 'variable' ) ) {
2022-06-01 18:17:51 +04:00
/**
* The method is defined in WC_Product_Variable class .
*
* @ psalm - suppress UndefinedMethod
*/
$variations = $product -> get_available_variations ( 'objects' );
$in_stock = $this -> has_in_stock_variation ( $variations );
}
2025-03-31 15:43:56 +02:00
$enable_button = ! $product -> is_type ( array ( 'external' , 'grouped' ) ) && $in_stock &&
! ( ( $product -> is_type ( 'subscription' ) || $product -> is_type ( 'variable-subscription' ) ) && ! empty ( $_GET [ 'switch-subscription' ] ) );
2022-06-01 18:17:51 +04:00
/**
* Allows to filter if PayPal buttons / messages can be rendered for the given product .
*/
2022-05-11 18:16:50 +03:00
return apply_filters (
'woocommerce_paypal_payments_product_supports_payment_request_button' ,
2025-03-31 15:43:56 +02:00
$enable_button ,
2022-05-11 18:16:50 +03:00
$product
);
2022-02-17 20:01:47 +04:00
}
2022-04-12 14:59:07 +03:00
2023-07-27 09:57:19 +01:00
/**
* Fills and returns the product context_data array to be used in filters .
*
2023-07-27 10:29:24 +01:00
* @ param array $context_data The context data for this filter .
2023-07-27 09:57:19 +01:00
* @ return array
*/
2023-07-27 10:29:24 +01:00
private function product_filter_context_data ( array $context_data = array () ) : array {
2023-07-27 09:57:19 +01:00
if ( ! isset ( $context_data [ 'product' ] ) ) {
$context_data [ 'product' ] = wc_get_product ();
}
if ( ! $context_data [ 'product' ] ) {
2023-07-27 10:29:24 +01:00
return array ();
2023-07-27 09:57:19 +01:00
}
if ( ! isset ( $context_data [ 'order_total' ] ) && ( $context_data [ 'product' ] instanceof WC_Product ) ) {
$context_data [ 'order_total' ] = ( float ) $context_data [ 'product' ] -> get_price ( 'raw' );
}
return $context_data ;
}
2023-07-03 08:31:27 +01:00
/**
* Checks if PayPal buttons / messages should be rendered for the current page .
*
2023-07-03 17:35:01 +01:00
* @ param string | null $context The context that should be checked , use default otherwise .
2023-07-27 10:29:24 +01:00
* @ param array $context_data The context data for this filter .
2023-07-03 08:31:27 +01:00
* @ return bool
*/
2023-07-27 10:29:24 +01:00
public function is_button_disabled ( string $context = null , array $context_data = array () ) : bool {
2023-07-03 17:35:01 +01:00
if ( null === $context ) {
$context = $this -> context ();
}
2023-07-03 11:40:37 +01:00
if ( 'product' === $context ) {
2023-07-27 10:29:24 +01:00
/**
* Allows to decide if the button should be disabled for a given product .
*/
2023-07-27 09:57:19 +01:00
return apply_filters (
2023-07-04 08:29:48 +01:00
'woocommerce_paypal_payments_product_buttons_disabled' ,
2023-07-27 09:57:19 +01:00
false ,
2023-07-27 10:29:24 +01:00
$this -> product_filter_context_data ( $context_data )
2023-07-03 17:35:01 +01:00
);
2023-07-03 08:25:35 +01:00
}
2023-07-27 10:29:24 +01:00
/**
* Allows to decide if the button should be disabled globally or on a given context .
*/
2023-07-27 09:57:19 +01:00
return apply_filters (
2023-07-04 08:29:48 +01:00
'woocommerce_paypal_payments_buttons_disabled' ,
2023-07-27 09:57:19 +01:00
false ,
$context
2023-07-03 17:35:01 +01:00
);
2023-07-03 08:25:35 +01:00
}
2023-07-13 11:59:31 +01:00
/**
* Checks a filter if pay_later / messages should be rendered on a given location / context .
*
2023-07-27 09:57:19 +01:00
* @ param string $location The location .
2023-07-27 10:29:24 +01:00
* @ param array $context_data The context data for this filter .
2023-07-13 11:59:31 +01:00
* @ return bool
*/
2023-07-27 10:29:24 +01:00
private function is_pay_later_filter_enabled_for_location ( string $location , array $context_data = array () ) : bool {
2023-07-13 11:59:31 +01:00
if ( 'product' === $location ) {
2023-07-27 10:29:24 +01:00
/**
* Allows to decide if the button should be disabled for a given product .
*/
2023-07-27 09:57:19 +01:00
return ! apply_filters (
2023-07-13 11:59:31 +01:00
'woocommerce_paypal_payments_product_buttons_paylater_disabled' ,
2023-07-27 09:57:19 +01:00
false ,
2023-07-27 10:29:24 +01:00
$this -> product_filter_context_data ( $context_data )
2023-07-13 11:59:31 +01:00
);
}
2023-07-27 10:29:24 +01:00
/**
* Allows to decide if the button should be disabled on a given context .
*/
2023-07-27 09:57:19 +01:00
return ! apply_filters (
2023-07-13 11:59:31 +01:00
'woocommerce_paypal_payments_buttons_paylater_disabled' ,
2023-07-27 09:57:19 +01:00
false ,
$location
2023-07-13 11:59:31 +01:00
);
}
/**
* Check whether Pay Later button is enabled for a given location .
*
2023-07-27 09:57:19 +01:00
* @ param string $location The location .
2023-07-27 10:29:24 +01:00
* @ param array $context_data The context data for this filter .
2023-07-13 11:59:31 +01:00
* @ return bool true if is enabled , otherwise false .
*/
2023-07-27 10:29:24 +01:00
public function is_pay_later_button_enabled_for_location ( string $location , array $context_data = array () ) : bool {
2023-07-27 09:57:19 +01:00
return $this -> is_pay_later_filter_enabled_for_location ( $location , $context_data )
2023-07-13 11:59:31 +01:00
&& $this -> settings_status -> is_pay_later_button_enabled_for_location ( $location );
}
/**
* Check whether Pay Later message is enabled for a given location .
*
2023-07-27 10:29:24 +01:00
* @ param string $location The location setting name .
* @ param array $context_data The context data for this filter .
2023-07-13 11:59:31 +01:00
* @ return bool true if is enabled , otherwise false .
*/
2023-07-27 10:29:24 +01:00
public function is_pay_later_messaging_enabled_for_location ( string $location , array $context_data = array () ) : bool {
2023-07-27 09:57:19 +01:00
return $this -> is_pay_later_filter_enabled_for_location ( $location , $context_data )
2023-07-13 11:59:31 +01:00
&& $this -> settings_status -> is_pay_later_messaging_enabled_for_location ( $location );
}
2022-04-12 14:59:07 +03:00
/**
* Retrieves all payment tokens for the user , via API or cached if already queried .
*
* @ return PaymentToken []
*/
private function get_payment_tokens () : array {
if ( null === $this -> payment_tokens ) {
$this -> payment_tokens = $this -> payment_token_repository -> all_for_user_id ( get_current_user_id () );
}
return $this -> payment_tokens ;
}
/**
* Returns the vaulted PayPal email or empty string .
*
* @ return string
*/
private function get_vaulted_paypal_email () : string {
try {
2024-04-04 16:52:08 +02:00
$customer_id = get_user_meta ( get_current_user_id (), '_ppcp_target_customer_id' , true );
if ( $customer_id ) {
$customer_tokens = $this -> payment_tokens_endpoint -> payment_tokens_for_customer ( $customer_id );
foreach ( $customer_tokens as $token ) {
$email_address = $token [ 'payment_source' ] -> properties () -> email_address ? ? '' ;
if ( $email_address ) {
return $email_address ;
}
}
}
2022-04-12 14:59:07 +03:00
2024-04-04 16:52:08 +02:00
$tokens = $this -> get_payment_tokens ();
2022-04-12 14:59:07 +03:00
foreach ( $tokens as $token ) {
if ( isset ( $token -> source () -> paypal ) ) {
return $token -> source () -> paypal -> payer -> email_address ;
}
}
} catch ( Exception $exception ) {
$this -> logger -> error ( 'Failed to get PayPal vaulted email. ' . $exception -> getMessage () );
}
2024-04-04 16:52:08 +02:00
2022-04-12 14:59:07 +03:00
return '' ;
}
2022-06-01 18:17:51 +04:00
/**
* Checks if variations contain any in stock variation .
*
* @ param WC_Product_Variation [] $variations The list of variations .
* @ return bool True if any in stock variation , false otherwise .
*/
protected function has_in_stock_variation ( array $variations ) : bool {
foreach ( $variations as $variation ) {
if ( $variation -> is_in_stock () ) {
return true ;
}
}
return false ;
}
2023-01-10 11:32:44 +01:00
2023-05-17 11:29:29 +02:00
/**
* Returns the intent .
*
* @ return string
* @ throws NotFoundException If intent is not found .
*/
private function intent () : string {
$subscription_mode = $this -> settings -> has ( 'subscriptions_mode' ) ? $this -> settings -> get ( 'subscriptions_mode' ) : '' ;
if ( $this -> subscription_helper -> need_subscription_intent ( $subscription_mode ) ) {
return 'subscription' ;
}
2023-09-19 12:19:31 +02:00
$intent = $this -> settings -> has ( 'intent' ) ? $this -> settings -> get ( 'intent' ) : 'capture' ;
2023-09-21 11:24:50 +02:00
return strtolower ( apply_filters ( 'woocommerce_paypal_payments_order_intent' , $intent ) );
2023-05-17 11:29:29 +02:00
}
2023-06-06 15:31:46 +03:00
2023-05-10 08:05:44 +03:00
/**
* Returns the ID of WC order on the order - pay page , or 0.
*
* @ return int
*/
protected function get_order_pay_id () : int {
global $wp ;
if ( ! isset ( $wp -> query_vars [ 'order-pay' ] ) ) {
return 0 ;
}
return absint ( $wp -> query_vars [ 'order-pay' ] );
}
2023-07-24 17:09:45 +01:00
/**
* Sanitize woocommerce filter on unexpected states .
*
* @ return void
*/
private function sanitize_woocommerce_filters () : void {
2023-07-24 17:24:34 +01:00
add_filter (
'woocommerce_widget_cart_is_hidden' ,
/**
* Sometimes external plugins like " woocommerce-one-page-checkout " set the $value to null , handle that case here .
* Here we also disable the mini - cart on cart - block and checkout - block pages where our buttons aren ' t supported yet .
*
* @ psalm - suppress MissingClosureParamType
*/
function ( $value ) {
if ( null === $value ) {
if ( is_product () ) {
return false ;
}
return in_array ( $this -> context (), array ( 'cart' , 'checkout' , 'cart-block' , 'checkout-block' ), true );
2023-07-24 17:09:45 +01:00
}
2023-07-24 17:24:34 +01:00
return in_array ( $this -> context (), array ( 'cart-block' , 'checkout-block' ), true ) ? true : $value ;
},
11
);
2023-07-24 17:09:45 +01:00
}
2023-10-31 11:31:25 +02:00
/**
* Converts the location name into the name used in hooks .
*
* @ param string $location The location .
* @ return string
*/
private function location_to_hook ( string $location ) : string {
switch ( $location ) {
case 'pay-now' :
return 'pay_order' ;
default :
return $location ;
}
}
2024-07-24 17:00:58 +02:00
/**
* Whether the given user has WC card payment tokens .
*
2024-08-02 15:24:26 +02:00
* @ param int $user_id The user ID .
2024-07-24 17:00:58 +02:00
* @ return bool
*/
2024-08-02 15:24:26 +02:00
private function user_has_wc_card_payment_tokens ( int $user_id ) : bool {
2024-07-24 17:00:58 +02:00
$tokens = WC_Payment_Tokens :: get_customer_tokens ( $user_id , CreditCardGateway :: ID );
2024-08-02 15:24:26 +02:00
if ( $tokens ) {
2024-07-24 17:00:58 +02:00
return true ;
}
return false ;
}
2020-04-06 11:16:18 +03:00
}