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 ;
2022-05-11 18:16:50 +03:00
use WC_Product ;
2022-06-01 18:17:51 +04:00
use WC_Product_Variation ;
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 ;
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies ;
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 ;
use WooCommerce\PayPalCommerce\Button\Endpoint\RequestData ;
2023-01-25 09:42:31 +02:00
use WooCommerce\PayPalCommerce\Button\Endpoint\SaveCheckoutFormEndpoint ;
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 ;
2020-09-11 14:11:10 +03:00
use WooCommerce\PayPalCommerce\Button\Helper\MessagesApply ;
2020-10-16 13:32:26 +03:00
use WooCommerce\PayPalCommerce\Onboarding\Environment ;
2020-09-11 14:11:10 +03:00
use WooCommerce\PayPalCommerce\Session\SessionHandler ;
2022-04-12 14:59:07 +03:00
use WooCommerce\PayPalCommerce\Subscription\FreeTrialHandlerTrait ;
2020-09-11 14:11:10 +03:00
use WooCommerce\PayPalCommerce\Subscription\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 ;
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
/**
* 3 - letter currency code of the shop .
*
* @ var string
*/
private $currency ;
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-01-04 12:13:26 +01:00
/**
* The intent .
*
* @ var string
*/
private $intent ;
/**
* The current context .
*
* @ var string
*/
private $context ;
2022-04-12 14:59:07 +03:00
/**
2023-01-04 12:40:24 +01:00
* Whether vault tokens could be saved .
2022-04-12 14:59:07 +03:00
*
2023-01-04 12:40:24 +01:00
* @ var bool
2022-04-12 14:59:07 +03:00
*/
2023-01-04 12:40:24 +01:00
private $can_save_vault_token ;
2022-04-12 14:59:07 +03:00
/**
2023-01-04 12:40:24 +01:00
* Whether vault could be enabled or not .
2022-04-12 14:59:07 +03:00
*
2023-01-04 12:40:24 +01:00
* @ var string
2022-04-12 14:59:07 +03:00
*/
2023-01-04 12:40:24 +01:00
private $vault ;
2023-04-24 08:15:22 +03:00
/**
* The contexts that should have the Pay Now button .
*
* @ var string []
*/
private $pay_now_contexts ;
2023-01-04 12:40:24 +01:00
/**
* The logger .
*
* @ var LoggerInterface
*/
private $logger ;
2023-05-02 14:28:36 +02:00
2022-04-12 14:59:07 +03:00
/**
2023-05-02 14:28:36 +02:00
* Session handler .
*
2023-03-17 09:20:51 +01:00
* @ var SessionHandler
2022-04-12 14:59:07 +03:00
*/
2023-03-17 09:20:51 +01:00
private $session_handler ;
2022-04-12 14:59:07 +03:00
2021-03-25 16:57:42 +01:00
/**
2020-08-31 11:12:46 +03:00
* SmartButton constructor .
*
2021-03-25 16:57:42 +01:00
* @ param string $module_url The URL to the module .
2023-05-02 14:28:36 +02:00
* @ param string $version The assets version .
* @ param SessionHandler $session_handler The Session handler .
2021-03-25 16:57:42 +01:00
* @ 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 .
2021-06-17 11:51:43 +02:00
* @ param SettingsStatus $settings_status The Settings status helper .
2021-11-30 10:40:38 +02:00
* @ param string $currency 3 - letter currency code of the shop .
2022-04-12 15:29:23 +03:00
* @ param array $all_funding_sources All existing funding sources .
2022-06-28 12:09:18 +03:00
* @ param bool $basic_checkout_validation_enabled Whether the basic JS validation of the form iss enabled .
2023-02-07 15:29:53 +02:00
* @ param bool $early_validation_enabled Whether to execute WC validation of the checkout form .
2023-01-04 12:13:26 +01:00
* @ param string $intent The intent .
* @ param string $context The current context .
2023-01-04 12:40:24 +01:00
* @ param bool $can_save_vault_token Whether vault tokens could be saved .
* @ param string $vault Whether vault could be enabled or not .
2023-04-24 08:15:22 +03:00
* @ param string [] $pay_now_contexts The contexts that should have the Pay Now button .
2022-04-12 14:59:07 +03:00
* @ param LoggerInterface $logger The logger .
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 ,
2022-04-12 14:59:07 +03:00
string $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-01-04 12:13:26 +01:00
string $intent ,
string $context ,
2023-01-04 12:40:24 +01:00
bool $can_save_vault_token ,
string $vault ,
2022-04-12 14:59:07 +03:00
LoggerInterface $logger
2020-08-27 11:08:36 +03:00
) {
2022-06-28 12:09:18 +03:00
$this -> module_url = $module_url ;
$this -> version = $version ;
2023-05-02 12:35:46 +02:00
$this -> session_handler = $session_handler ;
2022-06-28 12:09:18 +03:00
$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 ;
2023-02-07 15:29:53 +02:00
$this -> early_validation_enabled = $early_validation_enabled ;
2023-04-24 08:15:22 +03:00
$this -> pay_now_contexts = $pay_now_contexts ;
2023-01-04 12:13:26 +01:00
$this -> intent = $intent ;
2022-06-28 12:09:18 +03:00
$this -> logger = $logger ;
2023-01-04 12:13:26 +01:00
$this -> context = $context ;
2023-01-04 12:40:24 +01:00
$this -> can_save_vault_token = $can_save_vault_token ;
$this -> vault = $vault ;
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 {
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
}
if (
2020-09-02 13:52:40 +03:00
$this -> settings -> has ( 'dcc_enabled' )
&& $this -> settings -> get ( 'dcc_enabled' )
2020-08-27 11:08:36 +03:00
) {
add_action (
2021-07-26 10:27:34 +03:00
$this -> checkout_dcc_button_renderer_hook (),
2020-08-27 11:08:36 +03:00
array (
$this ,
2020-08-31 11:12:46 +03:00
'dcc_renderer' ,
2020-08-27 11:08:36 +03:00
),
11
);
2020-09-30 14:24:31 +03:00
add_action (
2021-07-26 18:32:16 +03:00
$this -> pay_order_renderer_hook (),
2020-09-30 14:24:31 +03:00
array (
$this ,
'dcc_renderer' ,
),
11
);
2021-02-16 17:06:50 +01:00
2021-11-19 11:06:16 +01:00
$subscription_helper = $this -> subscription_helper ;
2021-02-16 17:06:50 +01:00
add_filter (
'woocommerce_credit_card_form_fields' ,
2021-11-19 12:44:06 +02:00
function ( array $default_fields , $id ) use ( $subscription_helper ) : array {
2023-02-03 17:07:51 +01:00
if ( is_user_logged_in () && $this -> settings -> has ( 'vault_enabled_dcc' ) && $this -> settings -> get ( 'vault_enabled_dcc' ) && CreditCardGateway :: ID === $id ) {
2021-11-19 11:06:16 +01:00
2022-01-04 10:43:18 +01:00
$default_fields [ 'card-vault' ] = sprintf (
2022-01-11 10:31:47 +01:00
'<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>' ,
2022-01-04 10:43:18 +01:00
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' ] = '' ;
2021-11-19 11:06:16 +01:00
}
2021-03-25 16:11:45 +01:00
2021-05-19 15:39:33 +02:00
$tokens = $this -> payment_token_repository -> all_for_user_id ( get_current_user_id () );
if ( $tokens && $this -> payment_token_repository -> tokens_contains_card ( $tokens ) ) {
2021-03-25 16:57:42 +01:00
$output = sprintf (
2021-03-31 10:54:44 +02:00
'<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' ),
2021-04-01 13:55:14 +03:00
esc_html__ ( 'Choose a saved payment' , 'woocommerce-paypal-payments' )
2021-03-25 16:57:42 +01:00
);
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
);
}
}
2021-03-29 11:57:03 +02:00
$output .= '</select></p>' ;
2021-03-25 16:57:42 +01:00
$default_fields [ 'saved-credit-card' ] = $output ;
}
2021-02-16 17:06:50 +01:00
}
2021-03-25 16:11:45 +01:00
2021-02-16 17:06:50 +01:00
return $default_fields ;
},
10 ,
2
);
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
}
);
}
2020-08-27 11:08:36 +03:00
return true ;
}
2020-08-31 11:12:46 +03:00
/**
* Registers the hooks to render the credit messaging HTML depending on 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_message_wrapper_registrar () : bool {
2022-11-02 17:34:53 +04:00
if ( ! $this -> settings_status -> is_pay_later_messaging_enabled () ) {
2022-10-31 15:59:17 +04:00
return false ;
}
2020-08-27 11:08:36 +03:00
2022-10-31 15:59:17 +04:00
$selected_locations = $this -> settings -> has ( 'pay_later_messaging_locations' ) ? $this -> settings -> get ( 'pay_later_messaging_locations' ) : array ();
$not_enabled_on_cart = ! in_array ( 'cart' , $selected_locations , true );
2022-05-06 18:22:11 +04:00
add_action (
$this -> proceed_to_checkout_button_renderer_hook (),
function () use ( $not_enabled_on_cart ) {
if ( ! is_cart () || $not_enabled_on_cart ) {
return ;
}
$this -> message_renderer ();
},
19
);
2020-08-27 11:08:36 +03:00
2022-10-31 15:59:17 +04:00
$not_enabled_on_product_page = ! in_array ( 'product' , $selected_locations , true );
2020-08-27 11:08:36 +03:00
if (
( is_product () || wc_post_content_has_shortcode ( 'product_page' ) )
2020-08-31 11:12:46 +03:00
&& ! $not_enabled_on_product_page
2022-10-20 14:20:11 -03:00
&& ! is_checkout ()
2020-08-27 11:08:36 +03:00
) {
add_action (
2021-07-26 18:36:29 +03:00
$this -> single_product_renderer_hook (),
2022-10-31 15:59:17 +04:00
array ( $this , 'message_renderer' ),
2020-08-27 11:08:36 +03:00
30
);
}
2022-10-31 15:59:17 +04:00
$not_enabled_on_checkout = ! in_array ( 'checkout' , $selected_locations , true );
2020-08-31 11:12:46 +03:00
if ( ! $not_enabled_on_checkout ) {
2020-08-27 11:08:36 +03:00
add_action (
2021-07-26 18:23:25 +03:00
$this -> checkout_dcc_button_renderer_hook (),
2022-10-31 15:59:17 +04:00
array ( $this , 'message_renderer' ),
2020-08-27 11:08:36 +03:00
11
);
2020-09-30 14:24:31 +03:00
add_action (
2021-07-26 18:32:16 +03:00
$this -> pay_order_renderer_hook (),
2022-10-31 15:59:17 +04:00
array ( $this , 'message_renderer' ),
2023-02-27 12:03:32 +02:00
15
2020-09-30 14:24:31 +03:00
);
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 ;
}
2022-07-19 09:20:26 +03:00
$this -> button_renderer ( PayPalGateway :: ID );
},
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
2022-04-06 17:57:59 +04:00
echo ' < p
id = " ppc-button-minicart "
class = " woocommerce-mini-cart__buttons buttons "
></ p > ' ;
},
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 {
$this -> button_renderer ( PayPalGateway :: ID );
$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 {
$this -> button_renderer ( PayPalGateway :: ID );
$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 ) {
if ( ! is_cart () || ! $enabled_on_cart || $this -> is_free_trial_cart () || $this -> is_cart_price_total_zero () ) {
2022-06-27 15:47:21 +04:00
return ;
}
2022-07-26 19:11:07 +04:00
$this -> button_renderer ( PayPalGateway :: ID );
},
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 {
2020-08-31 11:12:46 +03:00
$buttons_enabled = $this -> settings -> has ( 'enabled' ) && $this -> settings -> get ( 'enabled' );
2023-03-29 20:12:39 +03:00
if ( ! $buttons_enabled ) {
2020-08-27 11:08:36 +03:00
return false ;
}
2020-09-03 11:40:44 +03:00
2023-03-29 20:15:42 +03:00
if ( in_array ( $this -> context (), array ( 'checkout-block' , 'cart-block' ), true ) ) {
return false ;
}
2023-03-29 20:12:39 +03:00
return $this -> should_load_buttons () || $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 {
$buttons_enabled = $this -> settings -> has ( 'enabled' ) && $this -> settings -> get ( 'enabled' );
if ( ! $buttons_enabled ) {
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' );
$messaging_enabled_for_current_location = $this -> settings_status -> is_pay_later_messaging_enabled_for_location ( $this -> context () );
switch ( $this -> context () ) {
case 'checkout' :
case 'cart' :
case 'pay-now' :
return $smart_button_enabled_for_current_location || $messaging_enabled_for_current_location ;
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' :
return $smart_button_enabled_for_current_location || $messaging_enabled_for_current_location || $smart_button_enabled_for_mini_cart ;
default :
return $smart_button_enabled_for_mini_cart ;
2020-09-03 11:48:25 +03:00
}
2023-03-29 20:12:39 +03:00
}
/**
* Whether DCC fields can be rendered .
*/
public function can_render_dcc () : bool {
return $this -> settings -> has ( 'dcc_enabled' ) && $this -> settings -> get ( 'dcc_enabled' )
&& $this -> settings -> has ( 'client_id' ) && $this -> settings -> get ( 'client_id' )
&& $this -> dcc_applies -> for_country_currency ()
&& in_array ( $this -> context (), array ( 'checkout' , 'pay-now' ), true );
}
/**
* 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-01-04 12:13:26 +01:00
if ( in_array ( $this -> context , array ( 'pay-now' , 'checkout' ), true ) ) {
2020-09-18 15:38:38 +03:00
wp_enqueue_style (
2022-10-20 13:13:42 +03:00
'gateway' ,
untrailingslashit ( $this -> module_url ) . '/assets/css/gateway.css' ,
2020-09-18 15:38:38 +03:00
array (),
2022-02-17 18:51:24 +02:00
$this -> version
2020-09-18 15:38:38 +03:00
);
}
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
*
* @ param string $gateway_id The gateway ID , like 'ppcp-gateway' .
2020-08-31 11:12:46 +03:00
*/
2022-07-19 09:20:26 +03:00
public function button_renderer ( string $gateway_id ) {
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.
2022-07-19 09:20:26 +03:00
echo '<div class="ppc-button-wrapper"><div id="ppc-button-' . esc_attr ( $gateway_id ) . '"></div></div>' ;
2020-08-27 11:08:36 +03:00
}
2020-08-31 11:12:46 +03:00
/**
* Renders the HTML for the credit messaging .
*/
public function message_renderer () {
2020-08-27 11:08:36 +03:00
2021-11-08 14:58:25 -05:00
$product = wc_get_product ();
if (
2022-05-11 18:16:50 +03:00
! is_checkout () && is_a ( $product , WC_Product :: class )
/**
* 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
2021-06-23 11:59:52 +02:00
echo '<div id="ppcp-messages" data-partner-attribution-id="Woo_PPCP"></div>' ;
2020-08-27 11:08:36 +03:00
}
2020-08-19 05:19:29 +03:00
2020-08-31 11:12:46 +03:00
/**
* The values for the credit messaging .
*
* @ return array
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 message_values () : array {
2022-11-02 17:34:53 +04:00
if ( ! $this -> settings_status -> is_pay_later_messaging_enabled () ) {
2020-08-27 11:08:36 +03:00
return array ();
}
2022-10-31 15:59:17 +04:00
$placement = is_checkout () ? 'payment' : ( is_cart () ? 'cart' : 'product' );
$product = wc_get_product ();
$amount = ( is_a ( $product , WC_Product :: class ) ) ? wc_get_price_including_tax ( $product ) : 0 ;
if ( is_checkout () || is_cart () ) {
$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' );
$per_location = is_checkout () ? 'checkout' : ( is_cart () ? 'cart' : 'product' );
$location = $styling_per_location ? $per_location : 'general' ;
$setting_name_prefix = " pay_later_ { $location } _message " ;
$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' ;
return array (
2020-08-27 11:08:36 +03:00
'wrapper' => '#ppcp-messages' ,
'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 ,
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
$id = 'ppcp-hosted-fields' ;
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-01-04 12:13:26 +01: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 (
2020-09-18 15:38:38 +03:00
' < div id = " %1 $s " style = " display:none; " >
2022-03-30 16:09:30 +03:00
< button type = " submit " class = " button alt ppcp-dcc-order-button " style = " display: none; " >% 2 $s </ button >
</ div >
< div id = " payments-sdk__contingency-lightbox " ></ div >
< style id = " ppcp-hide-dcc " >. payment_method_ppcp - credit - card - gateway { display : none ;} </ style > ' ,
2020-08-27 11:08:36 +03:00
esc_attr ( $id ),
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 {
if ( ! $this -> subscription_helper -> accept_only_automatic_payment_gateways () ) {
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 {
2023-05-15 16:18:11 +02:00
if ( defined ( 'PPCP_FLAG_SUBSCRIPTIONS_API' ) && ! PPCP_FLAG_SUBSCRIPTIONS_API ) {
return false ;
}
2023-01-16 12:37:16 +01:00
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 ) {
return $value ;
}
2021-08-20 17:47:32 +03:00
}
return 'SCA_WHEN_REQUIRED' ;
}
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 {
2020-09-30 14:24:31 +03:00
global $wp ;
2022-04-12 14:59:07 +03:00
$is_free_trial_cart = $this -> is_free_trial_cart ();
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-02-15 16:03:49 +02:00
'url' => add_query_arg ( $url_params , 'https://www.paypal.com/sdk/js' ),
'url_params' => $url_params ,
2022-06-28 12:09:18 +03:00
'script_attributes' => $this -> attributes (),
'data_client_id' => array (
2023-01-16 12:37:16 +01:00
'set_attribute' => ( is_checkout () && $this -> dcc_is_enabled () ) || $this -> can_save_vault_token ,
'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
),
2022-06-28 12:09:18 +03:00
'redirect' => wc_get_checkout_url (),
2023-01-04 12:13:26 +01:00
'context' => $this -> context ,
2022-06-28 12:09:18 +03:00
'ajax' => array (
2023-01-05 14:53:23 +01: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 () ),
),
2023-01-05 14:53:23 +01: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 () ),
),
2023-01-05 14:53:23 +01: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 () ),
),
2023-01-05 14:53:23 +01:00
'approve_subscription' => array (
'endpoint' => \WC_AJAX :: get_endpoint ( ApproveSubscriptionEndpoint :: ENDPOINT ),
'nonce' => wp_create_nonce ( ApproveSubscriptionEndpoint :: nonce () ),
),
'vault_paypal' => array (
2022-04-12 14:59:07 +03:00
'endpoint' => \WC_AJAX :: get_endpoint ( StartPayPalVaultingEndpoint :: ENDPOINT ),
'nonce' => wp_create_nonce ( StartPayPalVaultingEndpoint :: nonce () ),
),
2023-05-02 12:35:46 +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 () ),
),
2023-05-02 12:35:46 +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 () ),
),
2023-05-02 12:35:46 +02:00
'cart_script_params' => array (
2023-02-15 16:50:34 +02:00
'endpoint' => \WC_AJAX :: get_endpoint ( CartScriptParamsEndpoint :: ENDPOINT ),
),
2020-08-27 11:08:36 +03:00
),
2023-01-10 11:32:44 +01:00
'subscription_plan_id' => $this -> paypal_subscription_id (),
2022-06-28 12:09:18 +03:00
'enforce_vault' => $this -> has_subscriptions (),
2023-01-04 12:40:24 +01:00
'can_save_vault_token' => $this -> can_save_vault_token ,
2022-06-28 12:09:18 +03:00
'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 (
2022-07-19 09:20:26 +03:00
'wrapper' => '#ppc-button-' . PayPalGateway :: ID ,
2020-08-27 11:08:36 +03:00
'mini_cart_wrapper' => '#ppc-button-minicart' ,
'cancel_wrapper' => '#ppcp-cancel' ,
'mini_cart_style' => array (
2020-08-31 11:12:46 +03:00
'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' ),
2021-06-17 17:04:02 +02:00
'height' => $this -> settings -> has ( 'button_mini-cart_height' ) && $this -> settings -> get ( 'button_mini-cart_height' ) ? $this -> normalize_height ( ( int ) $this -> settings -> get ( 'button_mini-cart_height' ) ) : 35 ,
2020-08-27 11:08:36 +03:00
),
'style' => array (
2023-01-04 12:13:26 +01:00
'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 ),
2020-08-27 11:08:36 +03:00
),
),
2022-07-19 09:20:26 +03:00
'separate_buttons' => array (
'card' => array (
'id' => CardButtonGateway :: ID ,
'wrapper' => '#ppc-button-' . CardButtonGateway :: ID ,
'style' => array (
2023-01-04 12:13:26 +01:00
'shape' => $this -> style_for_context ( 'shape' , $this -> context ),
2022-07-19 09:20:26 +03:00
// TODO: color black, white from the gateway settings.
),
),
),
2022-06-28 12:09:18 +03: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' ),
'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
),
2022-06-28 12:09:18 +03: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-01-04 12:13:26 +01:00
'order_id' => 'pay-now' === $this -> context ? absint ( $wp -> query_vars [ 'order-pay' ] ) : 0 ,
2022-12-05 16:53:30 +04:00
'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' ),
2022-06-28 12:09:18 +03:00
'basic_checkout_validation_enabled' => $this -> basic_checkout_validation_enabled ,
2023-02-07 15:29:53 +02:00
'early_checkout_validation_enabled' => $this -> early_validation_enabled ,
2020-08-27 11:08:36 +03:00
);
2020-08-31 11:12:46 +03:00
if ( $this -> style_for_context ( 'layout' , 'mini-cart' ) !== 'horizontal' ) {
2022-08-09 09:44:26 +03:00
$localize [ 'button' ][ 'mini_cart_style' ][ 'tagline' ] = false ;
2020-08-27 11:08:36 +03:00
}
2023-01-04 12:13:26 +01:00
if ( $this -> style_for_context ( 'layout' , $this -> context ) !== 'horizontal' ) {
2022-08-09 09:44:26 +03:00
$localize [ 'button' ][ 'style' ][ 'tagline' ] = false ;
2020-08-27 11:08:36 +03:00
}
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 ();
2020-08-27 11:08:36 +03:00
return $localize ;
}
2020-04-13 09:07:20 +03:00
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-04-17 10:23:52 +03:00
$context = $this -> context ();
2022-07-04 17:30:29 +04:00
$intent = ( $this -> settings -> has ( 'intent' ) ) ? $this -> settings -> get ( 'intent' ) : 'capture' ;
$product_intent = $this -> subscription_helper -> current_product_is_subscription () ? 'authorize' : $intent ;
$other_context_intent = $this -> subscription_helper -> cart_contains_subscription () ? 'authorize' : $intent ;
2021-10-05 12:12:19 +02:00
2020-08-27 11:08:36 +03:00
$params = array (
2020-08-31 11:12:46 +03:00
'client-id' => $this -> client_id ,
2021-11-30 10:40:38 +02:00
'currency' => $this -> currency ,
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 () ),
2021-09-09 12:20:43 +02:00
'vault' => $this -> can_save_vault_token () ? 'true' : 'false' ,
2023-04-24 08:15:22 +03:00
'commit' => in_array ( $context , $this -> pay_now_contexts , true ) ? 'true' : 'false' ,
2023-04-17 10:23:52 +03:00
'intent' => $context === 'product' ? $product_intent : $other_context_intent ,
2020-08-27 11:08:36 +03:00
);
if (
2020-10-16 13:32:26 +03:00
$this -> environment -> current_environment_is ( Environment :: SANDBOX )
&& defined ( 'WP_DEBUG' ) && \WP_DEBUG && is_user_logged_in ()
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
$disable_funding = $this -> settings -> has ( 'disable_funding' )
? $this -> settings -> get ( 'disable_funding' )
: array ();
2020-08-27 11:08:36 +03:00
if ( ! is_checkout () ) {
2020-08-31 11:12:46 +03:00
$disable_funding [] = 'card' ;
2020-08-27 11:08:36 +03:00
}
2022-04-25 15:13:46 +03:00
$is_dcc_enabled = $this -> settings -> has ( 'dcc_enabled' ) && $this -> settings -> get ( 'dcc_enabled' );
2022-07-19 11:14:32 +03:00
$available_gateways = WC () -> payment_gateways -> get_available_payment_gateways ();
$is_separate_card_enabled = isset ( $available_gateways [ CardButtonGateway :: ID ] );
if ( is_checkout () && ( $is_dcc_enabled || $is_separate_card_enabled ) ) {
2021-09-09 12:20:43 +02:00
$key = array_search ( 'card' , $disable_funding , true );
if ( false !== $key ) {
unset ( $disable_funding [ $key ] );
}
}
2020-09-10 10:58:41 +03:00
2023-04-21 09:46:28 +03:00
if ( in_array ( $context , array ( 'checkout-block' , 'cart-block' ), true ) ) {
2023-04-27 15:45:39 +03:00
$disable_funding = array_diff (
array_keys ( $this -> all_funding_sources ),
array ( 'venmo' , 'paylater' )
);
2023-04-21 09:46:28 +03:00
}
2022-04-12 15:29:23 +03:00
if ( $this -> is_free_trial_cart () ) {
2022-05-30 15:09:41 +03:00
$all_sources = array_keys ( $this -> all_funding_sources );
2022-07-27 16:26:27 +03:00
if ( $is_dcc_enabled || $is_separate_card_enabled ) {
2022-05-30 15:09:41 +03:00
$all_sources = array_diff ( $all_sources , array ( 'card' ) );
2022-04-25 15:13:46 +03:00
}
$disable_funding = $all_sources ;
2022-04-12 15:29:23 +03:00
}
2023-02-27 12:02:47 +02:00
$enable_funding = array ( 'venmo' );
2023-04-17 10:23:52 +03:00
if ( $this -> settings_status -> is_pay_later_button_enabled_for_location ( $context ) ||
$this -> settings_status -> is_pay_later_messaging_enabled_for_location ( $context )
2023-02-27 12:02:47 +02:00
) {
$enable_funding [] = 'paylater' ;
} else {
$disable_funding [] = 'paylater' ;
2022-10-31 15:59:17 +04:00
}
2021-03-17 09:43:58 +01:00
if ( count ( $disable_funding ) > 0 ) {
$params [ 'disable-funding' ] = implode ( ',' , array_unique ( $disable_funding ) );
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-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 {
return array (
2023-01-04 12:13:26 +01:00
'data-partner-attribution-id' => $this -> bn_code_for_context ( $this -> context ),
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 {
2020-08-27 11:08:36 +03:00
2020-08-31 11:12:46 +03:00
$codes = $this -> bn_codes ();
2020-08-27 11:08:36 +03:00
return ( isset ( $codes [ $context ] ) ) ? $codes [ $context ] : '' ;
}
/**
2020-08-31 11:12:46 +03:00
* BN Codes to use .
2020-08-27 11:08:36 +03:00
*
* @ return array
*/
2020-08-31 11:12:46 +03:00
private function bn_codes () : array {
2020-08-27 11:08:36 +03:00
return array (
'checkout' => 'Woo_PPCP' ,
'cart' => 'Woo_PPCP' ,
'mini-cart' => 'Woo_PPCP' ,
'product' => 'Woo_PPCP' ,
);
}
2020-08-31 11:12:46 +03:00
/**
* The JS SKD components we need to load .
*
* @ return array
2022-10-31 15:59:17 +04:00
* @ throws NotFoundException If a setting was not found .
2020-08-31 11:12:46 +03:00
*/
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
}
2022-04-12 15:29:23 +03:00
if (
$this -> messages_apply -> for_country ()
&& ! $this -> is_free_trial_cart ()
) {
2020-09-03 11:48:25 +03:00
$components [] = 'messages' ;
}
if ( $this -> dcc_is_enabled () ) {
$components [] = 'hosted-fields' ;
}
return $components ;
}
2020-08-31 11:12:46 +03:00
/**
* Whether DCC is enabled or not .
*
* @ return bool
*/
private function dcc_is_enabled () : bool {
2020-10-01 11:37:36 +03:00
if ( ! is_checkout () ) {
return false ;
}
2020-09-01 09:00:45 +03:00
if ( ! $this -> dcc_applies -> for_country_currency () ) {
2020-08-27 11:08:36 +03:00
return false ;
}
$keys = array (
2020-10-01 11:37:36 +03:00
'client_id' ,
'client_secret' ,
'dcc_enabled' ,
2020-08-27 11:08:36 +03:00
);
2020-10-01 11:37:36 +03:00
foreach ( $keys as $key ) {
if ( ! $this -> settings -> has ( $key ) || ! $this -> settings -> get ( $key ) ) {
return false ;
2020-08-27 11:08:36 +03:00
}
}
2020-10-01 11:37:36 +03:00
return true ;
2020-08-27 11:08:36 +03:00
}
2020-08-31 11:12:46 +03:00
/**
* Determines the style for a given indicator in a given context .
*
* @ param string $style The style .
* @ param string $context The context .
*
* @ return string
*/
private function style_for_context ( string $style , string $context ) : string {
2023-05-10 11:26:45 +03:00
// Use the cart/checkout styles for blocks.
$context = str_replace ( '-block' , '' , $context );
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' ;
}
2020-08-27 11:08:36 +03:00
$value = isset ( $defaults [ $style ] ) ?
$defaults [ $style ] : '' ;
$value = $this -> settings -> has ( 'button_' . $style ) ?
$this -> settings -> get ( 'button_' . $style ) : $value ;
$value = $this -> settings -> has ( 'button_' . $context . '_' . $style ) ?
$this -> settings -> get ( 'button_' . $context . '_' . $style ) : $value ;
if ( is_bool ( $value ) ) {
$value = $value ? 'true' : 'false' ;
}
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
/**
* Returns a value between 25 and 55.
*
* @ param int $height The input value .
* @ return int The normalized output value .
*/
private function normalize_height ( int $height ) : int {
if ( $height < 25 ) {
return 25 ;
}
if ( $height > 55 ) {
return 55 ;
}
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
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 ();
if ( $product -> is_type ( 'variable' ) ) {
/**
* 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 );
}
/**
* 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' ,
2022-06-01 18:17:51 +04:00
! $product -> is_type ( array ( 'external' , 'grouped' ) ) && $in_stock ,
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
/**
* 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 {
$tokens = $this -> get_payment_tokens ();
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 () );
}
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
/**
* Returns PayPal subscription plan id from WC subscription product .
*
2023-01-10 11:39:09 +01:00
* @ return string
2023-01-10 11:32:44 +01:00
*/
private function paypal_subscription_id () : string {
2023-05-02 12:35:46 +02:00
if ( $this -> subscription_helper -> current_product_is_subscription () ) {
2023-03-20 11:58:34 +01:00
$product = wc_get_product ();
assert ( $product instanceof WC_Product );
if ( $product -> get_type () === 'subscription' && $product -> meta_exists ( 'ppcp_subscription_plan' ) ) {
return $product -> get_meta ( 'ppcp_subscription_plan' )[ 'id' ];
}
}
2023-01-10 11:32:44 +01:00
$items = WC () -> cart -> get_cart_contents ();
foreach ( $items as $item ) {
$product = wc_get_product ( $item [ 'product_id' ] );
assert ( $product instanceof WC_Product );
if ( $product -> get_type () === 'subscription' && $product -> meta_exists ( 'ppcp_subscription_plan' ) ) {
2023-03-20 11:58:34 +01:00
return $product -> get_meta ( 'ppcp_subscription_plan' )[ 'id' ];
2023-01-10 11:32:44 +01:00
}
}
return '' ;
}
2020-04-06 11:16:18 +03:00
}