mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-05 08:59:14 +08:00
Merge branch 'trunk' into feat/PCP-154-apple-pay-payment
# Conflicts: # modules/ppcp-applepay/resources/js/ApplepayButton.js # modules/ppcp-applepay/resources/js/ApplepayManager.js # modules/ppcp-applepay/resources/js/boot-block.js # modules/ppcp-applepay/resources/js/boot.js
This commit is contained in:
commit
30fb86406f
57 changed files with 2232 additions and 292 deletions
|
@ -39,7 +39,7 @@ return function ( string $root_dir ): iterable {
|
||||||
if ( apply_filters(
|
if ( apply_filters(
|
||||||
//phpcs:disable WordPress.NamingConventions.ValidHookName.UseUnderscores
|
//phpcs:disable WordPress.NamingConventions.ValidHookName.UseUnderscores
|
||||||
'woocommerce.feature-flags.woocommerce_paypal_payments.googlepay_enabled',
|
'woocommerce.feature-flags.woocommerce_paypal_payments.googlepay_enabled',
|
||||||
getenv( 'PCP_GOOGLEPAY_ENABLED' ) === '1'
|
getenv( 'PCP_GOOGLEPAY_ENABLED' ) !== '0'
|
||||||
) ) {
|
) ) {
|
||||||
$modules[] = ( require "$modules_dir/ppcp-googlepay/module.php" )();
|
$modules[] = ( require "$modules_dir/ppcp-googlepay/module.php" )();
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace WooCommerce\PayPalCommerce\ApiClient;
|
namespace WooCommerce\PayPalCommerce\ApiClient;
|
||||||
|
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Helper\FailureRegistry;
|
||||||
use WooCommerce\PayPalCommerce\Common\Pattern\SingletonDecorator;
|
use WooCommerce\PayPalCommerce\Common\Pattern\SingletonDecorator;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingSubscriptions;
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingSubscriptions;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\CatalogProducts;
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\CatalogProducts;
|
||||||
|
@ -120,7 +121,8 @@ return array(
|
||||||
$container->get( 'woocommerce.logger.woocommerce' ),
|
$container->get( 'woocommerce.logger.woocommerce' ),
|
||||||
$container->get( 'api.factory.sellerstatus' ),
|
$container->get( 'api.factory.sellerstatus' ),
|
||||||
$container->get( 'api.partner_merchant_id' ),
|
$container->get( 'api.partner_merchant_id' ),
|
||||||
$container->get( 'api.merchant_id' )
|
$container->get( 'api.merchant_id' ),
|
||||||
|
$container->get( 'api.helper.failure-registry' )
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
'api.factory.sellerstatus' => static function ( ContainerInterface $container ) : SellerStatusFactory {
|
'api.factory.sellerstatus' => static function ( ContainerInterface $container ) : SellerStatusFactory {
|
||||||
|
@ -846,6 +848,10 @@ return array(
|
||||||
$purchase_unit_sanitizer = $container->get( 'api.helper.purchase-unit-sanitizer' );
|
$purchase_unit_sanitizer = $container->get( 'api.helper.purchase-unit-sanitizer' );
|
||||||
return new OrderTransient( $cache, $purchase_unit_sanitizer );
|
return new OrderTransient( $cache, $purchase_unit_sanitizer );
|
||||||
},
|
},
|
||||||
|
'api.helper.failure-registry' => static function( ContainerInterface $container ): FailureRegistry {
|
||||||
|
$cache = new Cache( 'ppcp-paypal-api-status-cache' );
|
||||||
|
return new FailureRegistry( $cache );
|
||||||
|
},
|
||||||
'api.helper.purchase-unit-sanitizer' => SingletonDecorator::make(
|
'api.helper.purchase-unit-sanitizer' => SingletonDecorator::make(
|
||||||
static function( ContainerInterface $container ): PurchaseUnitSanitizer {
|
static function( ContainerInterface $container ): PurchaseUnitSanitizer {
|
||||||
$settings = $container->get( 'wcgateway.settings' );
|
$settings = $container->get( 'wcgateway.settings' );
|
||||||
|
|
|
@ -10,6 +10,7 @@ declare(strict_types=1);
|
||||||
namespace WooCommerce\PayPalCommerce\ApiClient;
|
namespace WooCommerce\PayPalCommerce\ApiClient;
|
||||||
|
|
||||||
use WC_Order;
|
use WC_Order;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Helper\FailureRegistry;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\OrderTransient;
|
use WooCommerce\PayPalCommerce\ApiClient\Helper\OrderTransient;
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider;
|
use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider;
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
||||||
|
@ -81,6 +82,18 @@ class ApiModule implements ModuleInterface {
|
||||||
10,
|
10,
|
||||||
2
|
2
|
||||||
);
|
);
|
||||||
|
add_action(
|
||||||
|
'woocommerce_paypal_payments_clear_apm_product_status',
|
||||||
|
function () use ( $c ) {
|
||||||
|
$failure_registry = $c->has( 'api.helper.failure-registry' ) ? $c->get( 'api.helper.failure-registry' ) : null;
|
||||||
|
|
||||||
|
if ( $failure_registry instanceof FailureRegistry ) {
|
||||||
|
$failure_registry->clear_failures( FailureRegistry::SELLER_STATUS_KEY );
|
||||||
|
}
|
||||||
|
},
|
||||||
|
10,
|
||||||
|
2
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -15,6 +15,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatus;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\SellerStatusFactory;
|
use WooCommerce\PayPalCommerce\ApiClient\Factory\SellerStatusFactory;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Helper\FailureRegistry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class PartnersEndpoint
|
* Class PartnersEndpoint
|
||||||
|
@ -65,6 +66,13 @@ class PartnersEndpoint {
|
||||||
*/
|
*/
|
||||||
private $merchant_id;
|
private $merchant_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The failure registry.
|
||||||
|
*
|
||||||
|
* @var FailureRegistry
|
||||||
|
*/
|
||||||
|
private $failure_registry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PartnersEndpoint constructor.
|
* PartnersEndpoint constructor.
|
||||||
*
|
*
|
||||||
|
@ -74,6 +82,7 @@ class PartnersEndpoint {
|
||||||
* @param SellerStatusFactory $seller_status_factory The seller status factory.
|
* @param SellerStatusFactory $seller_status_factory The seller status factory.
|
||||||
* @param string $partner_id The partner ID.
|
* @param string $partner_id The partner ID.
|
||||||
* @param string $merchant_id The merchant ID.
|
* @param string $merchant_id The merchant ID.
|
||||||
|
* @param FailureRegistry $failure_registry The API failure registry.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
string $host,
|
string $host,
|
||||||
|
@ -81,7 +90,8 @@ class PartnersEndpoint {
|
||||||
LoggerInterface $logger,
|
LoggerInterface $logger,
|
||||||
SellerStatusFactory $seller_status_factory,
|
SellerStatusFactory $seller_status_factory,
|
||||||
string $partner_id,
|
string $partner_id,
|
||||||
string $merchant_id
|
string $merchant_id,
|
||||||
|
FailureRegistry $failure_registry
|
||||||
) {
|
) {
|
||||||
$this->host = $host;
|
$this->host = $host;
|
||||||
$this->bearer = $bearer;
|
$this->bearer = $bearer;
|
||||||
|
@ -89,6 +99,7 @@ class PartnersEndpoint {
|
||||||
$this->seller_status_factory = $seller_status_factory;
|
$this->seller_status_factory = $seller_status_factory;
|
||||||
$this->partner_id = $partner_id;
|
$this->partner_id = $partner_id;
|
||||||
$this->merchant_id = $merchant_id;
|
$this->merchant_id = $merchant_id;
|
||||||
|
$this->failure_registry = $failure_registry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -140,9 +151,15 @@ class PartnersEndpoint {
|
||||||
'response' => $response,
|
'response' => $response,
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Register the failure on api failure registry.
|
||||||
|
$this->failure_registry->add_failure( FailureRegistry::SELLER_STATUS_KEY );
|
||||||
|
|
||||||
throw $error;
|
throw $error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$this->failure_registry->clear_failures( FailureRegistry::SELLER_STATUS_KEY );
|
||||||
|
|
||||||
$status = $this->seller_status_factory->from_paypal_reponse( $json );
|
$status = $this->seller_status_factory->from_paypal_reponse( $json );
|
||||||
return $status;
|
return $status;
|
||||||
}
|
}
|
||||||
|
|
94
modules/ppcp-api-client/src/Helper/FailureRegistry.php
Normal file
94
modules/ppcp-api-client/src/Helper/FailureRegistry.php
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Failure registry.
|
||||||
|
*
|
||||||
|
* This class is used to remember API failures.
|
||||||
|
* Mostly to prevent multiple failed API requests.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\ApiClient\Helper
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\ApiClient\Helper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class FailureRegistry
|
||||||
|
*/
|
||||||
|
class FailureRegistry {
|
||||||
|
const CACHE_KEY = 'failure_registry';
|
||||||
|
const CACHE_TIMEOUT = 60 * 60 * 24; // DAY_IN_SECONDS, if necessary we can increase this.
|
||||||
|
|
||||||
|
const SELLER_STATUS_KEY = 'seller_status';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Cache.
|
||||||
|
*
|
||||||
|
* @var Cache
|
||||||
|
*/
|
||||||
|
private $cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FailureRegistry constructor.
|
||||||
|
*
|
||||||
|
* @param Cache $cache The Cache.
|
||||||
|
*/
|
||||||
|
public function __construct( Cache $cache ) {
|
||||||
|
$this->cache = $cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if there was a failure within a given timeframe.
|
||||||
|
*
|
||||||
|
* @param string $key The cache key.
|
||||||
|
* @param int $seconds The timeframe in seconds.
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function has_failure_in_timeframe( string $key, int $seconds ): bool {
|
||||||
|
$cache_key = $this->cache_key( $key );
|
||||||
|
$failure_time = $this->cache->get( $cache_key );
|
||||||
|
|
||||||
|
if ( ! $failure_time ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$expiration = $failure_time + $seconds;
|
||||||
|
return $expiration > time();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a failure.
|
||||||
|
*
|
||||||
|
* @param string $key The cache key.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function add_failure( string $key ) {
|
||||||
|
$cache_key = $this->cache_key( $key );
|
||||||
|
$this->cache->set( $cache_key, time(), self::CACHE_TIMEOUT );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear a given failure.
|
||||||
|
*
|
||||||
|
* @param string $key The cache key.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function clear_failures( string $key ) {
|
||||||
|
$cache_key = $this->cache_key( $key );
|
||||||
|
if ( $this->cache->has( $cache_key ) ) {
|
||||||
|
$this->cache->delete( $cache_key );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build cache key.
|
||||||
|
*
|
||||||
|
* @param string $key The cache key.
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function cache_key( string $key ): string {
|
||||||
|
return implode( '_', array( self::CACHE_KEY, $key ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -17,11 +17,11 @@ use WC_Order;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class OrderHelper
|
* Class OrderTransient
|
||||||
*/
|
*/
|
||||||
class OrderTransient {
|
class OrderTransient {
|
||||||
const CACHE_KEY = 'order_transient';
|
const CACHE_KEY = 'order_transient';
|
||||||
const CACHE_TIMEOUT = DAY_IN_SECONDS; // If necessary we can increase this.
|
const CACHE_TIMEOUT = 60 * 60 * 24; // DAY_IN_SECONDS, if necessary we can increase this.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Cache.
|
* The Cache.
|
||||||
|
|
|
@ -13,10 +13,20 @@ use WooCommerce\PayPalCommerce\Applepay\Assets\PropertiesDictionary;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Helper\DisplayManager;
|
use WooCommerce\PayPalCommerce\WcGateway\Helper\DisplayManager;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||||
|
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'wcgateway.settings.fields' => function ( ContainerInterface $container, array $fields ): array {
|
'wcgateway.settings.fields' => function ( ContainerInterface $container, array $fields ): array {
|
||||||
|
|
||||||
|
// Eligibility check.
|
||||||
|
if ( ! $container->has( 'applepay.eligible' ) || ! $container->get( 'applepay.eligible' ) ) {
|
||||||
|
return $fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
$is_available = $container->get( 'applepay.enabled' );
|
||||||
|
$is_referral = $container->get( 'applepay.is_referral' );
|
||||||
|
|
||||||
$insert_after = function ( array $array, string $key, array $new ): array {
|
$insert_after = function ( array $array, string $key, array $new ): array {
|
||||||
$keys = array_keys( $array );
|
$keys = array_keys( $array );
|
||||||
$index = array_search( $key, $keys, true );
|
$index = array_search( $key, $keys, true );
|
||||||
|
@ -27,9 +37,27 @@ return array(
|
||||||
$display_manager = $container->get( 'wcgateway.display-manager' );
|
$display_manager = $container->get( 'wcgateway.display-manager' );
|
||||||
assert( $display_manager instanceof DisplayManager );
|
assert( $display_manager instanceof DisplayManager );
|
||||||
|
|
||||||
if ( ! $container->has( 'applepay.eligible' ) || ! $container->get( 'applepay.eligible' ) ) {
|
// Connection tab fields.
|
||||||
|
$fields = $insert_after(
|
||||||
|
$fields,
|
||||||
|
'ppcp_dcc_status',
|
||||||
|
array(
|
||||||
|
'applepay_status' => array(
|
||||||
|
'title' => __( 'Apple Pay Payments', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'ppcp-text',
|
||||||
|
'text' => $container->get( 'applepay.settings.connection.status-text' ),
|
||||||
|
'screens' => array(
|
||||||
|
State::STATE_ONBOARDED,
|
||||||
|
),
|
||||||
|
'requirements' => array(),
|
||||||
|
'gateway' => Settings::CONNECTION_TAB_ID,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( ! $is_available && $is_referral ) {
|
||||||
$connection_url = admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway&ppcp-tab=ppcp-connection#field-credentials_feature_onboarding_heading' );
|
$connection_url = admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway&ppcp-tab=ppcp-connection#field-credentials_feature_onboarding_heading' );
|
||||||
$connection_link = '<a href="' . $connection_url . '" target="_blank">';
|
$connection_link = '<a href="' . $connection_url . '" style="pointer-events: auto">';
|
||||||
return $insert_after(
|
return $insert_after(
|
||||||
$fields,
|
$fields,
|
||||||
'allow_card_button_gateway',
|
'allow_card_button_gateway',
|
||||||
|
@ -57,7 +85,7 @@ return array(
|
||||||
array(
|
array(
|
||||||
$display_manager
|
$display_manager
|
||||||
->rule()
|
->rule()
|
||||||
->condition_element( 'applepay_button_enabled', '1' )
|
->condition_is_true( false )
|
||||||
->action_enable( 'applepay_button_enabled' )
|
->action_enable( 'applepay_button_enabled' )
|
||||||
->to_array(),
|
->to_array(),
|
||||||
)
|
)
|
||||||
|
|
|
@ -31,6 +31,12 @@ class ApplepayButton {
|
||||||
this.updated_contact_info = []
|
this.updated_contact_info = []
|
||||||
this.selectedShippingMethod = []
|
this.selectedShippingMethod = []
|
||||||
this.nonce = document.getElementById('woocommerce-process-checkout-nonce').value
|
this.nonce = document.getElementById('woocommerce-process-checkout-nonce').value
|
||||||
|
|
||||||
|
this.log = function() {
|
||||||
|
if ( this.buttonConfig.is_debug ) {
|
||||||
|
console.log('[ApplePayButton]', ...arguments);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init(config) {
|
init(config) {
|
||||||
|
@ -52,12 +58,12 @@ class ApplepayButton {
|
||||||
const id = "#apple-" + this.buttonConfig.button.wrapper;
|
const id = "#apple-" + this.buttonConfig.button.wrapper;
|
||||||
|
|
||||||
if (this.context === 'mini-cart') {
|
if (this.context === 'mini-cart') {
|
||||||
document.querySelector(id_minicart).addEventListener('click', (evt) => {
|
document.querySelector(id_minicart)?.addEventListener('click', (evt) => {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
this.onButtonClick();
|
this.onButtonClick();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
document.querySelector(id).addEventListener('click', (evt) => {
|
document.querySelector(id)?.addEventListener('click', (evt) => {
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
this.onButtonClick();
|
this.onButtonClick();
|
||||||
});
|
});
|
||||||
|
@ -149,7 +155,10 @@ class ApplepayButton {
|
||||||
const language = this.buttonConfig.button.lang;
|
const language = this.buttonConfig.button.lang;
|
||||||
const color = this.buttonConfig.button.color;
|
const color = this.buttonConfig.button.color;
|
||||||
const id = "apple-" + wrapper;
|
const id = "apple-" + wrapper;
|
||||||
appleContainer.innerHTML = `<apple-pay-button id="${id}" buttonstyle="${color}" type="${type}" locale="${language}">`;
|
|
||||||
|
if (appleContainer) {
|
||||||
|
appleContainer.innerHTML = `<apple-pay-button id="${id}" buttonstyle="${color}" type="${type}" locale="${language}">`;
|
||||||
|
}
|
||||||
|
|
||||||
jQuery('#' + wrapper).addClass('ppcp-button-' + shape);
|
jQuery('#' + wrapper).addClass('ppcp-button-' + shape);
|
||||||
jQuery(wrapper).append(appleContainer);
|
jQuery(wrapper).append(appleContainer);
|
||||||
|
@ -256,6 +265,7 @@ class ApplepayButton {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.catch(validateError => {
|
.catch(validateError => {
|
||||||
|
console.error(validateError);
|
||||||
//call backend to update validation to false
|
//call backend to update validation to false
|
||||||
jQuery.ajax({
|
jQuery.ajax({
|
||||||
url: this.buttonConfig.ajax_url,
|
url: this.buttonConfig.ajax_url,
|
||||||
|
|
|
@ -16,6 +16,9 @@ use WooCommerce\PayPalCommerce\Applepay\Assets\AppleProductStatus;
|
||||||
use WooCommerce\PayPalCommerce\Applepay\Assets\DataToAppleButtonScripts;
|
use WooCommerce\PayPalCommerce\Applepay\Assets\DataToAppleButtonScripts;
|
||||||
use WooCommerce\PayPalCommerce\Applepay\Assets\BlocksPaymentMethod;
|
use WooCommerce\PayPalCommerce\Applepay\Assets\BlocksPaymentMethod;
|
||||||
use WooCommerce\PayPalCommerce\Applepay\Helper\ApmApplies;
|
use WooCommerce\PayPalCommerce\Applepay\Helper\ApmApplies;
|
||||||
|
use WooCommerce\PayPalCommerce\Googlepay\Helper\ApmProductStatus;
|
||||||
|
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||||
|
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||||
|
|
||||||
|
@ -36,12 +39,21 @@ return array(
|
||||||
'applepay.status-cache' => static function( ContainerInterface $container ): Cache {
|
'applepay.status-cache' => static function( ContainerInterface $container ): Cache {
|
||||||
return new Cache( 'ppcp-paypal-apple-status-cache' );
|
return new Cache( 'ppcp-paypal-apple-status-cache' );
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// We assume it's a referral if we can check product status without API request failures.
|
||||||
|
'applepay.is_referral' => static function ( ContainerInterface $container ): bool {
|
||||||
|
$status = $container->get( 'applepay.apple-product-status' );
|
||||||
|
assert( $status instanceof AppleProductStatus );
|
||||||
|
|
||||||
|
return ! $status->has_request_failure();
|
||||||
|
},
|
||||||
'applepay.apple-product-status' => static function( ContainerInterface $container ): AppleProductStatus {
|
'applepay.apple-product-status' => static function( ContainerInterface $container ): AppleProductStatus {
|
||||||
return new AppleProductStatus(
|
return new AppleProductStatus(
|
||||||
$container->get( 'wcgateway.settings' ),
|
$container->get( 'wcgateway.settings' ),
|
||||||
$container->get( 'api.endpoint.partners' ),
|
$container->get( 'api.endpoint.partners' ),
|
||||||
$container->get( 'applepay.status-cache' ),
|
$container->get( 'applepay.status-cache' ),
|
||||||
$container->get( 'onboarding.state' )
|
$container->get( 'onboarding.state' ),
|
||||||
|
$container->get( 'api.helper.failure-registry' )
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
'applepay.enabled' => static function ( ContainerInterface $container ): bool {
|
'applepay.enabled' => static function ( ContainerInterface $container ): bool {
|
||||||
|
@ -116,4 +128,52 @@ return array(
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'applepay.enable-url-sandbox' => static function ( ContainerInterface $container ): string {
|
||||||
|
return 'https://www.sandbox.paypal.com/bizsignup/add-product?product=payment_methods&capabilities=APPLE_PAY';
|
||||||
|
},
|
||||||
|
|
||||||
|
'applepay.enable-url-live' => static function ( ContainerInterface $container ): string {
|
||||||
|
return 'https://www.paypal.com/bizsignup/add-product?product=payment_methods&capabilities=APPLE_PAY';
|
||||||
|
},
|
||||||
|
|
||||||
|
'applepay.settings.connection.status-text' => static function ( ContainerInterface $container ): string {
|
||||||
|
$state = $container->get( 'onboarding.state' );
|
||||||
|
if ( $state->current_state() < State::STATE_ONBOARDED ) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$product_status = $container->get( 'applepay.apple-product-status' );
|
||||||
|
assert( $product_status instanceof AppleProductStatus );
|
||||||
|
|
||||||
|
$environment = $container->get( 'onboarding.environment' );
|
||||||
|
assert( $environment instanceof Environment );
|
||||||
|
|
||||||
|
$enabled = $product_status->apple_is_active();
|
||||||
|
|
||||||
|
$enabled_status_text = esc_html__( 'Status: Available', 'woocommerce-paypal-payments' );
|
||||||
|
$disabled_status_text = esc_html__( 'Status: Not yet enabled', 'woocommerce-paypal-payments' );
|
||||||
|
|
||||||
|
$button_text = $enabled
|
||||||
|
? esc_html__( 'Settings', 'woocommerce-paypal-payments' )
|
||||||
|
: esc_html__( 'Enable Apple Pay', 'woocommerce-paypal-payments' );
|
||||||
|
|
||||||
|
$enable_url = $environment->current_environment_is( Environment::PRODUCTION )
|
||||||
|
? $container->get( 'applepay.enable-url-live' )
|
||||||
|
: $container->get( 'applepay.enable-url-sandbox' );
|
||||||
|
|
||||||
|
$button_url = $enabled
|
||||||
|
? admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway#field-alternative_payment_methods' )
|
||||||
|
: $enable_url;
|
||||||
|
|
||||||
|
return sprintf(
|
||||||
|
'<p>%1$s %2$s</p><p><a target="%3$s" href="%4$s" class="button">%5$s</a></p>',
|
||||||
|
$enabled ? $enabled_status_text : $disabled_status_text,
|
||||||
|
$enabled ? '<span class="dashicons dashicons-yes"></span>' : '<span class="dashicons dashicons-no"></span>',
|
||||||
|
$enabled ? '_self' : '_blank',
|
||||||
|
esc_url( $button_url ),
|
||||||
|
esc_html( $button_text )
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
|
@ -147,6 +147,19 @@ class ApplePayButton implements ButtonInterface {
|
||||||
*/
|
*/
|
||||||
public function initialize(): void {
|
public function initialize(): void {
|
||||||
add_filter( 'ppcp_onboarding_options', array( $this, 'add_apple_onboarding_option' ), 10, 1 );
|
add_filter( 'ppcp_onboarding_options', array( $this, 'add_apple_onboarding_option' ), 10, 1 );
|
||||||
|
add_filter(
|
||||||
|
'ppcp_partner_referrals_option',
|
||||||
|
function ( array $option ): array {
|
||||||
|
if ( $option['valid'] ) {
|
||||||
|
return $option;
|
||||||
|
}
|
||||||
|
if ( $option['field'] === 'ppcp-onboarding-apple' ) {
|
||||||
|
$option['valid'] = true;
|
||||||
|
$option['value'] = ( $option['value'] ? '1' : '' );
|
||||||
|
}
|
||||||
|
return $option;
|
||||||
|
}
|
||||||
|
);
|
||||||
add_filter(
|
add_filter(
|
||||||
'ppcp_partner_referrals_data',
|
'ppcp_partner_referrals_data',
|
||||||
function ( array $data ): array {
|
function ( array $data ): array {
|
||||||
|
@ -165,7 +178,6 @@ class ApplePayButton implements ButtonInterface {
|
||||||
$data['products'][0] = 'PAYMENT_METHODS';
|
$data['products'][0] = 'PAYMENT_METHODS';
|
||||||
}
|
}
|
||||||
$data['capabilities'][] = 'APPLE_PAY';
|
$data['capabilities'][] = 'APPLE_PAY';
|
||||||
$nonce = $data['operations'][0]['api_integration_preference']['rest_api_integration']['first_party_details']['seller_nonce'];
|
|
||||||
$data['operations'][] = array(
|
$data['operations'][] = array(
|
||||||
'operation' => 'API_INTEGRATION',
|
'operation' => 'API_INTEGRATION',
|
||||||
'api_integration_preference' => array(
|
'api_integration_preference' => array(
|
||||||
|
@ -173,11 +185,10 @@ class ApplePayButton implements ButtonInterface {
|
||||||
'integration_method' => 'PAYPAL',
|
'integration_method' => 'PAYPAL',
|
||||||
'integration_type' => 'THIRD_PARTY',
|
'integration_type' => 'THIRD_PARTY',
|
||||||
'third_party_details' => array(
|
'third_party_details' => array(
|
||||||
'features' => array(
|
'features' => array(
|
||||||
'PAYMENT',
|
'PAYMENT',
|
||||||
'REFUND',
|
'REFUND',
|
||||||
),
|
),
|
||||||
'seller_nonce' => $nonce,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -196,6 +207,10 @@ class ApplePayButton implements ButtonInterface {
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function add_apple_onboarding_option( $options ): string {
|
public function add_apple_onboarding_option( $options ): string {
|
||||||
|
if ( ! apply_filters( 'woocommerce_paypal_payments_apple_pay_onboarding_option', false ) ) {
|
||||||
|
return $options;
|
||||||
|
}
|
||||||
|
|
||||||
$checked = '';
|
$checked = '';
|
||||||
try {
|
try {
|
||||||
$onboard_with_apple = $this->settings->get( 'ppcp-onboarding-apple' );
|
$onboard_with_apple = $this->settings->get( 'ppcp-onboarding-apple' );
|
||||||
|
@ -206,7 +221,7 @@ class ApplePayButton implements ButtonInterface {
|
||||||
$checked = '';
|
$checked = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
return $options . '<li><label><input type="checkbox" id="ppcp-onboarding-apple" ' . $checked . '> ' .
|
return $options . '<li><label><input type="checkbox" id="ppcp-onboarding-apple" ' . $checked . ' data-onboarding-option="ppcp-onboarding-apple"> ' .
|
||||||
__( 'Onboard with ApplePay', 'woocommerce-paypal-payments' ) . '
|
__( 'Onboard with ApplePay', 'woocommerce-paypal-payments' ) . '
|
||||||
</label></li>';
|
</label></li>';
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,8 @@ namespace WooCommerce\PayPalCommerce\Applepay\Assets;
|
||||||
|
|
||||||
use Throwable;
|
use Throwable;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnersEndpoint;
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnersEndpoint;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatusProduct;
|
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
|
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Helper\FailureRegistry;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||||
|
|
||||||
|
@ -36,6 +36,14 @@ class AppleProductStatus {
|
||||||
* @var bool|null
|
* @var bool|null
|
||||||
*/
|
*/
|
||||||
private $current_status_cache;
|
private $current_status_cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If there was a request failure.
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $has_request_failure = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The settings.
|
* The settings.
|
||||||
*
|
*
|
||||||
|
@ -57,6 +65,13 @@ class AppleProductStatus {
|
||||||
*/
|
*/
|
||||||
private $onboarding_state;
|
private $onboarding_state;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The API failure registry
|
||||||
|
*
|
||||||
|
* @var FailureRegistry
|
||||||
|
*/
|
||||||
|
private $api_failure_registry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PayUponInvoiceProductStatus constructor.
|
* PayUponInvoiceProductStatus constructor.
|
||||||
*
|
*
|
||||||
|
@ -64,17 +79,20 @@ class AppleProductStatus {
|
||||||
* @param PartnersEndpoint $partners_endpoint The Partner Endpoint.
|
* @param PartnersEndpoint $partners_endpoint The Partner Endpoint.
|
||||||
* @param Cache $cache The cache.
|
* @param Cache $cache The cache.
|
||||||
* @param State $onboarding_state The onboarding state.
|
* @param State $onboarding_state The onboarding state.
|
||||||
|
* @param FailureRegistry $api_failure_registry The API failure registry.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
Settings $settings,
|
Settings $settings,
|
||||||
PartnersEndpoint $partners_endpoint,
|
PartnersEndpoint $partners_endpoint,
|
||||||
Cache $cache,
|
Cache $cache,
|
||||||
State $onboarding_state
|
State $onboarding_state,
|
||||||
|
FailureRegistry $api_failure_registry
|
||||||
) {
|
) {
|
||||||
$this->settings = $settings;
|
$this->settings = $settings;
|
||||||
$this->partners_endpoint = $partners_endpoint;
|
$this->partners_endpoint = $partners_endpoint;
|
||||||
$this->cache = $cache;
|
$this->cache = $cache;
|
||||||
$this->onboarding_state = $onboarding_state;
|
$this->onboarding_state = $onboarding_state;
|
||||||
|
$this->api_failure_registry = $api_failure_registry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -99,9 +117,17 @@ class AppleProductStatus {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check API failure registry to prevent multiple failed API requests.
|
||||||
|
if ( $this->api_failure_registry->has_failure_in_timeframe( FailureRegistry::SELLER_STATUS_KEY, HOUR_IN_SECONDS ) ) {
|
||||||
|
$this->has_request_failure = true;
|
||||||
|
$this->current_status_cache = false;
|
||||||
|
return $this->current_status_cache;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$seller_status = $this->partners_endpoint->seller_status();
|
$seller_status = $this->partners_endpoint->seller_status();
|
||||||
} catch ( Throwable $error ) {
|
} catch ( Throwable $error ) {
|
||||||
|
$this->has_request_failure = true;
|
||||||
$this->current_status_cache = false;
|
$this->current_status_cache = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -124,4 +150,14 @@ class AppleProductStatus {
|
||||||
$this->current_status_cache = false;
|
$this->current_status_cache = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if there was a request failure.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function has_request_failure(): bool {
|
||||||
|
return $this->has_request_failure;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,6 +127,7 @@ class DataToAppleButtonScripts {
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'sdk_url' => $this->sdk_url,
|
'sdk_url' => $this->sdk_url,
|
||||||
|
'is_debug' => defined( 'WP_DEBUG' ) && WP_DEBUG ? true : false,
|
||||||
'button' => array(
|
'button' => array(
|
||||||
'wrapper' => 'applepay-container',
|
'wrapper' => 'applepay-container',
|
||||||
'mini_cart_wrapper' => 'applepay-container-minicart',
|
'mini_cart_wrapper' => 'applepay-container-minicart',
|
||||||
|
@ -180,6 +181,7 @@ class DataToAppleButtonScripts {
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'sdk_url' => $this->sdk_url,
|
'sdk_url' => $this->sdk_url,
|
||||||
|
'is_debug' => defined( 'WP_DEBUG' ) && WP_DEBUG ? true : false,
|
||||||
'button' => array(
|
'button' => array(
|
||||||
'wrapper' => 'applepay-container',
|
'wrapper' => 'applepay-container',
|
||||||
'mini_cart_wrapper' => 'applepay-container-minicart',
|
'mini_cart_wrapper' => 'applepay-container-minicart',
|
||||||
|
|
|
@ -7,3 +7,7 @@
|
||||||
-webkit-filter: grayscale(100%);
|
-webkit-filter: grayscale(100%);
|
||||||
filter: grayscale(100%);
|
filter: grayscale(100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ppc-button-wrapper #ppcp-messages:first-child {
|
||||||
|
padding-top: 10px;
|
||||||
|
}
|
||||||
|
|
|
@ -156,8 +156,15 @@ class CheckoutBootstap {
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldShowMessages() {
|
shouldShowMessages() {
|
||||||
return getCurrentPaymentMethod() === PaymentMethods.PAYPAL
|
// hide when another method selected only if messages are near buttons
|
||||||
&& !PayPalCommerceGateway.is_free_trial_cart;
|
const messagesWrapper = document.querySelector(this.gateway.messages.wrapper);
|
||||||
|
if (getCurrentPaymentMethod() !== PaymentMethods.PAYPAL &&
|
||||||
|
messagesWrapper && jQuery(messagesWrapper).closest('.ppc-button-wrapper').length
|
||||||
|
) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !PayPalCommerceGateway.is_free_trial_cart;
|
||||||
}
|
}
|
||||||
|
|
||||||
disableCreditCardFields() {
|
disableCreditCardFields() {
|
||||||
|
|
|
@ -28,15 +28,9 @@ class MessageRenderer {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const newWrapper = document.createElement('div');
|
const wrapper = document.querySelector(this.config.wrapper);
|
||||||
newWrapper.setAttribute('id', this.config.wrapper.replace('#', ''));
|
|
||||||
this.currentNumber++;
|
this.currentNumber++;
|
||||||
newWrapper.setAttribute('data-render-number', this.currentNumber);
|
wrapper.setAttribute('data-render-number', this.currentNumber);
|
||||||
|
|
||||||
const oldWrapper = document.querySelector(this.config.wrapper);
|
|
||||||
const sibling = oldWrapper.nextSibling;
|
|
||||||
oldWrapper.parentElement.removeChild(oldWrapper);
|
|
||||||
sibling.parentElement.insertBefore(newWrapper, sibling);
|
|
||||||
|
|
||||||
widgetBuilder.registerMessages(this.config.wrapper, options);
|
widgetBuilder.registerMessages(this.config.wrapper, options);
|
||||||
widgetBuilder.renderMessages(this.config.wrapper);
|
widgetBuilder.renderMessages(this.config.wrapper);
|
||||||
|
|
|
@ -27,6 +27,7 @@ class WidgetBuilder {
|
||||||
|
|
||||||
setPaypal(paypal) {
|
setPaypal(paypal) {
|
||||||
this.paypal = paypal;
|
this.paypal = paypal;
|
||||||
|
jQuery(document).trigger('ppcp-paypal-loaded', paypal);
|
||||||
}
|
}
|
||||||
|
|
||||||
registerButtons(wrapper, options) {
|
registerButtons(wrapper, options) {
|
||||||
|
@ -84,11 +85,14 @@ class WidgetBuilder {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const entry = this.messages.get(wrapper);
|
||||||
|
|
||||||
if (this.hasRendered(wrapper)) {
|
if (this.hasRendered(wrapper)) {
|
||||||
|
const element = document.querySelector(wrapper);
|
||||||
|
element.setAttribute('data-pp-amount', entry.options.amount);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const entry = this.messages.get(wrapper);
|
|
||||||
const btn = this.paypal.Messages(entry.options);
|
const btn = this.paypal.Messages(entry.options);
|
||||||
|
|
||||||
btn.render(entry.wrapper);
|
btn.render(entry.wrapper);
|
||||||
|
@ -174,4 +178,5 @@ class WidgetBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new WidgetBuilder();
|
window.widgetBuilder = window.widgetBuilder || new WidgetBuilder();
|
||||||
|
export default window.widgetBuilder;
|
||||||
|
|
|
@ -14,6 +14,7 @@ use Psr\Log\LoggerInterface;
|
||||||
use WC_Order;
|
use WC_Order;
|
||||||
use WC_Product;
|
use WC_Product;
|
||||||
use WC_Product_Variation;
|
use WC_Product_Variation;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Money;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken;
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory;
|
use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
|
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
|
||||||
|
@ -382,54 +383,48 @@ class SmartButton implements SmartButtonInterface {
|
||||||
* Registers the hooks to render the credit messaging HTML depending on the settings.
|
* Registers the hooks to render the credit messaging HTML depending on the settings.
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
* @throws NotFoundException When a setting was not found.
|
|
||||||
*/
|
*/
|
||||||
private function render_message_wrapper_registrar(): bool {
|
private function render_message_wrapper_registrar(): bool {
|
||||||
if ( ! $this->settings_status->is_pay_later_messaging_enabled() ) {
|
if ( ! $this->settings_status->is_pay_later_messaging_enabled() ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$selected_locations = $this->settings->has( 'pay_later_messaging_locations' ) ? $this->settings->get( 'pay_later_messaging_locations' ) : array();
|
$location = $this->location();
|
||||||
|
|
||||||
$not_enabled_on_cart = ! in_array( 'cart', $selected_locations, true );
|
if ( ! $this->settings_status->is_pay_later_messaging_enabled_for_location( $location ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$get_hook = function ( string $location ): ?array {
|
||||||
|
switch ( $location ) {
|
||||||
|
case 'checkout':
|
||||||
|
return $this->messages_renderer_hook( $location, 'woocommerce_review_order_before_payment', 10 );
|
||||||
|
case 'cart':
|
||||||
|
return $this->messages_renderer_hook( $location, $this->proceed_to_checkout_button_renderer_hook(), 19 );
|
||||||
|
case 'pay-now':
|
||||||
|
return $this->messages_renderer_hook( 'pay_order', 'woocommerce_pay_order_before_submit', 10 );
|
||||||
|
case 'product':
|
||||||
|
return $this->messages_renderer_hook( $location, $this->single_product_renderer_hook(), 30 );
|
||||||
|
case 'shop':
|
||||||
|
return $this->messages_renderer_hook( $location, 'woocommerce_archive_description', 10 );
|
||||||
|
case 'home':
|
||||||
|
return $this->messages_renderer_hook( $location, 'loop_start', 20 );
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$hook = $get_hook( $location );
|
||||||
|
if ( ! $hook ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
add_action(
|
add_action(
|
||||||
$this->proceed_to_checkout_button_renderer_hook(),
|
$hook['name'],
|
||||||
function() use ( $not_enabled_on_cart ) {
|
array( $this, 'message_renderer' ),
|
||||||
if ( ! is_cart() || $not_enabled_on_cart ) {
|
$hook['priority']
|
||||||
return;
|
|
||||||
}
|
|
||||||
$this->message_renderer();
|
|
||||||
},
|
|
||||||
19
|
|
||||||
);
|
);
|
||||||
|
|
||||||
$not_enabled_on_product_page = ! in_array( 'product', $selected_locations, true );
|
|
||||||
if (
|
|
||||||
( is_product() || wc_post_content_has_shortcode( 'product_page' ) )
|
|
||||||
&& ! $not_enabled_on_product_page
|
|
||||||
&& ! is_checkout()
|
|
||||||
) {
|
|
||||||
add_action(
|
|
||||||
$this->single_product_renderer_hook(),
|
|
||||||
array( $this, 'message_renderer' ),
|
|
||||||
30
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$not_enabled_on_checkout = ! in_array( 'checkout', $selected_locations, true );
|
|
||||||
if ( ! $not_enabled_on_checkout ) {
|
|
||||||
add_action(
|
|
||||||
$this->checkout_dcc_button_renderer_hook(),
|
|
||||||
array( $this, 'message_renderer' ),
|
|
||||||
11
|
|
||||||
);
|
|
||||||
add_action(
|
|
||||||
$this->pay_order_renderer_hook(),
|
|
||||||
array( $this, 'message_renderer' ),
|
|
||||||
15
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -528,8 +523,8 @@ class SmartButton implements SmartButtonInterface {
|
||||||
* Whether any of our scripts (for DCC or product, mini-cart, non-block cart/checkout) should be loaded.
|
* Whether any of our scripts (for DCC or product, mini-cart, non-block cart/checkout) should be loaded.
|
||||||
*/
|
*/
|
||||||
public function should_load_ppcp_script(): bool {
|
public function should_load_ppcp_script(): bool {
|
||||||
$buttons_enabled = $this->settings->has( 'enabled' ) && $this->settings->get( 'enabled' );
|
$pcp_gateway_enabled = $this->settings->has( 'enabled' ) && $this->settings->get( 'enabled' );
|
||||||
if ( ! $buttons_enabled ) {
|
if ( ! $pcp_gateway_enabled ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -537,37 +532,65 @@ class SmartButton implements SmartButtonInterface {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->should_load_buttons() || $this->can_render_dcc();
|
return $this->should_load_buttons() || $this->should_load_messages() || $this->can_render_dcc();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines whether the button component should be loaded.
|
* Determines whether the button component should be loaded.
|
||||||
*/
|
*/
|
||||||
public function should_load_buttons() : bool {
|
public function should_load_buttons() : bool {
|
||||||
$buttons_enabled = $this->settings->has( 'enabled' ) && $this->settings->get( 'enabled' );
|
$pcp_gateway_enabled = $this->settings->has( 'enabled' ) && $this->settings->get( 'enabled' );
|
||||||
if ( ! $buttons_enabled ) {
|
if ( ! $pcp_gateway_enabled ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$smart_button_enabled_for_current_location = $this->settings_status->is_smart_button_enabled_for_location( $this->context() );
|
$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' );
|
$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() ) {
|
switch ( $this->context() ) {
|
||||||
case 'checkout':
|
case 'checkout':
|
||||||
case 'cart':
|
case 'cart':
|
||||||
case 'pay-now':
|
case 'pay-now':
|
||||||
return $smart_button_enabled_for_current_location || $messaging_enabled_for_current_location;
|
|
||||||
case 'checkout-block':
|
case 'checkout-block':
|
||||||
case 'cart-block':
|
case 'cart-block':
|
||||||
return $smart_button_enabled_for_current_location;
|
return $smart_button_enabled_for_current_location;
|
||||||
case 'product':
|
case 'product':
|
||||||
return $smart_button_enabled_for_current_location || $messaging_enabled_for_current_location || $smart_button_enabled_for_mini_cart;
|
return $smart_button_enabled_for_current_location || $smart_button_enabled_for_mini_cart;
|
||||||
default:
|
default:
|
||||||
return $smart_button_enabled_for_mini_cart;
|
return $smart_button_enabled_for_mini_cart;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 );
|
||||||
|
|
||||||
|
switch ( $location ) {
|
||||||
|
case 'checkout':
|
||||||
|
case 'cart':
|
||||||
|
case 'pay-now':
|
||||||
|
case 'product':
|
||||||
|
case 'shop':
|
||||||
|
case 'home':
|
||||||
|
return $messaging_enabled_for_current_location;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether DCC fields can be rendered.
|
* Whether DCC fields can be rendered.
|
||||||
*/
|
*/
|
||||||
|
@ -630,8 +653,24 @@ class SmartButton implements SmartButtonInterface {
|
||||||
// The wrapper is needed for the loading spinner,
|
// The wrapper is needed for the loading spinner,
|
||||||
// otherwise jQuery block() prevents buttons rendering.
|
// otherwise jQuery block() prevents buttons rendering.
|
||||||
echo '<div class="ppc-button-wrapper">';
|
echo '<div class="ppc-button-wrapper">';
|
||||||
|
|
||||||
|
$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 );
|
||||||
|
|
||||||
echo '<div id="ppc-button-' . esc_attr( $gateway_id ) . '"></div>';
|
echo '<div id="ppc-button-' . esc_attr( $gateway_id ) . '"></div>';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 );
|
||||||
|
|
||||||
if ( null !== $action_name ) {
|
if ( null !== $action_name ) {
|
||||||
do_action( $action_name );
|
do_action( $action_name );
|
||||||
}
|
}
|
||||||
|
@ -646,8 +685,10 @@ class SmartButton implements SmartButtonInterface {
|
||||||
|
|
||||||
$product = wc_get_product();
|
$product = wc_get_product();
|
||||||
|
|
||||||
|
$location = $this->location();
|
||||||
|
|
||||||
if (
|
if (
|
||||||
! is_checkout() && is_a( $product, WC_Product::class )
|
$location === 'product' && is_a( $product, WC_Product::class )
|
||||||
/**
|
/**
|
||||||
* The filter returning true if PayPal buttons can be rendered, or false otherwise.
|
* The filter returning true if PayPal buttons can be rendered, or false otherwise.
|
||||||
*/
|
*/
|
||||||
|
@ -663,24 +704,47 @@ class SmartButton implements SmartButtonInterface {
|
||||||
* The values for the credit messaging.
|
* The values for the credit messaging.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
* @throws NotFoundException When a setting was not found.
|
|
||||||
*/
|
*/
|
||||||
private function message_values(): array {
|
private function message_values(): array {
|
||||||
if ( ! $this->settings_status->is_pay_later_messaging_enabled() ) {
|
if ( ! $this->settings_status->is_pay_later_messaging_enabled() ) {
|
||||||
return array();
|
return array();
|
||||||
}
|
}
|
||||||
|
|
||||||
$placement = is_checkout() ? 'payment' : ( is_cart() ? 'cart' : 'product' );
|
$location = $this->location();
|
||||||
$product = wc_get_product();
|
|
||||||
$amount = ( is_a( $product, WC_Product::class ) ) ? wc_get_price_including_tax( $product ) : 0;
|
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();
|
||||||
|
$amount = ( is_a( $product, WC_Product::class ) ) ? wc_get_price_including_tax( $product ) : 0;
|
||||||
|
|
||||||
if ( is_checkout() || is_cart() ) {
|
if ( is_checkout() || is_cart() ) {
|
||||||
$amount = WC()->cart->get_total( 'raw' );
|
$amount = WC()->cart->get_total( 'raw' );
|
||||||
}
|
}
|
||||||
|
|
||||||
$styling_per_location = $this->settings->has( 'pay_later_enable_styling_per_messaging_location' ) && $this->settings->get( 'pay_later_enable_styling_per_messaging_location' );
|
$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 ? $location : 'general';
|
||||||
$location = $styling_per_location ? $per_location : 'general';
|
|
||||||
$setting_name_prefix = "pay_later_{$location}_message";
|
$setting_name_prefix = "pay_later_{$location}_message";
|
||||||
|
|
||||||
$layout = $this->settings->has( "{$setting_name_prefix}_layout" ) ? $this->settings->get( "{$setting_name_prefix}_layout" ) : 'text';
|
$layout = $this->settings->has( "{$setting_name_prefix}_layout" ) ? $this->settings->get( "{$setting_name_prefix}_layout" ) : 'text';
|
||||||
|
@ -975,6 +1039,10 @@ class SmartButton implements SmartButtonInterface {
|
||||||
'funding_sources_without_redirect' => $this->funding_sources_without_redirect,
|
'funding_sources_without_redirect' => $this->funding_sources_without_redirect,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ( 'pay-now' === $this->context() ) {
|
||||||
|
$localize['pay_now'] = $this->pay_now_script_data();
|
||||||
|
}
|
||||||
|
|
||||||
if ( $this->style_for_context( 'layout', 'mini-cart' ) !== 'horizontal' ) {
|
if ( $this->style_for_context( 'layout', 'mini-cart' ) !== 'horizontal' ) {
|
||||||
$localize['button']['mini_cart_style']['tagline'] = false;
|
$localize['button']['mini_cart_style']['tagline'] = false;
|
||||||
}
|
}
|
||||||
|
@ -995,6 +1063,32 @@ class SmartButton implements SmartButtonInterface {
|
||||||
return $localize;
|
return $localize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If we can find the payer data for a current customer, we will return it.
|
* If we can find the payer data for a current customer, we will return it.
|
||||||
*
|
*
|
||||||
|
@ -1163,10 +1257,7 @@ class SmartButton implements SmartButtonInterface {
|
||||||
$components[] = 'buttons';
|
$components[] = 'buttons';
|
||||||
$components[] = 'funding-eligibility';
|
$components[] = 'funding-eligibility';
|
||||||
}
|
}
|
||||||
if (
|
if ( $this->should_load_messages() ) {
|
||||||
$this->messages_apply->for_country()
|
|
||||||
&& ! $this->is_free_trial_cart()
|
|
||||||
) {
|
|
||||||
$components[] = 'messages';
|
$components[] = 'messages';
|
||||||
}
|
}
|
||||||
if ( $this->dcc_is_enabled() ) {
|
if ( $this->dcc_is_enabled() ) {
|
||||||
|
@ -1176,7 +1267,6 @@ class SmartButton implements SmartButtonInterface {
|
||||||
* Filter to add further components from the extensions.
|
* Filter to add further components from the extensions.
|
||||||
*
|
*
|
||||||
* @internal Matches filter name in APM extension.
|
* @internal Matches filter name in APM extension.
|
||||||
* @since TODO
|
|
||||||
*
|
*
|
||||||
* @param array $components The array of components already registered.
|
* @param array $components The array of components already registered.
|
||||||
*/
|
*/
|
||||||
|
@ -1300,6 +1390,35 @@ class SmartButton implements SmartButtonInterface {
|
||||||
return (string) apply_filters( 'woocommerce_paypal_payments_pay_order_dcc_renderer_hook', 'woocommerce_pay_order_after_submit' );
|
return (string) apply_filters( 'woocommerce_paypal_payments_pay_order_dcc_renderer_hook', 'woocommerce_pay_order_after_submit' );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 {
|
||||||
|
/**
|
||||||
|
* The filter returning the action name that will be used for rendering Pay Later messages.
|
||||||
|
*/
|
||||||
|
$hook = (string) apply_filters(
|
||||||
|
"woocommerce_paypal_payments_${location}_messages_renderer_hook",
|
||||||
|
$default_hook
|
||||||
|
);
|
||||||
|
/**
|
||||||
|
* The filter returning the action priority that will be used for rendering Pay Later messages.
|
||||||
|
*/
|
||||||
|
$priority = (int) apply_filters(
|
||||||
|
"woocommerce_paypal_payments_${location}_messages_renderer_priority",
|
||||||
|
$default_priority
|
||||||
|
);
|
||||||
|
return array(
|
||||||
|
'name' => $hook,
|
||||||
|
'priority' => $priority,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns action name that PayPal button will use for rendering next to Proceed to checkout button (normally displayed in cart).
|
* Returns action name that PayPal button will use for rendering next to Proceed to checkout button (normally displayed in cart).
|
||||||
*
|
*
|
||||||
|
|
|
@ -76,7 +76,7 @@ class CartScriptParamsEndpoint implements EndpointInterface {
|
||||||
|
|
||||||
// Shop settings.
|
// Shop settings.
|
||||||
$base_location = wc_get_base_location();
|
$base_location = wc_get_base_location();
|
||||||
$shop_country_code = $base_location['country'];
|
$shop_country_code = $base_location['country'] ?? '';
|
||||||
$currency_code = get_woocommerce_currency();
|
$currency_code = get_woocommerce_currency();
|
||||||
|
|
||||||
wp_send_json_success(
|
wp_send_json_success(
|
||||||
|
|
|
@ -12,6 +12,27 @@ namespace WooCommerce\PayPalCommerce\Button\Helper;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus;
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\OrderStatus;
|
||||||
|
|
||||||
trait ContextTrait {
|
trait ContextTrait {
|
||||||
|
/**
|
||||||
|
* Checks WC is_checkout() + WC checkout ajax requests.
|
||||||
|
*/
|
||||||
|
private function is_checkout(): bool {
|
||||||
|
if ( is_checkout() ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The filter returning whether to detect WC checkout ajax requests.
|
||||||
|
*/
|
||||||
|
if ( apply_filters( 'ppcp_check_ajax_checkout', true ) ) {
|
||||||
|
// phpcs:ignore WordPress.Security
|
||||||
|
$wc_ajax = $_GET['wc-ajax'] ?? '';
|
||||||
|
if ( in_array( $wc_ajax, array( 'update_order_review' ), true ) ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current context.
|
* The current context.
|
||||||
|
@ -23,7 +44,7 @@ trait ContextTrait {
|
||||||
|
|
||||||
// Do this check here instead of reordering outside conditions.
|
// Do this check here instead of reordering outside conditions.
|
||||||
// In order to have more control over the context.
|
// In order to have more control over the context.
|
||||||
if ( ( is_checkout() ) && ! $this->is_paypal_continuation() ) {
|
if ( $this->is_checkout() && ! $this->is_paypal_continuation() ) {
|
||||||
return 'checkout';
|
return 'checkout';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,13 +68,35 @@ trait ContextTrait {
|
||||||
return 'checkout-block';
|
return 'checkout-block';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ( is_checkout() ) && ! $this->is_paypal_continuation() ) {
|
if ( $this->is_checkout() && ! $this->is_paypal_continuation() ) {
|
||||||
return 'checkout';
|
return 'checkout';
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'mini-cart';
|
return 'mini-cart';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current location.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function location(): string {
|
||||||
|
$context = $this->context();
|
||||||
|
if ( $context !== 'mini-cart' ) {
|
||||||
|
return $context;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( is_shop() ) {
|
||||||
|
return 'shop';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( is_front_page() ) {
|
||||||
|
return 'home';
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if PayPal payment was already initiated (on the product or cart pages).
|
* Checks if PayPal payment was already initiated (on the product or cart pages).
|
||||||
*
|
*
|
||||||
|
|
|
@ -13,6 +13,7 @@ use WooCommerce\PayPalCommerce\Googlepay\Helper\PropertiesDictionary;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Helper\DisplayManager;
|
use WooCommerce\PayPalCommerce\WcGateway\Helper\DisplayManager;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||||
|
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
|
@ -24,6 +25,9 @@ return array(
|
||||||
return $fields;
|
return $fields;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$is_available = $container->get( 'googlepay.available' );
|
||||||
|
$is_referral = $container->get( 'googlepay.is_referral' );
|
||||||
|
|
||||||
$insert_after = function( array $array, string $key, array $new ): array {
|
$insert_after = function( array $array, string $key, array $new ): array {
|
||||||
$keys = array_keys( $array );
|
$keys = array_keys( $array );
|
||||||
$index = array_search( $key, $keys, true );
|
$index = array_search( $key, $keys, true );
|
||||||
|
@ -35,6 +39,66 @@ return array(
|
||||||
$display_manager = $container->get( 'wcgateway.display-manager' );
|
$display_manager = $container->get( 'wcgateway.display-manager' );
|
||||||
assert( $display_manager instanceof DisplayManager );
|
assert( $display_manager instanceof DisplayManager );
|
||||||
|
|
||||||
|
// Connection tab fields.
|
||||||
|
$fields = $insert_after(
|
||||||
|
$fields,
|
||||||
|
'ppcp_dcc_status',
|
||||||
|
array(
|
||||||
|
'googlepay_status' => array(
|
||||||
|
'title' => __( 'Google Pay Payments', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'ppcp-text',
|
||||||
|
'text' => $container->get( 'googlepay.settings.connection.status-text' ),
|
||||||
|
'screens' => array(
|
||||||
|
State::STATE_ONBOARDED,
|
||||||
|
),
|
||||||
|
'requirements' => array(),
|
||||||
|
'gateway' => Settings::CONNECTION_TAB_ID,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( ! $is_available && $is_referral ) {
|
||||||
|
$connection_url = admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway&ppcp-tab=ppcp-connection#field-credentials_feature_onboarding_heading' );
|
||||||
|
$connection_link = '<a href="' . $connection_url . '" style="pointer-events: auto">';
|
||||||
|
return $insert_after(
|
||||||
|
$fields,
|
||||||
|
'allow_card_button_gateway',
|
||||||
|
array(
|
||||||
|
'googlepay_button_enabled' => array(
|
||||||
|
'title' => __( 'Google Pay Button', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'checkbox',
|
||||||
|
'class' => array( 'ppcp-grayed-out-text' ),
|
||||||
|
'input_class' => array( 'ppcp-disabled-checkbox' ),
|
||||||
|
'label' => __( 'Enable Google Pay button', 'woocommerce-paypal-payments' )
|
||||||
|
. '<p class="description">'
|
||||||
|
. sprintf(
|
||||||
|
// translators: %1$s and %2$s are the opening and closing of HTML <a> tag.
|
||||||
|
__( 'Your PayPal account %1$srequires additional permissions%2$s to enable Google Pay.', 'woocommerce-paypal-payments' ),
|
||||||
|
$connection_link,
|
||||||
|
'</a>'
|
||||||
|
)
|
||||||
|
. '</p>',
|
||||||
|
'default' => 'yes',
|
||||||
|
'screens' => array( State::STATE_ONBOARDED ),
|
||||||
|
'gateway' => 'paypal',
|
||||||
|
'requirements' => array(),
|
||||||
|
'custom_attributes' => array(
|
||||||
|
'data-ppcp-display' => wp_json_encode(
|
||||||
|
array(
|
||||||
|
$display_manager
|
||||||
|
->rule()
|
||||||
|
->condition_is_true( false )
|
||||||
|
->action_enable( 'googlepay_button_enabled' )
|
||||||
|
->to_array(),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Standard Payments tab fields.
|
||||||
return $insert_after(
|
return $insert_after(
|
||||||
$fields,
|
$fields,
|
||||||
'allow_card_button_gateway',
|
'allow_card_button_gateway',
|
||||||
|
|
|
@ -10,6 +10,10 @@ class BaseHandler {
|
||||||
this.externalHandler = externalHandler;
|
this.externalHandler = externalHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shippingAllowed() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
transactionInfo() {
|
transactionInfo() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,10 @@ import BaseHandler from "./BaseHandler";
|
||||||
|
|
||||||
class CheckoutBlockHandler extends BaseHandler{
|
class CheckoutBlockHandler extends BaseHandler{
|
||||||
|
|
||||||
|
shippingAllowed() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
createOrder() {
|
createOrder() {
|
||||||
return this.externalHandler.createOrder();
|
return this.externalHandler.createOrder();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,10 @@ import FormValidator from "../../../../ppcp-button/resources/js/modules/Helper/F
|
||||||
|
|
||||||
class CheckoutHandler extends BaseHandler {
|
class CheckoutHandler extends BaseHandler {
|
||||||
|
|
||||||
|
shippingAllowed() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
transactionInfo() {
|
transactionInfo() {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ import CheckoutHandler from "./CheckoutHandler";
|
||||||
import CartBlockHandler from "./CartBlockHandler";
|
import CartBlockHandler from "./CartBlockHandler";
|
||||||
import CheckoutBlockHandler from "./CheckoutBlockHandler";
|
import CheckoutBlockHandler from "./CheckoutBlockHandler";
|
||||||
import MiniCartHandler from "./MiniCartHandler";
|
import MiniCartHandler from "./MiniCartHandler";
|
||||||
|
import PayNowHandler from "./PayNowHandler";
|
||||||
|
import PreviewHandler from "./PreviewHandler";
|
||||||
|
|
||||||
class ContextHandlerFactory {
|
class ContextHandlerFactory {
|
||||||
|
|
||||||
|
@ -14,14 +16,17 @@ class ContextHandlerFactory {
|
||||||
case 'cart':
|
case 'cart':
|
||||||
return new CartHandler(buttonConfig, ppcpConfig, externalActionHandler);
|
return new CartHandler(buttonConfig, ppcpConfig, externalActionHandler);
|
||||||
case 'checkout':
|
case 'checkout':
|
||||||
case 'pay-now': // same as checkout
|
|
||||||
return new CheckoutHandler(buttonConfig, ppcpConfig, externalActionHandler);
|
return new CheckoutHandler(buttonConfig, ppcpConfig, externalActionHandler);
|
||||||
|
case 'pay-now':
|
||||||
|
return new PayNowHandler(buttonConfig, ppcpConfig, externalActionHandler);
|
||||||
case 'mini-cart':
|
case 'mini-cart':
|
||||||
return new MiniCartHandler(buttonConfig, ppcpConfig, externalActionHandler);
|
return new MiniCartHandler(buttonConfig, ppcpConfig, externalActionHandler);
|
||||||
case 'cart-block':
|
case 'cart-block':
|
||||||
return new CartBlockHandler(buttonConfig, ppcpConfig, externalActionHandler);
|
return new CartBlockHandler(buttonConfig, ppcpConfig, externalActionHandler);
|
||||||
case 'checkout-block':
|
case 'checkout-block':
|
||||||
return new CheckoutBlockHandler(buttonConfig, ppcpConfig, externalActionHandler);
|
return new CheckoutBlockHandler(buttonConfig, ppcpConfig, externalActionHandler);
|
||||||
|
case 'preview':
|
||||||
|
return new PreviewHandler(buttonConfig, ppcpConfig, externalActionHandler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
35
modules/ppcp-googlepay/resources/js/Context/PayNowHandler.js
Normal file
35
modules/ppcp-googlepay/resources/js/Context/PayNowHandler.js
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import Spinner from "../../../../ppcp-button/resources/js/modules/Helper/Spinner";
|
||||||
|
import BaseHandler from "./BaseHandler";
|
||||||
|
import CheckoutActionHandler
|
||||||
|
from "../../../../ppcp-button/resources/js/modules/ActionHandler/CheckoutActionHandler";
|
||||||
|
|
||||||
|
class PayNowHandler extends BaseHandler {
|
||||||
|
|
||||||
|
shippingAllowed() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
transactionInfo() {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
const data = this.ppcpConfig['pay_now'];
|
||||||
|
|
||||||
|
resolve({
|
||||||
|
countryCode: data.country_code,
|
||||||
|
currencyCode: data.currency_code,
|
||||||
|
totalPriceStatus: 'FINAL',
|
||||||
|
totalPrice: data.total_str
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
actionHandler() {
|
||||||
|
return new CheckoutActionHandler(
|
||||||
|
this.ppcpConfig,
|
||||||
|
this.errorHandler(),
|
||||||
|
new Spinner()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PayNowHandler;
|
|
@ -0,0 +1,31 @@
|
||||||
|
import BaseHandler from "./BaseHandler";
|
||||||
|
|
||||||
|
class CartHandler extends BaseHandler {
|
||||||
|
|
||||||
|
constructor(buttonConfig, ppcpConfig, externalHandler) {
|
||||||
|
super(buttonConfig, ppcpConfig, externalHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
transactionInfo() {
|
||||||
|
throw new Error('Transaction info fail. This is just a preview.');
|
||||||
|
}
|
||||||
|
|
||||||
|
createOrder() {
|
||||||
|
throw new Error('Create order fail. This is just a preview.');
|
||||||
|
}
|
||||||
|
|
||||||
|
approveOrder(data, actions) {
|
||||||
|
throw new Error('Approve order fail. This is just a preview.');
|
||||||
|
}
|
||||||
|
|
||||||
|
actionHandler() {
|
||||||
|
throw new Error('Action handler fail. This is just a preview.');
|
||||||
|
}
|
||||||
|
|
||||||
|
errorHandler() {
|
||||||
|
throw new Error('Error handler fail. This is just a preview.');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CartHandler;
|
|
@ -1,6 +1,8 @@
|
||||||
import ContextHandlerFactory from "./Context/ContextHandlerFactory";
|
import ContextHandlerFactory from "./Context/ContextHandlerFactory";
|
||||||
import {setVisible} from '../../../ppcp-button/resources/js/modules/Helper/Hiding';
|
import {setVisible} from '../../../ppcp-button/resources/js/modules/Helper/Hiding';
|
||||||
import {setEnabled} from '../../../ppcp-button/resources/js/modules/Helper/ButtonDisabler';
|
import {setEnabled} from '../../../ppcp-button/resources/js/modules/Helper/ButtonDisabler';
|
||||||
|
import widgetBuilder from "../../../ppcp-button/resources/js/modules/Renderer/WidgetBuilder";
|
||||||
|
import UpdatePaymentData from "./Helper/UpdatePaymentData";
|
||||||
|
|
||||||
class GooglepayButton {
|
class GooglepayButton {
|
||||||
|
|
||||||
|
@ -21,7 +23,11 @@ class GooglepayButton {
|
||||||
this.externalHandler
|
this.externalHandler
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log('[GooglePayButton] new Button', this);
|
this.log = function() {
|
||||||
|
if ( this.buttonConfig.is_debug ) {
|
||||||
|
console.log('[GooglePayButton]', ...arguments);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init(config) {
|
init(config) {
|
||||||
|
@ -54,6 +60,15 @@ class GooglepayButton {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reinit() {
|
||||||
|
if (!this.googlePayConfig) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isInitialized = false;
|
||||||
|
this.init(this.googlePayConfig);
|
||||||
|
}
|
||||||
|
|
||||||
validateConfig() {
|
validateConfig() {
|
||||||
if ( ['PRODUCTION', 'TEST'].indexOf(this.buttonConfig.environment) === -1) {
|
if ( ['PRODUCTION', 'TEST'].indexOf(this.buttonConfig.environment) === -1) {
|
||||||
console.error('[GooglePayButton] Invalid environment.', this.buttonConfig.environment);
|
console.error('[GooglePayButton] Invalid environment.', this.buttonConfig.environment);
|
||||||
|
@ -99,13 +114,18 @@ class GooglepayButton {
|
||||||
}
|
}
|
||||||
|
|
||||||
initClient() {
|
initClient() {
|
||||||
|
const callbacks = {
|
||||||
|
onPaymentAuthorized: this.onPaymentAuthorized.bind(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( this.buttonConfig.shipping.enabled && this.contextHandler.shippingAllowed() ) {
|
||||||
|
callbacks['onPaymentDataChanged'] = this.onPaymentDataChanged.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
this.paymentsClient = new google.payments.api.PaymentsClient({
|
this.paymentsClient = new google.payments.api.PaymentsClient({
|
||||||
environment: this.buttonConfig.environment,
|
environment: this.buttonConfig.environment,
|
||||||
// add merchant info maybe
|
// add merchant info maybe
|
||||||
paymentDataCallbacks: {
|
paymentDataCallbacks: callbacks
|
||||||
//onPaymentDataChanged: onPaymentDataChanged,
|
|
||||||
onPaymentAuthorized: this.onPaymentAuthorized.bind(this),
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,22 +157,41 @@ class GooglepayButton {
|
||||||
* Add a Google Pay purchase button
|
* Add a Google Pay purchase button
|
||||||
*/
|
*/
|
||||||
addButton(baseCardPaymentMethod) {
|
addButton(baseCardPaymentMethod) {
|
||||||
console.log('[GooglePayButton] addButton', this.context);
|
this.log('addButton', this.context);
|
||||||
|
|
||||||
const { wrapper, ppcpStyle, buttonStyle } = this.contextConfig();
|
const { wrapper, ppcpStyle, buttonStyle } = this.contextConfig();
|
||||||
|
|
||||||
jQuery(wrapper).addClass('ppcp-button-' + ppcpStyle.shape);
|
this.waitForWrapper(wrapper, () => {
|
||||||
|
jQuery(wrapper).addClass('ppcp-button-' + ppcpStyle.shape);
|
||||||
|
|
||||||
const button =
|
const button =
|
||||||
this.paymentsClient.createButton({
|
this.paymentsClient.createButton({
|
||||||
onClick: this.onButtonClick.bind(this),
|
onClick: this.onButtonClick.bind(this),
|
||||||
allowedPaymentMethods: [baseCardPaymentMethod],
|
allowedPaymentMethods: [baseCardPaymentMethod],
|
||||||
buttonColor: buttonStyle.color || 'black',
|
buttonColor: buttonStyle.color || 'black',
|
||||||
buttonType: buttonStyle.type || 'pay',
|
buttonType: buttonStyle.type || 'pay',
|
||||||
buttonLocale: buttonStyle.language || 'en',
|
buttonLocale: buttonStyle.language || 'en',
|
||||||
buttonSizeMode: 'fill',
|
buttonSizeMode: 'fill',
|
||||||
});
|
});
|
||||||
jQuery(wrapper).append(button);
|
|
||||||
|
jQuery(wrapper).append(button);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
waitForWrapper(selector, callback, delay = 100, timeout = 2000) {
|
||||||
|
const startTime = Date.now();
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
const el = document.querySelector(selector);
|
||||||
|
const timeElapsed = Date.now() - startTime;
|
||||||
|
|
||||||
|
if (el) {
|
||||||
|
clearInterval(interval);
|
||||||
|
callback(el);
|
||||||
|
} else if (timeElapsed > timeout) {
|
||||||
|
clearInterval(interval);
|
||||||
|
console.error('Waiting for wrapper timed out.', selector);
|
||||||
|
}
|
||||||
|
}, delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------
|
//------------------------
|
||||||
|
@ -163,10 +202,10 @@ class GooglepayButton {
|
||||||
* Show Google Pay payment sheet when Google Pay payment button is clicked
|
* Show Google Pay payment sheet when Google Pay payment button is clicked
|
||||||
*/
|
*/
|
||||||
async onButtonClick() {
|
async onButtonClick() {
|
||||||
console.log('[GooglePayButton] onButtonClick', this.context);
|
this.log('onButtonClick', this.context);
|
||||||
|
|
||||||
const paymentDataRequest = await this.paymentDataRequest();
|
const paymentDataRequest = await this.paymentDataRequest();
|
||||||
console.log('[GooglePayButton] onButtonClick: paymentDataRequest', paymentDataRequest, this.context);
|
this.log('onButtonClick: paymentDataRequest', paymentDataRequest, this.context);
|
||||||
|
|
||||||
window.ppcpFundingSource = 'googlepay'; // Do this on another place like on create order endpoint handler.
|
window.ppcpFundingSource = 'googlepay'; // Do this on another place like on create order endpoint handler.
|
||||||
|
|
||||||
|
@ -184,35 +223,111 @@ class GooglepayButton {
|
||||||
paymentDataRequest.allowedPaymentMethods = googlePayConfig.allowedPaymentMethods;
|
paymentDataRequest.allowedPaymentMethods = googlePayConfig.allowedPaymentMethods;
|
||||||
paymentDataRequest.transactionInfo = await this.contextHandler.transactionInfo();
|
paymentDataRequest.transactionInfo = await this.contextHandler.transactionInfo();
|
||||||
paymentDataRequest.merchantInfo = googlePayConfig.merchantInfo;
|
paymentDataRequest.merchantInfo = googlePayConfig.merchantInfo;
|
||||||
paymentDataRequest.callbackIntents = ['PAYMENT_AUTHORIZATION'];
|
|
||||||
|
if ( this.buttonConfig.shipping.enabled && this.contextHandler.shippingAllowed() ) {
|
||||||
|
paymentDataRequest.callbackIntents = ["SHIPPING_ADDRESS", "SHIPPING_OPTION", "PAYMENT_AUTHORIZATION"];
|
||||||
|
paymentDataRequest.shippingAddressRequired = true;
|
||||||
|
paymentDataRequest.shippingAddressParameters = this.shippingAddressParameters();
|
||||||
|
paymentDataRequest.shippingOptionRequired = true;
|
||||||
|
} else {
|
||||||
|
paymentDataRequest.callbackIntents = ['PAYMENT_AUTHORIZATION'];
|
||||||
|
}
|
||||||
|
|
||||||
return paymentDataRequest;
|
return paymentDataRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//------------------------
|
||||||
|
// Shipping processing
|
||||||
|
//------------------------
|
||||||
|
|
||||||
|
shippingAddressParameters() {
|
||||||
|
return {
|
||||||
|
allowedCountryCodes: this.buttonConfig.shipping.countries,
|
||||||
|
phoneNumberRequired: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
onPaymentDataChanged(paymentData) {
|
||||||
|
this.log('onPaymentDataChanged', this.context);
|
||||||
|
this.log('paymentData', paymentData);
|
||||||
|
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
let paymentDataRequestUpdate = {};
|
||||||
|
|
||||||
|
const updatedData = await (new UpdatePaymentData(this.buttonConfig.ajax.update_payment_data)).update(paymentData);
|
||||||
|
const transactionInfo = await this.contextHandler.transactionInfo();
|
||||||
|
|
||||||
|
this.log('onPaymentDataChanged:updatedData', updatedData);
|
||||||
|
this.log('onPaymentDataChanged:transactionInfo', transactionInfo);
|
||||||
|
|
||||||
|
updatedData.country_code = transactionInfo.countryCode;
|
||||||
|
updatedData.currency_code = transactionInfo.currencyCode;
|
||||||
|
updatedData.total_str = transactionInfo.totalPrice;
|
||||||
|
|
||||||
|
// Handle unserviceable address.
|
||||||
|
if(!updatedData.shipping_options || !updatedData.shipping_options.shippingOptions.length) {
|
||||||
|
paymentDataRequestUpdate.error = this.unserviceableShippingAddressError();
|
||||||
|
resolve(paymentDataRequestUpdate);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (paymentData.callbackTrigger) {
|
||||||
|
case 'INITIALIZE':
|
||||||
|
case 'SHIPPING_ADDRESS':
|
||||||
|
paymentDataRequestUpdate.newShippingOptionParameters = updatedData.shipping_options;
|
||||||
|
paymentDataRequestUpdate.newTransactionInfo = this.calculateNewTransactionInfo(updatedData);
|
||||||
|
break;
|
||||||
|
case 'SHIPPING_OPTION':
|
||||||
|
paymentDataRequestUpdate.newTransactionInfo = this.calculateNewTransactionInfo(updatedData);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(paymentDataRequestUpdate);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
unserviceableShippingAddressError() {
|
||||||
|
return {
|
||||||
|
reason: "SHIPPING_ADDRESS_UNSERVICEABLE",
|
||||||
|
message: "Cannot ship to the selected address",
|
||||||
|
intent: "SHIPPING_ADDRESS"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateNewTransactionInfo(updatedData) {
|
||||||
|
return {
|
||||||
|
countryCode: updatedData.country_code,
|
||||||
|
currencyCode: updatedData.currency_code,
|
||||||
|
totalPriceStatus: 'FINAL',
|
||||||
|
totalPrice: updatedData.total_str
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//------------------------
|
//------------------------
|
||||||
// Payment process
|
// Payment process
|
||||||
//------------------------
|
//------------------------
|
||||||
|
|
||||||
onPaymentAuthorized(paymentData) {
|
onPaymentAuthorized(paymentData) {
|
||||||
console.log('[GooglePayButton] onPaymentAuthorized', this.context);
|
this.log('onPaymentAuthorized', this.context);
|
||||||
return this.processPayment(paymentData);
|
return this.processPayment(paymentData);
|
||||||
}
|
}
|
||||||
|
|
||||||
async processPayment(paymentData) {
|
async processPayment(paymentData) {
|
||||||
console.log('[GooglePayButton] processPayment', this.context);
|
this.log('processPayment', this.context);
|
||||||
|
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
let id = await this.contextHandler.createOrder();
|
let id = await this.contextHandler.createOrder();
|
||||||
|
|
||||||
console.log('[GooglePayButton] processPayment: createOrder', id, this.context);
|
this.log('processPayment: createOrder', id, this.context);
|
||||||
|
|
||||||
const confirmOrderResponse = await paypal.Googlepay().confirmOrder({
|
const confirmOrderResponse = await widgetBuilder.paypal.Googlepay().confirmOrder({
|
||||||
orderId: id,
|
orderId: id,
|
||||||
paymentMethodData: paymentData.paymentMethodData
|
paymentMethodData: paymentData.paymentMethodData
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('[GooglePayButton] processPayment: confirmOrder', confirmOrderResponse, this.context);
|
this.log('processPayment: confirmOrder', confirmOrderResponse, this.context);
|
||||||
|
|
||||||
/** Capture the Order on the Server */
|
/** Capture the Order on the Server */
|
||||||
if (confirmOrderResponse.status === "APPROVED") {
|
if (confirmOrderResponse.status === "APPROVED") {
|
||||||
|
@ -259,7 +374,7 @@ class GooglepayButton {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('[GooglePayButton] processPaymentResponse', response, this.context);
|
this.log('processPaymentResponse', response, this.context);
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,12 @@ class GooglepayManager {
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reinit() {
|
||||||
|
for (const button of this.buttons) {
|
||||||
|
button.reinit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default GooglepayManager;
|
export default GooglepayManager;
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
|
||||||
|
class UpdatePaymentData {
|
||||||
|
|
||||||
|
constructor(config) {
|
||||||
|
this.config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
update(paymentData) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
fetch(
|
||||||
|
this.config.endpoint,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
credentials: 'same-origin',
|
||||||
|
body: JSON.stringify({
|
||||||
|
nonce: this.config.nonce,
|
||||||
|
paymentData: paymentData,
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then(result => result.json())
|
||||||
|
.then(result => {
|
||||||
|
if (!result.success) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(result.data);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default UpdatePaymentData;
|
146
modules/ppcp-googlepay/resources/js/boot-admin.js
Normal file
146
modules/ppcp-googlepay/resources/js/boot-admin.js
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
import {loadCustomScript} from "@paypal/paypal-js";
|
||||||
|
import GooglepayButton from "./GooglepayButton";
|
||||||
|
import widgetBuilder from "../../../ppcp-button/resources/js/modules/Renderer/WidgetBuilder";
|
||||||
|
|
||||||
|
(function ({
|
||||||
|
buttonConfig,
|
||||||
|
jQuery
|
||||||
|
}) {
|
||||||
|
|
||||||
|
let googlePayConfig;
|
||||||
|
let buttonQueue = [];
|
||||||
|
let activeButtons = {};
|
||||||
|
let bootstrapped = false;
|
||||||
|
|
||||||
|
// React to PayPal config changes.
|
||||||
|
jQuery(document).on('ppcp_paypal_render_preview', (ev, ppcpConfig) => {
|
||||||
|
if (bootstrapped) {
|
||||||
|
createButton(ppcpConfig);
|
||||||
|
} else {
|
||||||
|
buttonQueue.push({
|
||||||
|
ppcpConfig: JSON.parse(JSON.stringify(ppcpConfig))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// React to GooglePay config changes.
|
||||||
|
jQuery([
|
||||||
|
'#ppcp-googlepay_button_enabled',
|
||||||
|
'#ppcp-googlepay_button_type',
|
||||||
|
'#ppcp-googlepay_button_color',
|
||||||
|
'#ppcp-googlepay_button_language',
|
||||||
|
'#ppcp-googlepay_button_shipping_enabled'
|
||||||
|
].join(',')).on('change', () => {
|
||||||
|
for (const [selector, ppcpConfig] of Object.entries(activeButtons)) {
|
||||||
|
createButton(ppcpConfig);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Maybe we can find a more elegant reload method when transitioning from styling modes.
|
||||||
|
jQuery([
|
||||||
|
'#ppcp-smart_button_enable_styling_per_location'
|
||||||
|
].join(',')).on('change', () => {
|
||||||
|
setTimeout(() => {
|
||||||
|
for (const [selector, ppcpConfig] of Object.entries(activeButtons)) {
|
||||||
|
createButton(ppcpConfig);
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
});
|
||||||
|
|
||||||
|
const applyConfigOptions = function (buttonConfig) {
|
||||||
|
buttonConfig.button = buttonConfig.button || {};
|
||||||
|
buttonConfig.button.style = buttonConfig.button.style || {};
|
||||||
|
buttonConfig.button.style.type = jQuery('#ppcp-googlepay_button_type').val();
|
||||||
|
buttonConfig.button.style.color = jQuery('#ppcp-googlepay_button_color').val();
|
||||||
|
buttonConfig.button.style.language = jQuery('#ppcp-googlepay_button_language').val();
|
||||||
|
}
|
||||||
|
|
||||||
|
const createButton = function (ppcpConfig) {
|
||||||
|
const selector = ppcpConfig.button.wrapper + 'GooglePay';
|
||||||
|
|
||||||
|
if (!jQuery('#ppcp-googlepay_button_enabled').is(':checked')) {
|
||||||
|
jQuery(selector).remove();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
buttonConfig = JSON.parse(JSON.stringify(buttonConfig));
|
||||||
|
buttonConfig.button.wrapper = selector;
|
||||||
|
applyConfigOptions(buttonConfig);
|
||||||
|
|
||||||
|
const wrapperElement = `<div id="${selector.replace('#', '')}" class="ppcp-button-googlepay"></div>`;
|
||||||
|
|
||||||
|
if (!jQuery(selector).length) {
|
||||||
|
jQuery(ppcpConfig.button.wrapper).after(wrapperElement);
|
||||||
|
} else {
|
||||||
|
jQuery(selector).replaceWith(wrapperElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
const button = new GooglepayButton(
|
||||||
|
'preview',
|
||||||
|
null,
|
||||||
|
buttonConfig,
|
||||||
|
ppcpConfig,
|
||||||
|
);
|
||||||
|
|
||||||
|
button.init(googlePayConfig);
|
||||||
|
|
||||||
|
activeButtons[selector] = ppcpConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bootstrap = async function () {
|
||||||
|
if (!widgetBuilder.paypal) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
googlePayConfig = await widgetBuilder.paypal.Googlepay().config();
|
||||||
|
|
||||||
|
// We need to set bootstrapped here otherwise googlePayConfig may not be set.
|
||||||
|
bootstrapped = true;
|
||||||
|
|
||||||
|
let options;
|
||||||
|
while (options = buttonQueue.pop()) {
|
||||||
|
createButton(options.ppcpConfig);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.addEventListener(
|
||||||
|
'DOMContentLoaded',
|
||||||
|
() => {
|
||||||
|
|
||||||
|
if (typeof (buttonConfig) === 'undefined') {
|
||||||
|
console.error('PayPal button could not be configured.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let paypalLoaded = false;
|
||||||
|
let googlePayLoaded = false;
|
||||||
|
|
||||||
|
const tryToBoot = () => {
|
||||||
|
if (!bootstrapped && paypalLoaded && googlePayLoaded) {
|
||||||
|
bootstrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load GooglePay SDK
|
||||||
|
loadCustomScript({ url: buttonConfig.sdk_url }).then(() => {
|
||||||
|
googlePayLoaded = true;
|
||||||
|
tryToBoot();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wait for PayPal to be loaded externally
|
||||||
|
if (typeof widgetBuilder.paypal !== 'undefined') {
|
||||||
|
paypalLoaded = true;
|
||||||
|
tryToBoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
jQuery(document).on('ppcp-paypal-loaded', () => {
|
||||||
|
paypalLoaded = true;
|
||||||
|
tryToBoot();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
})({
|
||||||
|
buttonConfig: window.wc_ppcp_googlepay_admin,
|
||||||
|
jQuery: window.jQuery
|
||||||
|
});
|
|
@ -8,11 +8,17 @@ import GooglepayManager from "./GooglepayManager";
|
||||||
jQuery
|
jQuery
|
||||||
}) {
|
}) {
|
||||||
|
|
||||||
|
let manager;
|
||||||
|
|
||||||
const bootstrap = function () {
|
const bootstrap = function () {
|
||||||
const manager = new GooglepayManager(buttonConfig, ppcpConfig);
|
manager = new GooglepayManager(buttonConfig, ppcpConfig);
|
||||||
manager.init();
|
manager.init();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
jQuery(document.body).on('updated_cart_totals updated_checkout', () => {
|
||||||
|
manager.reinit();
|
||||||
|
});
|
||||||
|
|
||||||
document.addEventListener(
|
document.addEventListener(
|
||||||
'DOMContentLoaded',
|
'DOMContentLoaded',
|
||||||
() => {
|
() => {
|
||||||
|
@ -20,12 +26,7 @@ import GooglepayManager from "./GooglepayManager";
|
||||||
(typeof (buttonConfig) === 'undefined') ||
|
(typeof (buttonConfig) === 'undefined') ||
|
||||||
(typeof (ppcpConfig) === 'undefined')
|
(typeof (ppcpConfig) === 'undefined')
|
||||||
) {
|
) {
|
||||||
console.error('PayPal button could not be configured.');
|
// No PayPal buttons present on this page.
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If button wrapper is not present then there is no need to load the scripts.
|
|
||||||
if (!jQuery(buttonConfig.button.wrapper).length) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,15 @@ namespace WooCommerce\PayPalCommerce\Googlepay;
|
||||||
|
|
||||||
use Automattic\WooCommerce\Blocks\Payments\PaymentMethodTypeInterface;
|
use Automattic\WooCommerce\Blocks\Payments\PaymentMethodTypeInterface;
|
||||||
use WooCommerce\PayPalCommerce\Button\Assets\ButtonInterface;
|
use WooCommerce\PayPalCommerce\Button\Assets\ButtonInterface;
|
||||||
|
use WooCommerce\PayPalCommerce\Common\Pattern\SingletonDecorator;
|
||||||
use WooCommerce\PayPalCommerce\Googlepay\Assets\BlocksPaymentMethod;
|
use WooCommerce\PayPalCommerce\Googlepay\Assets\BlocksPaymentMethod;
|
||||||
use WooCommerce\PayPalCommerce\Googlepay\Assets\Button;
|
use WooCommerce\PayPalCommerce\Googlepay\Assets\Button;
|
||||||
|
use WooCommerce\PayPalCommerce\Googlepay\Endpoint\UpdatePaymentDataEndpoint;
|
||||||
use WooCommerce\PayPalCommerce\Googlepay\Helper\ApmApplies;
|
use WooCommerce\PayPalCommerce\Googlepay\Helper\ApmApplies;
|
||||||
use WooCommerce\PayPalCommerce\Googlepay\Helper\ApmProductStatus;
|
use WooCommerce\PayPalCommerce\Googlepay\Helper\ApmProductStatus;
|
||||||
|
use WooCommerce\PayPalCommerce\Googlepay\Helper\AvailabilityNotice;
|
||||||
|
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||||
|
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
|
@ -35,9 +40,9 @@ return array(
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
// If GooglePay is configured.
|
// If GooglePay is configured and onboarded.
|
||||||
'googlepay.available' => static function ( ContainerInterface $container ): bool {
|
'googlepay.available' => static function ( ContainerInterface $container ): bool {
|
||||||
if ( apply_filters( 'woocommerce_paypal_payments_googlepay_validate_product_status', false ) ) {
|
if ( apply_filters( 'woocommerce_paypal_payments_googlepay_validate_product_status', true ) ) {
|
||||||
$status = $container->get( 'googlepay.helpers.apm-product-status' );
|
$status = $container->get( 'googlepay.helpers.apm-product-status' );
|
||||||
assert( $status instanceof ApmProductStatus );
|
assert( $status instanceof ApmProductStatus );
|
||||||
/**
|
/**
|
||||||
|
@ -48,14 +53,33 @@ return array(
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
'googlepay.helpers.apm-product-status' => static function( ContainerInterface $container ): ApmProductStatus {
|
// We assume it's a referral if we can check product status without API request failures.
|
||||||
return new ApmProductStatus(
|
'googlepay.is_referral' => static function ( ContainerInterface $container ): bool {
|
||||||
$container->get( 'wcgateway.settings' ),
|
$status = $container->get( 'googlepay.helpers.apm-product-status' );
|
||||||
$container->get( 'api.endpoint.partners' ),
|
assert( $status instanceof ApmProductStatus );
|
||||||
$container->get( 'onboarding.state' )
|
|
||||||
|
return ! $status->has_request_failure();
|
||||||
|
},
|
||||||
|
|
||||||
|
'googlepay.availability_notice' => static function ( ContainerInterface $container ): AvailabilityNotice {
|
||||||
|
return new AvailabilityNotice(
|
||||||
|
$container->get( 'googlepay.helpers.apm-product-status' ),
|
||||||
|
$container->get( 'wcgateway.is-wc-gateways-list-page' ),
|
||||||
|
$container->get( 'wcgateway.is-ppcp-settings-page' )
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'googlepay.helpers.apm-product-status' => SingletonDecorator::make(
|
||||||
|
static function( ContainerInterface $container ): ApmProductStatus {
|
||||||
|
return new ApmProductStatus(
|
||||||
|
$container->get( 'wcgateway.settings' ),
|
||||||
|
$container->get( 'api.endpoint.partners' ),
|
||||||
|
$container->get( 'onboarding.state' ),
|
||||||
|
$container->get( 'api.helper.failure-registry' )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The matrix which countries and currency combinations can be used for GooglePay.
|
* The matrix which countries and currency combinations can be used for GooglePay.
|
||||||
*/
|
*/
|
||||||
|
@ -153,4 +177,58 @@ return array(
|
||||||
return 'https://pay.google.com/gp/p/js/pay.js';
|
return 'https://pay.google.com/gp/p/js/pay.js';
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'googlepay.endpoint.update-payment-data' => static function ( ContainerInterface $container ): UpdatePaymentDataEndpoint {
|
||||||
|
return new UpdatePaymentDataEndpoint(
|
||||||
|
$container->get( 'button.request-data' ),
|
||||||
|
$container->get( 'woocommerce.logger.woocommerce' )
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
'googlepay.enable-url-sandbox' => static function ( ContainerInterface $container ): string {
|
||||||
|
return 'https://www.sandbox.paypal.com/bizsignup/add-product?product=payment_methods&capabilities=GOOGLE_PAY';
|
||||||
|
},
|
||||||
|
|
||||||
|
'googlepay.enable-url-live' => static function ( ContainerInterface $container ): string {
|
||||||
|
return 'https://www.paypal.com/bizsignup/add-product?product=payment_methods&capabilities=GOOGLE_PAY';
|
||||||
|
},
|
||||||
|
|
||||||
|
'googlepay.settings.connection.status-text' => static function ( ContainerInterface $container ): string {
|
||||||
|
$state = $container->get( 'onboarding.state' );
|
||||||
|
if ( $state->current_state() < State::STATE_ONBOARDED ) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$product_status = $container->get( 'googlepay.helpers.apm-product-status' );
|
||||||
|
assert( $product_status instanceof ApmProductStatus );
|
||||||
|
|
||||||
|
$environment = $container->get( 'onboarding.environment' );
|
||||||
|
assert( $environment instanceof Environment );
|
||||||
|
|
||||||
|
$enabled = $product_status->is_active();
|
||||||
|
|
||||||
|
$enabled_status_text = esc_html__( 'Status: Available', 'woocommerce-paypal-payments' );
|
||||||
|
$disabled_status_text = esc_html__( 'Status: Not yet enabled', 'woocommerce-paypal-payments' );
|
||||||
|
|
||||||
|
$button_text = $enabled
|
||||||
|
? esc_html__( 'Settings', 'woocommerce-paypal-payments' )
|
||||||
|
: esc_html__( 'Enable Google Pay', 'woocommerce-paypal-payments' );
|
||||||
|
|
||||||
|
$enable_url = $environment->current_environment_is( Environment::PRODUCTION )
|
||||||
|
? $container->get( 'googlepay.enable-url-live' )
|
||||||
|
: $container->get( 'googlepay.enable-url-sandbox' );
|
||||||
|
|
||||||
|
$button_url = $enabled
|
||||||
|
? admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway#field-alternative_payment_methods' )
|
||||||
|
: $enable_url;
|
||||||
|
|
||||||
|
return sprintf(
|
||||||
|
'<p>%1$s %2$s</p><p><a target="%3$s" href="%4$s" class="button">%5$s</a></p>',
|
||||||
|
$enabled ? $enabled_status_text : $disabled_status_text,
|
||||||
|
$enabled ? '<span class="dashicons dashicons-yes"></span>' : '<span class="dashicons dashicons-no"></span>',
|
||||||
|
$enabled ? '_self' : '_blank',
|
||||||
|
esc_url( $button_url ),
|
||||||
|
esc_html( $button_text )
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
|
@ -11,7 +11,9 @@ namespace WooCommerce\PayPalCommerce\Googlepay\Assets;
|
||||||
|
|
||||||
use Exception;
|
use Exception;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
|
use WC_Countries;
|
||||||
use WooCommerce\PayPalCommerce\Button\Assets\ButtonInterface;
|
use WooCommerce\PayPalCommerce\Button\Assets\ButtonInterface;
|
||||||
|
use WooCommerce\PayPalCommerce\Googlepay\Endpoint\UpdatePaymentDataEndpoint;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
|
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
|
||||||
|
@ -127,6 +129,7 @@ class Button implements ButtonInterface {
|
||||||
*/
|
*/
|
||||||
public function initialize(): void {
|
public function initialize(): void {
|
||||||
add_filter( 'ppcp_onboarding_options', array( $this, 'add_onboarding_options' ), 10, 1 );
|
add_filter( 'ppcp_onboarding_options', array( $this, 'add_onboarding_options' ), 10, 1 );
|
||||||
|
add_filter( 'ppcp_partner_referrals_option', array( $this, 'filter_partner_referrals_option' ), 10, 1 );
|
||||||
add_filter( 'ppcp_partner_referrals_data', array( $this, 'add_partner_referrals_data' ), 10, 1 );
|
add_filter( 'ppcp_partner_referrals_data', array( $this, 'add_partner_referrals_data' ), 10, 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,6 +142,10 @@ class Button implements ButtonInterface {
|
||||||
* @psalm-suppress MissingClosureParamType
|
* @psalm-suppress MissingClosureParamType
|
||||||
*/
|
*/
|
||||||
public function add_onboarding_options( $options ): string {
|
public function add_onboarding_options( $options ): string {
|
||||||
|
if ( ! apply_filters( 'woocommerce_paypal_payments_google_pay_onboarding_option', false ) ) {
|
||||||
|
return $options;
|
||||||
|
}
|
||||||
|
|
||||||
$checked = '';
|
$checked = '';
|
||||||
try {
|
try {
|
||||||
$onboard_with_google = $this->settings->get( 'ppcp-onboarding-google' );
|
$onboard_with_google = $this->settings->get( 'ppcp-onboarding-google' );
|
||||||
|
@ -150,11 +157,28 @@ class Button implements ButtonInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
return $options
|
return $options
|
||||||
. '<li><label><input type="checkbox" id="ppcp-onboarding-google" ' . $checked . '> '
|
. '<li><label><input type="checkbox" id="ppcp-onboarding-google" ' . $checked . ' data-onboarding-option="ppcp-onboarding-google"> '
|
||||||
. __( 'Onboard with GooglePay', 'woocommerce-paypal-payments' )
|
. __( 'Onboard with GooglePay', 'woocommerce-paypal-payments' )
|
||||||
. '</label></li>';
|
. '</label></li>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters a partner referrals option.
|
||||||
|
*
|
||||||
|
* @param array $option The option data.
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function filter_partner_referrals_option( array $option ): array {
|
||||||
|
if ( $option['valid'] ) {
|
||||||
|
return $option;
|
||||||
|
}
|
||||||
|
if ( $option['field'] === 'ppcp-onboarding-google' ) {
|
||||||
|
$option['valid'] = true;
|
||||||
|
$option['value'] = ( $option['value'] ? '1' : '' );
|
||||||
|
}
|
||||||
|
return $option;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds to partner referrals data.
|
* Adds to partner referrals data.
|
||||||
*
|
*
|
||||||
|
@ -180,21 +204,17 @@ class Button implements ButtonInterface {
|
||||||
}
|
}
|
||||||
|
|
||||||
$data['capabilities'][] = 'GOOGLE_PAY';
|
$data['capabilities'][] = 'GOOGLE_PAY';
|
||||||
|
$data['operations'][] = array(
|
||||||
$nonce = $data['operations'][0]['api_integration_preference']['rest_api_integration']['first_party_details']['seller_nonce'];
|
|
||||||
|
|
||||||
$data['operations'][] = array(
|
|
||||||
'operation' => 'API_INTEGRATION',
|
'operation' => 'API_INTEGRATION',
|
||||||
'api_integration_preference' => array(
|
'api_integration_preference' => array(
|
||||||
'rest_api_integration' => array(
|
'rest_api_integration' => array(
|
||||||
'integration_method' => 'PAYPAL',
|
'integration_method' => 'PAYPAL',
|
||||||
'integration_type' => 'THIRD_PARTY',
|
'integration_type' => 'THIRD_PARTY',
|
||||||
'third_party_details' => array(
|
'third_party_details' => array(
|
||||||
'features' => array(
|
'features' => array(
|
||||||
'PAYMENT',
|
'PAYMENT',
|
||||||
'REFUND',
|
'REFUND',
|
||||||
),
|
),
|
||||||
'seller_nonce' => $nonce,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -358,14 +378,53 @@ class Button implements ButtonInterface {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueues scripts/styles for admin.
|
||||||
|
*/
|
||||||
|
public function enqueue_admin(): void {
|
||||||
|
wp_register_style(
|
||||||
|
'wc-ppcp-googlepay-admin',
|
||||||
|
untrailingslashit( $this->module_url ) . '/assets/css/styles.css',
|
||||||
|
array(),
|
||||||
|
$this->version
|
||||||
|
);
|
||||||
|
wp_enqueue_style( 'wc-ppcp-googlepay-admin' );
|
||||||
|
|
||||||
|
wp_register_script(
|
||||||
|
'wc-ppcp-googlepay-admin',
|
||||||
|
untrailingslashit( $this->module_url ) . '/assets/js/boot-admin.js',
|
||||||
|
array(),
|
||||||
|
$this->version,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
wp_enqueue_script( 'wc-ppcp-googlepay-admin' );
|
||||||
|
|
||||||
|
wp_localize_script(
|
||||||
|
'wc-ppcp-googlepay-admin',
|
||||||
|
'wc_ppcp_googlepay_admin',
|
||||||
|
$this->script_data()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The configuration for the smart buttons.
|
* The configuration for the smart buttons.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function script_data(): array {
|
public function script_data(): array {
|
||||||
|
$shipping = array(
|
||||||
|
'enabled' => $this->settings->has( 'googlepay_button_shipping_enabled' )
|
||||||
|
? boolval( $this->settings->get( 'googlepay_button_shipping_enabled' ) )
|
||||||
|
: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( $shipping['enabled'] ) {
|
||||||
|
$shipping['countries'] = array_keys( $this->wc_countries()->get_shipping_countries() );
|
||||||
|
}
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'environment' => $this->environment->current_environment_is( Environment::SANDBOX ) ? 'TEST' : 'PRODUCTION',
|
'environment' => $this->environment->current_environment_is( Environment::SANDBOX ) ? 'TEST' : 'PRODUCTION',
|
||||||
|
'is_debug' => defined( 'WP_DEBUG' ) && WP_DEBUG ? true : false,
|
||||||
'sdk_url' => $this->sdk_url,
|
'sdk_url' => $this->sdk_url,
|
||||||
'button' => array(
|
'button' => array(
|
||||||
'wrapper' => '#ppc-button-googlepay-container',
|
'wrapper' => '#ppc-button-googlepay-container',
|
||||||
|
@ -373,6 +432,13 @@ class Button implements ButtonInterface {
|
||||||
'mini_cart_wrapper' => '#ppc-button-googlepay-container-minicart',
|
'mini_cart_wrapper' => '#ppc-button-googlepay-container-minicart',
|
||||||
'mini_cart_style' => $this->button_styles_for_context( 'mini-cart' ),
|
'mini_cart_style' => $this->button_styles_for_context( 'mini-cart' ),
|
||||||
),
|
),
|
||||||
|
'shipping' => $shipping,
|
||||||
|
'ajax' => array(
|
||||||
|
'update_payment_data' => array(
|
||||||
|
'endpoint' => \WC_AJAX::get_endpoint( UpdatePaymentDataEndpoint::ENDPOINT ),
|
||||||
|
'nonce' => wp_create_nonce( UpdatePaymentDataEndpoint::nonce() ),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -404,4 +470,12 @@ class Button implements ButtonInterface {
|
||||||
return $values;
|
return $values;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a WC_Countries instance to check shipping
|
||||||
|
*
|
||||||
|
* @return WC_Countries
|
||||||
|
*/
|
||||||
|
private function wc_countries(): WC_Countries {
|
||||||
|
return new WC_Countries();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,219 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Endpoint to update payment data like shipping method and address.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\Button\Endpoint
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\Googlepay\Endpoint;
|
||||||
|
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use Throwable;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Money;
|
||||||
|
use WooCommerce\PayPalCommerce\Button\Endpoint\RequestData;
|
||||||
|
use WooCommerce\PayPalCommerce\Button\Exception\RuntimeException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class UpdatePaymentDataEndpoint
|
||||||
|
*/
|
||||||
|
class UpdatePaymentDataEndpoint {
|
||||||
|
|
||||||
|
const ENDPOINT = 'ppc-googlepay-update-payment-data';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The request data helper.
|
||||||
|
*
|
||||||
|
* @var RequestData
|
||||||
|
*/
|
||||||
|
private $request_data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The logger.
|
||||||
|
*
|
||||||
|
* @var LoggerInterface
|
||||||
|
*/
|
||||||
|
private $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UpdatePaymentDataEndpoint constructor.
|
||||||
|
*
|
||||||
|
* @param RequestData $request_data The request data helper.
|
||||||
|
* @param LoggerInterface $logger The logger.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
RequestData $request_data,
|
||||||
|
LoggerInterface $logger
|
||||||
|
) {
|
||||||
|
$this->request_data = $request_data;
|
||||||
|
$this->logger = $logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the nonce.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function nonce(): string {
|
||||||
|
return self::ENDPOINT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the request.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
* @throws RuntimeException When a validation fails.
|
||||||
|
*/
|
||||||
|
public function handle_request(): bool {
|
||||||
|
try {
|
||||||
|
$data = $this->request_data->read_request( $this->nonce() );
|
||||||
|
|
||||||
|
// Validate payment data.
|
||||||
|
if ( ! isset( $data['paymentData'] ) ) {
|
||||||
|
throw new RuntimeException(
|
||||||
|
__( 'No paymentData provided.', 'woocommerce-paypal-payments' )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$payment_data = $data['paymentData'];
|
||||||
|
|
||||||
|
// Set context as cart.
|
||||||
|
if ( is_callable( 'wc_maybe_define_constant' ) ) {
|
||||||
|
wc_maybe_define_constant( 'WOOCOMMERCE_CART', true );
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->update_addresses( $payment_data );
|
||||||
|
$this->update_shipping_method( $payment_data );
|
||||||
|
|
||||||
|
WC()->cart->calculate_shipping();
|
||||||
|
WC()->cart->calculate_fees();
|
||||||
|
WC()->cart->calculate_totals();
|
||||||
|
|
||||||
|
$total = (float) WC()->cart->get_total( 'numeric' );
|
||||||
|
|
||||||
|
// Shop settings.
|
||||||
|
$base_location = wc_get_base_location();
|
||||||
|
$shop_country_code = $base_location['country'];
|
||||||
|
$currency_code = get_woocommerce_currency();
|
||||||
|
|
||||||
|
wp_send_json_success(
|
||||||
|
array(
|
||||||
|
'total' => $total,
|
||||||
|
'total_str' => ( new Money( $total, $currency_code ) )->value_str(),
|
||||||
|
'currency_code' => $currency_code,
|
||||||
|
'country_code' => $shop_country_code,
|
||||||
|
'shipping_options' => $this->get_shipping_options(),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch ( Throwable $error ) {
|
||||||
|
$this->logger->error( "UpdatePaymentDataEndpoint execution failed. {$error->getMessage()} {$error->getFile()}:{$error->getLine()}" );
|
||||||
|
|
||||||
|
wp_send_json_error();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the array of available shipping methods.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function get_shipping_options(): array {
|
||||||
|
$shipping_options = array();
|
||||||
|
|
||||||
|
$calculated_packages = WC()->shipping->calculate_shipping(
|
||||||
|
WC()->cart->get_shipping_packages()
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( ! isset( $calculated_packages[0] ) && ! isset( $calculated_packages[0]['rates'] ) ) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ( $calculated_packages[0]['rates'] as $rate ) {
|
||||||
|
/**
|
||||||
|
* The shipping rate.
|
||||||
|
*
|
||||||
|
* @var \WC_Shipping_Rate $rate
|
||||||
|
*/
|
||||||
|
$shipping_options[] = array(
|
||||||
|
'id' => $rate->get_id(),
|
||||||
|
'label' => $rate->get_label(),
|
||||||
|
'description' => html_entity_decode(
|
||||||
|
wp_strip_all_tags(
|
||||||
|
wc_price( (float) $rate->get_cost(), array( 'currency' => get_woocommerce_currency() ) )
|
||||||
|
)
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! isset( $shipping_options[0] ) ) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' );
|
||||||
|
|
||||||
|
return array(
|
||||||
|
'defaultSelectedOptionId' => ( $chosen_shipping_methods[0] ?? null ) ? $chosen_shipping_methods[0] : $shipping_options[0]['id'],
|
||||||
|
'shippingOptions' => $shipping_options,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update addresses.
|
||||||
|
*
|
||||||
|
* @param array $payment_data The payment data.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function update_addresses( array $payment_data ): void {
|
||||||
|
if ( ! in_array( $payment_data['callbackTrigger'] ?? '', array( 'SHIPPING_ADDRESS', 'INITIALIZE' ), true ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The shipping methods.
|
||||||
|
*
|
||||||
|
* @var \WC_Customer|null $customer
|
||||||
|
*/
|
||||||
|
$customer = WC()->customer;
|
||||||
|
|
||||||
|
if ( ! $customer ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$customer->set_billing_postcode( $payment_data['shippingAddress']['postalCode'] ?? '' );
|
||||||
|
$customer->set_billing_country( $payment_data['shippingAddress']['countryCode'] ?? '' );
|
||||||
|
$customer->set_billing_state( '' );
|
||||||
|
$customer->set_billing_city( $payment_data['shippingAddress']['locality'] ?? '' );
|
||||||
|
|
||||||
|
$customer->set_shipping_postcode( $payment_data['shippingAddress']['postalCode'] ?? '' );
|
||||||
|
$customer->set_shipping_country( $payment_data['shippingAddress']['countryCode'] ?? '' );
|
||||||
|
$customer->set_shipping_state( '' );
|
||||||
|
$customer->set_shipping_city( $payment_data['shippingAddress']['locality'] ?? '' );
|
||||||
|
|
||||||
|
// Save the data.
|
||||||
|
$customer->save();
|
||||||
|
|
||||||
|
WC()->session->set( 'customer', WC()->customer->get_data() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update shipping method.
|
||||||
|
*
|
||||||
|
* @param array $payment_data The payment data.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function update_shipping_method( array $payment_data ): void {
|
||||||
|
$rate_id = $payment_data['shippingOptionData']['id'];
|
||||||
|
$calculated_packages = WC()->shipping->calculate_shipping(
|
||||||
|
WC()->cart->get_shipping_packages()
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( $rate_id && isset( $calculated_packages[0]['rates'][ $rate_id ] ) ) {
|
||||||
|
WC()->session->set( 'chosen_shipping_methods', array( $rate_id ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -11,7 +11,9 @@ namespace WooCommerce\PayPalCommerce\Googlepay;
|
||||||
|
|
||||||
use Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry;
|
use Automattic\WooCommerce\Blocks\Payments\PaymentMethodRegistry;
|
||||||
use WooCommerce\PayPalCommerce\Button\Assets\ButtonInterface;
|
use WooCommerce\PayPalCommerce\Button\Assets\ButtonInterface;
|
||||||
|
use WooCommerce\PayPalCommerce\Googlepay\Endpoint\UpdatePaymentDataEndpoint;
|
||||||
use WooCommerce\PayPalCommerce\Googlepay\Helper\ApmProductStatus;
|
use WooCommerce\PayPalCommerce\Googlepay\Helper\ApmProductStatus;
|
||||||
|
use WooCommerce\PayPalCommerce\Googlepay\Helper\AvailabilityNotice;
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider;
|
use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider;
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface;
|
use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface;
|
||||||
|
@ -37,18 +39,39 @@ class GooglepayModule implements ModuleInterface {
|
||||||
*/
|
*/
|
||||||
public function run( ContainerInterface $c ): void {
|
public function run( ContainerInterface $c ): void {
|
||||||
|
|
||||||
|
// Clears product status when appropriate.
|
||||||
|
add_action(
|
||||||
|
'woocommerce_paypal_payments_clear_apm_product_status',
|
||||||
|
function( Settings $settings = null ) use ( $c ): void {
|
||||||
|
$apm_status = $c->get( 'googlepay.helpers.apm-product-status' );
|
||||||
|
assert( $apm_status instanceof ApmProductStatus );
|
||||||
|
|
||||||
|
$apm_status->clear( $settings );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check if the module is applicable, correct country, currency, ... etc.
|
||||||
if ( ! $c->get( 'googlepay.eligible' ) ) {
|
if ( ! $c->get( 'googlepay.eligible' ) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load the button handler.
|
||||||
$button = $c->get( 'googlepay.button' );
|
$button = $c->get( 'googlepay.button' );
|
||||||
assert( $button instanceof ButtonInterface );
|
assert( $button instanceof ButtonInterface );
|
||||||
$button->initialize();
|
$button->initialize();
|
||||||
|
|
||||||
if ( ! $c->get( 'googlepay.available' ) ) {
|
// Show notice if there are product availability issues.
|
||||||
|
$availability_notice = $c->get( 'googlepay.availability_notice' );
|
||||||
|
assert( $availability_notice instanceof AvailabilityNotice );
|
||||||
|
$availability_notice->execute();
|
||||||
|
|
||||||
|
// Check if this merchant can activate / use the buttons.
|
||||||
|
// We allow non referral merchants as they can potentially still use GooglePay, we just have no way of checking the capability.
|
||||||
|
if ( ( ! $c->get( 'googlepay.available' ) ) && $c->get( 'googlepay.is_referral' ) ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initializes button rendering.
|
||||||
add_action(
|
add_action(
|
||||||
'wp',
|
'wp',
|
||||||
static function () use ( $c, $button ) {
|
static function () use ( $c, $button ) {
|
||||||
|
@ -59,6 +82,7 @@ class GooglepayModule implements ModuleInterface {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Enqueue frontend scripts.
|
||||||
add_action(
|
add_action(
|
||||||
'wp_enqueue_scripts',
|
'wp_enqueue_scripts',
|
||||||
static function () use ( $c, $button ) {
|
static function () use ( $c, $button ) {
|
||||||
|
@ -66,6 +90,23 @@ class GooglepayModule implements ModuleInterface {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Enqueue backend scripts.
|
||||||
|
add_action(
|
||||||
|
'admin_enqueue_scripts',
|
||||||
|
static function () use ( $c, $button ) {
|
||||||
|
if ( ! is_admin() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Should add this to the ButtonInterface.
|
||||||
|
*
|
||||||
|
* @psalm-suppress UndefinedInterfaceMethod
|
||||||
|
*/
|
||||||
|
$button->enqueue_admin();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Registers buttons on blocks pages.
|
||||||
add_action(
|
add_action(
|
||||||
'woocommerce_blocks_payment_method_type_registration',
|
'woocommerce_blocks_payment_method_type_registration',
|
||||||
function( PaymentMethodRegistry $payment_method_registry ) use ( $c, $button ): void {
|
function( PaymentMethodRegistry $payment_method_registry ) use ( $c, $button ): void {
|
||||||
|
@ -75,21 +116,26 @@ class GooglepayModule implements ModuleInterface {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
// Clear product status handling.
|
// Adds GooglePay component to the backend button preview settings.
|
||||||
add_action(
|
add_action(
|
||||||
'woocommerce_paypal_payments_clear_apm_product_status',
|
'woocommerce_paypal_payments_admin_gateway_settings',
|
||||||
function( Settings $settings = null ) use ( $c ): void {
|
function( array $settings ) use ( $c, $button ): array {
|
||||||
$apm_status = $c->get( 'googlepay.helpers.apm-product-status' );
|
if ( is_array( $settings['components'] ) ) {
|
||||||
assert( $apm_status instanceof ApmProductStatus );
|
$settings['components'][] = 'googlepay';
|
||||||
|
|
||||||
if ( ! $settings instanceof Settings ) {
|
|
||||||
$settings = null;
|
|
||||||
}
|
}
|
||||||
|
return $settings;
|
||||||
$apm_status->clear( $settings );
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Initialize AJAX endpoints.
|
||||||
|
add_action(
|
||||||
|
'wc_ajax_' . UpdatePaymentDataEndpoint::ENDPOINT,
|
||||||
|
static function () use ( $c ) {
|
||||||
|
$endpoint = $c->get( 'googlepay.endpoint.update-payment-data' );
|
||||||
|
assert( $endpoint instanceof UpdatePaymentDataEndpoint );
|
||||||
|
$endpoint->handle_request();
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -11,6 +11,7 @@ namespace WooCommerce\PayPalCommerce\Googlepay\Helper;
|
||||||
|
|
||||||
use Throwable;
|
use Throwable;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnersEndpoint;
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnersEndpoint;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Helper\FailureRegistry;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||||
|
|
||||||
|
@ -32,6 +33,13 @@ class ApmProductStatus {
|
||||||
*/
|
*/
|
||||||
private $current_status = null;
|
private $current_status = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If there was a request failure.
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $has_request_failure = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The settings.
|
* The settings.
|
||||||
*
|
*
|
||||||
|
@ -53,21 +61,31 @@ class ApmProductStatus {
|
||||||
*/
|
*/
|
||||||
private $onboarding_state;
|
private $onboarding_state;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The API failure registry
|
||||||
|
*
|
||||||
|
* @var FailureRegistry
|
||||||
|
*/
|
||||||
|
private $api_failure_registry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ApmProductStatus constructor.
|
* ApmProductStatus constructor.
|
||||||
*
|
*
|
||||||
* @param Settings $settings The Settings.
|
* @param Settings $settings The Settings.
|
||||||
* @param PartnersEndpoint $partners_endpoint The Partner Endpoint.
|
* @param PartnersEndpoint $partners_endpoint The Partner Endpoint.
|
||||||
* @param State $onboarding_state The onboarding state.
|
* @param State $onboarding_state The onboarding state.
|
||||||
|
* @param FailureRegistry $api_failure_registry The API failure registry.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
Settings $settings,
|
Settings $settings,
|
||||||
PartnersEndpoint $partners_endpoint,
|
PartnersEndpoint $partners_endpoint,
|
||||||
State $onboarding_state
|
State $onboarding_state,
|
||||||
|
FailureRegistry $api_failure_registry
|
||||||
) {
|
) {
|
||||||
$this->settings = $settings;
|
$this->settings = $settings;
|
||||||
$this->partners_endpoint = $partners_endpoint;
|
$this->partners_endpoint = $partners_endpoint;
|
||||||
$this->onboarding_state = $onboarding_state;
|
$this->onboarding_state = $onboarding_state;
|
||||||
|
$this->api_failure_registry = $api_failure_registry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -76,33 +94,47 @@ class ApmProductStatus {
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
public function is_active() : bool {
|
public function is_active() : bool {
|
||||||
if ( $this->onboarding_state->current_state() < State::STATE_ONBOARDED ) {
|
|
||||||
|
// If not onboarded then makes no sense to check status.
|
||||||
|
if ( ! $this->is_onboarded() ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If status was already checked on this request return the same result.
|
||||||
if ( null !== $this->current_status ) {
|
if ( null !== $this->current_status ) {
|
||||||
return $this->current_status;
|
return $this->current_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if status was checked on previous requests.
|
||||||
if ( $this->settings->has( self::SETTINGS_KEY ) && ( $this->settings->get( self::SETTINGS_KEY ) ) ) {
|
if ( $this->settings->has( self::SETTINGS_KEY ) && ( $this->settings->get( self::SETTINGS_KEY ) ) ) {
|
||||||
$this->current_status = wc_string_to_bool( $this->settings->get( self::SETTINGS_KEY ) );
|
$this->current_status = wc_string_to_bool( $this->settings->get( self::SETTINGS_KEY ) );
|
||||||
return $this->current_status;
|
return $this->current_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
// Check API failure registry to prevent multiple failed API requests.
|
||||||
$seller_status = $this->partners_endpoint->seller_status();
|
if ( $this->api_failure_registry->has_failure_in_timeframe( FailureRegistry::SELLER_STATUS_KEY, HOUR_IN_SECONDS ) ) {
|
||||||
} catch ( Throwable $error ) {
|
$this->has_request_failure = true;
|
||||||
// It may be a transitory error, don't persist the status.
|
$this->current_status = false;
|
||||||
$this->current_status = false;
|
|
||||||
return $this->current_status;
|
return $this->current_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Request seller status via PayPal API.
|
||||||
|
try {
|
||||||
|
$seller_status = $this->partners_endpoint->seller_status();
|
||||||
|
} catch ( Throwable $error ) {
|
||||||
|
$this->has_request_failure = true;
|
||||||
|
$this->current_status = false;
|
||||||
|
return $this->current_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the seller status for the intended capability.
|
||||||
foreach ( $seller_status->products() as $product ) {
|
foreach ( $seller_status->products() as $product ) {
|
||||||
if ( $product->name() !== 'PAYMENT_METHODS' ) {
|
if ( $product->name() !== 'PAYMENT_METHODS' ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( in_array( self::CAPABILITY_NAME, $product->capabilities(), true ) ) {
|
if ( in_array( self::CAPABILITY_NAME, $product->capabilities(), true ) ) {
|
||||||
|
// Capability found, persist status and return true.
|
||||||
$this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_ENABLED );
|
$this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_ENABLED );
|
||||||
$this->settings->persist();
|
$this->settings->persist();
|
||||||
|
|
||||||
|
@ -111,6 +143,7 @@ class ApmProductStatus {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Capability not found, persist status and return false.
|
||||||
$this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_DISABLED );
|
$this->settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_DISABLED );
|
||||||
$this->settings->persist();
|
$this->settings->persist();
|
||||||
|
|
||||||
|
@ -118,6 +151,24 @@ class ApmProductStatus {
|
||||||
return $this->current_status;
|
return $this->current_status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if the seller is onboarded.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function is_onboarded(): bool {
|
||||||
|
return $this->onboarding_state->current_state() >= State::STATE_ONBOARDED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if there was a request failure.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function has_request_failure(): bool {
|
||||||
|
return $this->has_request_failure;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears the persisted result to force a recheck.
|
* Clears the persisted result to force a recheck.
|
||||||
*
|
*
|
||||||
|
@ -132,8 +183,10 @@ class ApmProductStatus {
|
||||||
|
|
||||||
$this->current_status = null;
|
$this->current_status = null;
|
||||||
|
|
||||||
$settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_UNDEFINED );
|
if ( $settings->has( self::SETTINGS_KEY ) ) {
|
||||||
$settings->persist();
|
$settings->set( self::SETTINGS_KEY, self::SETTINGS_VALUE_UNDEFINED );
|
||||||
|
$settings->persist();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
159
modules/ppcp-googlepay/src/Helper/AvailabilityNotice.php
Normal file
159
modules/ppcp-googlepay/src/Helper/AvailabilityNotice.php
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Adds availability notice if applicable.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\Googlepay\Helper
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\Googlepay\Helper;
|
||||||
|
|
||||||
|
use WooCommerce\PayPalCommerce\AdminNotices\Entity\Message;
|
||||||
|
use WooCommerce\PayPalCommerce\AdminNotices\Repository\Repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class AvailabilityNotice
|
||||||
|
*/
|
||||||
|
class AvailabilityNotice {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The product status handler.
|
||||||
|
*
|
||||||
|
* @var ApmProductStatus
|
||||||
|
*/
|
||||||
|
private $product_status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if we're on the WooCommerce gateways list page.
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $is_wc_gateways_list_page;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if we're on a PPCP Settings page.
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $is_ppcp_settings_page;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ApmProductStatus constructor.
|
||||||
|
|
||||||
|
* @param ApmProductStatus $product_status The product status handler.
|
||||||
|
* @param bool $is_wc_gateways_list_page Indicates if we're on the WooCommerce gateways list page.
|
||||||
|
* @param bool $is_ppcp_settings_page Indicates if we're on a PPCP Settings page.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
ApmProductStatus $product_status,
|
||||||
|
bool $is_wc_gateways_list_page,
|
||||||
|
bool $is_ppcp_settings_page
|
||||||
|
) {
|
||||||
|
$this->product_status = $product_status;
|
||||||
|
$this->is_wc_gateways_list_page = $is_wc_gateways_list_page;
|
||||||
|
$this->is_ppcp_settings_page = $is_ppcp_settings_page;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds availability notice if applicable.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function execute(): void {
|
||||||
|
if ( ! $this->should_display() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to check is active before checking failure requests, otherwise failure status won't be set.
|
||||||
|
$is_active = $this->product_status->is_active();
|
||||||
|
|
||||||
|
if ( $this->product_status->has_request_failure() ) {
|
||||||
|
$this->add_seller_status_failure_notice();
|
||||||
|
} elseif ( ! $is_active ) {
|
||||||
|
$this->add_not_available_notice();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the message should display.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function should_display(): bool {
|
||||||
|
if ( ! $this->product_status->is_onboarded() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( ! $this->is_wc_gateways_list_page && ! $this->is_ppcp_settings_page ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds seller status failure notice.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function add_seller_status_failure_notice(): void {
|
||||||
|
add_filter(
|
||||||
|
Repository::NOTICES_FILTER,
|
||||||
|
/**
|
||||||
|
* Adds seller status notice.
|
||||||
|
*
|
||||||
|
* @param array $notices The notices.
|
||||||
|
* @return array
|
||||||
|
*
|
||||||
|
* @psalm-suppress MissingClosureParamType
|
||||||
|
*/
|
||||||
|
static function ( $notices ): array {
|
||||||
|
|
||||||
|
$message = sprintf(
|
||||||
|
// translators: %1$s and %2$s are the opening and closing of HTML <a> tag.
|
||||||
|
__(
|
||||||
|
'<p>Notice: We could not determine your PayPal seller status to list your available features. Disconnect and reconnect your PayPal account through our %1$sonboarding process%2$s to resolve this.</p><p>Don\'t worry if you cannot use the %1$sonboarding process%2$s; most functionalities available to your account should work.</p>',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
),
|
||||||
|
'<a href="https://woocommerce.com/document/woocommerce-paypal-payments/#connect-paypal-account" target="_blank">',
|
||||||
|
'</a>'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Name the key so it can be overridden in other modules.
|
||||||
|
$notices['error_product_status'] = new Message( $message, 'warning', true, 'ppcp-notice-wrapper' );
|
||||||
|
return $notices;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds not available notice.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function add_not_available_notice(): void {
|
||||||
|
add_filter(
|
||||||
|
Repository::NOTICES_FILTER,
|
||||||
|
/**
|
||||||
|
* Adds GooglePay not available notice.
|
||||||
|
*
|
||||||
|
* @param array $notices The notices.
|
||||||
|
* @return array
|
||||||
|
*
|
||||||
|
* @psalm-suppress MissingClosureParamType
|
||||||
|
*/
|
||||||
|
static function ( $notices ): array {
|
||||||
|
|
||||||
|
$message = sprintf(
|
||||||
|
__(
|
||||||
|
'Google Pay is not available on your PayPal seller account.',
|
||||||
|
'woocommerce-paypal-payments'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$notices[] = new Message( $message, 'warning', true, 'ppcp-notice-wrapper' );
|
||||||
|
return $notices;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ module.exports = {
|
||||||
entry: {
|
entry: {
|
||||||
'boot': path.resolve('./resources/js/boot.js'),
|
'boot': path.resolve('./resources/js/boot.js'),
|
||||||
'boot-block': path.resolve('./resources/js/boot-block.js'),
|
'boot-block': path.resolve('./resources/js/boot-block.js'),
|
||||||
|
'boot-admin': path.resolve('./resources/js/boot-admin.js'),
|
||||||
"styles": path.resolve('./resources/css/styles.scss')
|
"styles": path.resolve('./resources/css/styles.scss')
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
|
|
|
@ -13,84 +13,102 @@ const ppcp_onboarding = {
|
||||||
reload: function() {
|
reload: function() {
|
||||||
const buttons = document.querySelectorAll(ppcp_onboarding.BUTTON_SELECTOR);
|
const buttons = document.querySelectorAll(ppcp_onboarding.BUTTON_SELECTOR);
|
||||||
|
|
||||||
if (0 === buttons.length) {
|
if (buttons.length > 0) {
|
||||||
return;
|
// Add event listeners to buttons preventing link clicking if PayPal init failed.
|
||||||
|
buttons.forEach(
|
||||||
|
(element) => {
|
||||||
|
if (element.hasAttribute('data-ppcp-button-initialized')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
element.addEventListener(
|
||||||
|
'click',
|
||||||
|
(e) => {
|
||||||
|
if (!element.hasAttribute('data-ppcp-button-initialized') || 'undefined' === typeof window.PAYPAL) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Clear any previous PayPal scripts.
|
||||||
|
[ppcp_onboarding.PAYPAL_JS_ID, 'signup-js', 'biz-js'].forEach(
|
||||||
|
(scriptID) => {
|
||||||
|
const scriptTag = document.getElementById(scriptID);
|
||||||
|
|
||||||
|
if (scriptTag) {
|
||||||
|
scriptTag.parentNode.removeChild(scriptTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('undefined' !== typeof window.PAYPAL) {
|
||||||
|
delete window.PAYPAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Load PayPal scripts.
|
||||||
|
const paypalScriptTag = document.createElement('script');
|
||||||
|
paypalScriptTag.id = ppcp_onboarding.PAYPAL_JS_ID;
|
||||||
|
paypalScriptTag.src = PayPalCommerceGatewayOnboarding.paypal_js_url;
|
||||||
|
document.body.appendChild(paypalScriptTag);
|
||||||
|
|
||||||
|
if (ppcp_onboarding._timeout) {
|
||||||
|
clearTimeout(ppcp_onboarding._timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
ppcp_onboarding._timeout = setTimeout(
|
||||||
|
() => {
|
||||||
|
buttons.forEach((element) => { element.setAttribute('data-ppcp-button-initialized', 'true'); });
|
||||||
|
|
||||||
|
if ('undefined' !== window.PAYPAL.apps.Signup) {
|
||||||
|
window.PAYPAL.apps.Signup.render();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
1000
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add event listeners to buttons preventing link clicking if PayPal init failed.
|
const $onboarding_inputs = function () {
|
||||||
buttons.forEach(
|
return jQuery('*[data-onboarding-option]');
|
||||||
(element) => {
|
};
|
||||||
if (element.hasAttribute('data-ppcp-button-initialized')) {
|
const onboarding_options = function () {
|
||||||
return;
|
let options = {};
|
||||||
}
|
$onboarding_inputs().each((index, el) => {
|
||||||
|
const opt = jQuery(el).data('onboardingOption');
|
||||||
|
options[opt] = el.checked;
|
||||||
|
});
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
const disable_onboarding_options = function () {
|
||||||
|
$onboarding_inputs().each((index, el) => {
|
||||||
|
el.setAttribute('disabled', 'disabled');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const enable_onboarding_options = function () {
|
||||||
|
$onboarding_inputs().each((index, el) => {
|
||||||
|
el.removeAttribute('disabled');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const update_onboarding_options = function () {
|
||||||
|
const spinner = '<span class="spinner is-active" style="float: none;"></span>';
|
||||||
|
|
||||||
element.addEventListener(
|
disable_onboarding_options();
|
||||||
'click',
|
|
||||||
(e) => {
|
|
||||||
if (!element.hasAttribute('data-ppcp-button-initialized') || 'undefined' === typeof window.PAYPAL) {
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Clear any previous PayPal scripts.
|
|
||||||
[ppcp_onboarding.PAYPAL_JS_ID, 'signup-js', 'biz-js'].forEach(
|
|
||||||
(scriptID) => {
|
|
||||||
const scriptTag = document.getElementById(scriptID);
|
|
||||||
|
|
||||||
if (scriptTag) {
|
|
||||||
scriptTag.parentNode.removeChild(scriptTag);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('undefined' !== typeof window.PAYPAL) {
|
|
||||||
delete window.PAYPAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// Load PayPal scripts.
|
|
||||||
const paypalScriptTag = document.createElement('script');
|
|
||||||
paypalScriptTag.id = ppcp_onboarding.PAYPAL_JS_ID;
|
|
||||||
paypalScriptTag.src = PayPalCommerceGatewayOnboarding.paypal_js_url;
|
|
||||||
document.body.appendChild(paypalScriptTag);
|
|
||||||
|
|
||||||
if (ppcp_onboarding._timeout) {
|
|
||||||
clearTimeout(ppcp_onboarding._timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
ppcp_onboarding._timeout = setTimeout(
|
|
||||||
() => {
|
|
||||||
buttons.forEach((element) => { element.setAttribute('data-ppcp-button-initialized', 'true'); });
|
|
||||||
|
|
||||||
if ('undefined' !== window.PAYPAL.apps.Signup) {
|
|
||||||
window.PAYPAL.apps.Signup.render();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
1000
|
|
||||||
);
|
|
||||||
|
|
||||||
const onboard_pui = document.querySelector('#ppcp-onboarding-pui');
|
|
||||||
const spinner = '<span class="spinner is-active" style="float: none;"></span>';
|
|
||||||
onboard_pui?.addEventListener('click', (event) => {
|
|
||||||
event.preventDefault();
|
|
||||||
onboard_pui.setAttribute('disabled', 'disabled');
|
|
||||||
buttons.forEach((element) => {
|
buttons.forEach((element) => {
|
||||||
element.removeAttribute('href');
|
element.removeAttribute('href');
|
||||||
element.setAttribute('disabled', 'disabled');
|
element.setAttribute('disabled', 'disabled');
|
||||||
jQuery(spinner).insertAfter(element);
|
jQuery(spinner).insertAfter(element);
|
||||||
});
|
});
|
||||||
|
|
||||||
fetch(PayPalCommerceGatewayOnboarding.pui_endpoint, {
|
fetch(PayPalCommerceGatewayOnboarding.update_signup_links_endpoint, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
credentials: 'same-origin',
|
credentials: 'same-origin',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
nonce: PayPalCommerceGatewayOnboarding.pui_nonce,
|
nonce: PayPalCommerceGatewayOnboarding.update_signup_links_nonce,
|
||||||
checked: onboard_pui.checked
|
settings: onboarding_options()
|
||||||
})
|
})
|
||||||
}).then((res)=>{
|
}).then((res)=>{
|
||||||
return res.json();
|
return res.json();
|
||||||
|
@ -99,7 +117,6 @@ const ppcp_onboarding = {
|
||||||
alert('Could not update signup buttons: ' + JSON.stringify(data));
|
alert('Could not update signup buttons: ' + JSON.stringify(data));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
buttons.forEach((element) => {
|
buttons.forEach((element) => {
|
||||||
for (let [key, value] of Object.entries(data.data.signup_links)) {
|
for (let [key, value] of Object.entries(data.data.signup_links)) {
|
||||||
key = 'connect-to' + key.replace(/-/g, '');
|
key = 'connect-to' + key.replace(/-/g, '');
|
||||||
|
@ -110,9 +127,13 @@ const ppcp_onboarding = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
onboard_pui.removeAttribute('disabled');
|
enable_onboarding_options();
|
||||||
});
|
});
|
||||||
})
|
}
|
||||||
|
$onboarding_inputs().on('click', (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
update_onboarding_options();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
loginSeller: function(env, authCode, sharedId) {
|
loginSeller: function(env, authCode, sharedId) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
document.addEventListener(
|
document.addEventListener(
|
||||||
'DOMContentLoaded',
|
'DOMContentLoaded',
|
||||||
() => {
|
() => {
|
||||||
const payLaterMessagingSelectableLocations = ['product', 'cart', 'checkout'];
|
const payLaterMessagingSelectableLocations = ['product', 'cart', 'checkout', 'shop', 'home'];
|
||||||
const payLaterMessagingAllLocations = payLaterMessagingSelectableLocations.concat('general');
|
const payLaterMessagingAllLocations = payLaterMessagingSelectableLocations.concat('general');
|
||||||
const payLaterMessagingLocationsSelector = '#field-pay_later_messaging_locations';
|
const payLaterMessagingLocationsSelector = '#field-pay_later_messaging_locations';
|
||||||
const payLaterMessagingLocationsSelect = payLaterMessagingLocationsSelector + ' select';
|
const payLaterMessagingLocationsSelect = payLaterMessagingLocationsSelector + ' select';
|
||||||
|
@ -9,7 +9,7 @@ document.addEventListener(
|
||||||
|
|
||||||
const smartButtonLocationsSelector = '#field-smart_button_locations';
|
const smartButtonLocationsSelector = '#field-smart_button_locations';
|
||||||
const smartButtonLocationsSelect = smartButtonLocationsSelector + ' select';
|
const smartButtonLocationsSelect = smartButtonLocationsSelector + ' select';
|
||||||
const smartButtonSelectableLocations = payLaterMessagingSelectableLocations.concat('mini-cart');
|
const smartButtonSelectableLocations = ['product', 'cart', 'checkout', 'mini-cart'];
|
||||||
|
|
||||||
const groupToggle = (selector, group) => {
|
const groupToggle = (selector, group) => {
|
||||||
const toggleElement = document.querySelector(selector);
|
const toggleElement = document.querySelector(selector);
|
||||||
|
@ -19,7 +19,10 @@ document.addEventListener(
|
||||||
|
|
||||||
if (! toggleElement.checked) {
|
if (! toggleElement.checked) {
|
||||||
group.forEach( (elementToHide) => {
|
group.forEach( (elementToHide) => {
|
||||||
document.querySelector(elementToHide).style.display = 'none';
|
const element = document.querySelector(elementToHide);
|
||||||
|
if (element) {
|
||||||
|
element.style.display = 'none';
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
toggleElement.addEventListener(
|
toggleElement.addEventListener(
|
||||||
|
@ -27,7 +30,10 @@ document.addEventListener(
|
||||||
(event) => {
|
(event) => {
|
||||||
if (! event.target.checked) {
|
if (! event.target.checked) {
|
||||||
group.forEach( (elementToHide) => {
|
group.forEach( (elementToHide) => {
|
||||||
document.querySelector(elementToHide).style.display = 'none';
|
const element = document.querySelector(elementToHide);
|
||||||
|
if (element) {
|
||||||
|
element.style.display = 'none';
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -18,7 +18,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnerReferrals;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
|
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\Assets\OnboardingAssets;
|
use WooCommerce\PayPalCommerce\Onboarding\Assets\OnboardingAssets;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\Endpoint\LoginSellerEndpoint;
|
use WooCommerce\PayPalCommerce\Onboarding\Endpoint\LoginSellerEndpoint;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\Endpoint\PayUponInvoiceEndpoint;
|
use WooCommerce\PayPalCommerce\Onboarding\Endpoint\UpdateSignupLinksEndpoint;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingOptionsRenderer;
|
use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingOptionsRenderer;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingRenderer;
|
use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingRenderer;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\OnboardingRESTController;
|
use WooCommerce\PayPalCommerce\Onboarding\OnboardingRESTController;
|
||||||
|
@ -187,8 +187,8 @@ return array(
|
||||||
$logger
|
$logger
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
'onboarding.endpoint.pui' => static function( ContainerInterface $container ) : PayUponInvoiceEndpoint {
|
'onboarding.endpoint.pui' => static function( ContainerInterface $container ) : UpdateSignupLinksEndpoint {
|
||||||
return new PayUponInvoiceEndpoint(
|
return new UpdateSignupLinksEndpoint(
|
||||||
$container->get( 'wcgateway.settings' ),
|
$container->get( 'wcgateway.settings' ),
|
||||||
$container->get( 'button.request-data' ),
|
$container->get( 'button.request-data' ),
|
||||||
$container->get( 'onboarding.signup-link-cache' ),
|
$container->get( 'onboarding.signup-link-cache' ),
|
||||||
|
|
|
@ -10,6 +10,7 @@ declare(strict_types=1);
|
||||||
namespace WooCommerce\PayPalCommerce\Onboarding\Assets;
|
namespace WooCommerce\PayPalCommerce\Onboarding\Assets;
|
||||||
|
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\Endpoint\LoginSellerEndpoint;
|
use WooCommerce\PayPalCommerce\Onboarding\Endpoint\LoginSellerEndpoint;
|
||||||
|
use WooCommerce\PayPalCommerce\Onboarding\Endpoint\UpdateSignupLinksEndpoint;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||||
|
@ -145,18 +146,18 @@ class OnboardingAssets {
|
||||||
*/
|
*/
|
||||||
public function get_script_data() {
|
public function get_script_data() {
|
||||||
return array(
|
return array(
|
||||||
'endpoint' => \WC_AJAX::get_endpoint( LoginSellerEndpoint::ENDPOINT ),
|
'endpoint' => \WC_AJAX::get_endpoint( LoginSellerEndpoint::ENDPOINT ),
|
||||||
'nonce' => wp_create_nonce( $this->login_seller_endpoint::nonce() ),
|
'nonce' => wp_create_nonce( $this->login_seller_endpoint::nonce() ),
|
||||||
'paypal_js_url' => 'https://www.paypal.com/webapps/merchantboarding/js/lib/lightbox/partner.js',
|
'paypal_js_url' => 'https://www.paypal.com/webapps/merchantboarding/js/lib/lightbox/partner.js',
|
||||||
'sandbox_state' => State::get_state_name( $this->state->sandbox_state() ),
|
'sandbox_state' => State::get_state_name( $this->state->sandbox_state() ),
|
||||||
'production_state' => State::get_state_name( $this->state->production_state() ),
|
'production_state' => State::get_state_name( $this->state->production_state() ),
|
||||||
'current_state' => State::get_state_name( $this->state->current_state() ),
|
'current_state' => State::get_state_name( $this->state->current_state() ),
|
||||||
'current_env' => $this->environment->current_environment(),
|
'current_env' => $this->environment->current_environment(),
|
||||||
'error_messages' => array(
|
'error_messages' => array(
|
||||||
'no_credentials' => __( 'API credentials must be entered to save the settings.', 'woocommerce-paypal-payments' ),
|
'no_credentials' => __( 'API credentials must be entered to save the settings.', 'woocommerce-paypal-payments' ),
|
||||||
),
|
),
|
||||||
'pui_endpoint' => \WC_AJAX::get_endpoint( 'ppc-pui' ),
|
'update_signup_links_endpoint' => \WC_AJAX::get_endpoint( UpdateSignupLinksEndpoint::ENDPOINT ),
|
||||||
'pui_nonce' => wp_create_nonce( 'ppc-pui' ),
|
'update_signup_links_nonce' => wp_create_nonce( UpdateSignupLinksEndpoint::ENDPOINT ),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,14 +14,17 @@ use Psr\Log\LoggerInterface;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
|
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
|
||||||
use WooCommerce\PayPalCommerce\Button\Endpoint\EndpointInterface;
|
use WooCommerce\PayPalCommerce\Button\Endpoint\EndpointInterface;
|
||||||
use WooCommerce\PayPalCommerce\Button\Endpoint\RequestData;
|
use WooCommerce\PayPalCommerce\Button\Endpoint\RequestData;
|
||||||
|
use WooCommerce\PayPalCommerce\Onboarding\Helper\OnboardingUrl;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingRenderer;
|
use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingRenderer;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
|
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class PayUponInvoiceEndpoint
|
* Class UpdateSignupLinksEndpoint
|
||||||
*/
|
*/
|
||||||
class PayUponInvoiceEndpoint implements EndpointInterface {
|
class UpdateSignupLinksEndpoint implements EndpointInterface {
|
||||||
|
|
||||||
|
const ENDPOINT = 'ppc-update-signup-links';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The settings.
|
* The settings.
|
||||||
|
@ -66,7 +69,7 @@ class PayUponInvoiceEndpoint implements EndpointInterface {
|
||||||
protected $logger;
|
protected $logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PayUponInvoiceEndpoint constructor.
|
* UpdateSignupLinksEndpoint constructor.
|
||||||
*
|
*
|
||||||
* @param Settings $settings The settings.
|
* @param Settings $settings The settings.
|
||||||
* @param RequestData $request_data The request data.
|
* @param RequestData $request_data The request data.
|
||||||
|
@ -97,7 +100,7 @@ class PayUponInvoiceEndpoint implements EndpointInterface {
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function nonce(): string {
|
public static function nonce(): string {
|
||||||
return 'ppc-pui';
|
return self::ENDPOINT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -116,13 +119,26 @@ class PayUponInvoiceEndpoint implements EndpointInterface {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$data = $this->request_data->read_request( $this->nonce() );
|
$data = $this->request_data->read_request( $this->nonce() );
|
||||||
$this->settings->set( 'ppcp-onboarding-pui', $data['checked'] );
|
|
||||||
|
foreach ( $data['settings'] ?? array() as $field => $value ) {
|
||||||
|
$option = apply_filters(
|
||||||
|
'ppcp_partner_referrals_option',
|
||||||
|
array(
|
||||||
|
'field' => $field,
|
||||||
|
'value' => $value,
|
||||||
|
'valid' => false,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( $option['valid'] ) {
|
||||||
|
$this->settings->set( $field, $value );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$this->settings->persist();
|
$this->settings->persist();
|
||||||
|
|
||||||
foreach ( $this->signup_link_ids as $key ) {
|
foreach ( $this->signup_link_ids as $key ) {
|
||||||
if ( $this->signup_link_cache->has( $key ) ) {
|
( new OnboardingUrl( $this->signup_link_cache, $key, get_current_user_id() ) )->delete();
|
||||||
$this->signup_link_cache->delete( $key );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ( $this->signup_link_ids as $key ) {
|
foreach ( $this->signup_link_ids as $key ) {
|
|
@ -9,6 +9,7 @@ declare(strict_types=1);
|
||||||
|
|
||||||
namespace WooCommerce\PayPalCommerce\Onboarding;
|
namespace WooCommerce\PayPalCommerce\Onboarding;
|
||||||
|
|
||||||
|
use WooCommerce\PayPalCommerce\Onboarding\Endpoint\UpdateSignupLinksEndpoint;
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider;
|
use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider;
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\Assets\OnboardingAssets;
|
use WooCommerce\PayPalCommerce\Onboarding\Assets\OnboardingAssets;
|
||||||
|
@ -96,7 +97,7 @@ class OnboardingModule implements ModuleInterface {
|
||||||
);
|
);
|
||||||
|
|
||||||
add_action(
|
add_action(
|
||||||
'wc_ajax_ppc-pui',
|
'wc_ajax_' . UpdateSignupLinksEndpoint::ENDPOINT,
|
||||||
static function () use ( $c ) {
|
static function () use ( $c ) {
|
||||||
$endpoint = $c->get( 'onboarding.endpoint.pui' );
|
$endpoint = $c->get( 'onboarding.endpoint.pui' );
|
||||||
$endpoint->handle_request();
|
$endpoint->handle_request();
|
||||||
|
|
|
@ -95,7 +95,7 @@ class OnboardingOptionsRenderer {
|
||||||
$checked = '';
|
$checked = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
return '<li><label><input type="checkbox" id="ppcp-onboarding-pui" ' . $checked . '> ' .
|
return '<li><label><input type="checkbox" id="ppcp-onboarding-pui" ' . $checked . ' data-onboarding-option="ppcp-onboarding-pui"> ' .
|
||||||
__( 'Onboard with Pay upon Invoice', 'woocommerce-paypal-payments' ) . '
|
__( 'Onboard with Pay upon Invoice', 'woocommerce-paypal-payments' ) . '
|
||||||
</label></li>';
|
</label></li>';
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ document.addEventListener(
|
||||||
jQuery( '*[data-ppcp-display]' ).each( (index, el) => {
|
jQuery( '*[data-ppcp-display]' ).each( (index, el) => {
|
||||||
const rules = jQuery(el).data('ppcpDisplay');
|
const rules = jQuery(el).data('ppcpDisplay');
|
||||||
|
|
||||||
console.log('rules', rules);
|
// console.log('rules', rules);
|
||||||
|
|
||||||
for (const rule of rules) {
|
for (const rule of rules) {
|
||||||
displayManager.addRule(rule);
|
displayManager.addRule(rule);
|
||||||
|
|
|
@ -14,11 +14,11 @@ class DisplayManager {
|
||||||
addRule(ruleConfig) {
|
addRule(ruleConfig) {
|
||||||
const updateStatus = () => {
|
const updateStatus = () => {
|
||||||
this.ruleStatus[ruleConfig.key] = this.rules[ruleConfig.key].status;
|
this.ruleStatus[ruleConfig.key] = this.rules[ruleConfig.key].status;
|
||||||
console.log('ruleStatus', this.ruleStatus);
|
//console.log('ruleStatus', this.ruleStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.rules[ruleConfig.key] = new Rule(ruleConfig, updateStatus.bind(this));
|
this.rules[ruleConfig.key] = new Rule(ruleConfig, updateStatus.bind(this));
|
||||||
console.log('Rule', this.rules[ruleConfig.key]);
|
//console.log('Rule', this.rules[ruleConfig.key]);
|
||||||
}
|
}
|
||||||
|
|
||||||
register() {
|
register() {
|
||||||
|
|
|
@ -15,14 +15,14 @@ class Rule {
|
||||||
const condition = ConditionFactory.make(conditionConfig, updateStatus);
|
const condition = ConditionFactory.make(conditionConfig, updateStatus);
|
||||||
this.conditions[condition.key] = condition;
|
this.conditions[condition.key] = condition;
|
||||||
|
|
||||||
console.log('Condition', condition);
|
//console.log('Condition', condition);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const actionConfig of this.config.actions) {
|
for (const actionConfig of this.config.actions) {
|
||||||
const action = ActionFactory.make(actionConfig);
|
const action = ActionFactory.make(actionConfig);
|
||||||
this.actions[action.key] = action;
|
this.actions[action.key] = action;
|
||||||
|
|
||||||
console.log('Action', action);
|
//console.log('Action', action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,7 @@ document.addEventListener(
|
||||||
|
|
||||||
try {
|
try {
|
||||||
renderer.render({});
|
renderer.render({});
|
||||||
|
jQuery(document).trigger('ppcp_paypal_render_preview', settings);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
}
|
}
|
||||||
|
@ -113,7 +114,7 @@ document.addEventListener(
|
||||||
'client-id': PayPalCommerceGatewaySettings.client_id,
|
'client-id': PayPalCommerceGatewaySettings.client_id,
|
||||||
'currency': PayPalCommerceGatewaySettings.currency,
|
'currency': PayPalCommerceGatewaySettings.currency,
|
||||||
'integration-date': PayPalCommerceGatewaySettings.integration_date,
|
'integration-date': PayPalCommerceGatewaySettings.integration_date,
|
||||||
'components': ['buttons', 'funding-eligibility', 'messages'],
|
'components': PayPalCommerceGatewaySettings.components,
|
||||||
'enable-funding': ['venmo', 'paylater'],
|
'enable-funding': ['venmo', 'paylater'],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -172,11 +173,16 @@ document.addEventListener(
|
||||||
|
|
||||||
function createMessagesPreview(settingsCallback) {
|
function createMessagesPreview(settingsCallback) {
|
||||||
const render = (settings) => {
|
const render = (settings) => {
|
||||||
const wrapper = document.querySelector(settings.wrapper);
|
let wrapper = document.querySelector(settings.wrapper);
|
||||||
if (!wrapper) {
|
if (!wrapper) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
wrapper.innerHTML = '';
|
// looks like .innerHTML = '' is not enough, PayPal somehow renders with old style
|
||||||
|
const parent = wrapper.parentElement;
|
||||||
|
parent.removeChild(wrapper);
|
||||||
|
wrapper = document.createElement('div');
|
||||||
|
wrapper.setAttribute('id', settings.wrapper.replace('#', ''));
|
||||||
|
parent.appendChild(wrapper);
|
||||||
|
|
||||||
const messageRenderer = new MessageRenderer(settings);
|
const messageRenderer = new MessageRenderer(settings);
|
||||||
|
|
||||||
|
@ -269,7 +275,7 @@ document.addEventListener(
|
||||||
}, 1000));
|
}, 1000));
|
||||||
|
|
||||||
loadPaypalScript(oldScriptSettings, () => {
|
loadPaypalScript(oldScriptSettings, () => {
|
||||||
const payLaterMessagingLocations = ['product', 'cart', 'checkout', 'general'];
|
const payLaterMessagingLocations = ['product', 'cart', 'checkout', 'shop', 'home', 'general'];
|
||||||
const paypalButtonLocations = ['product', 'cart', 'checkout', 'mini-cart', 'general'];
|
const paypalButtonLocations = ['product', 'cart', 'checkout', 'mini-cart', 'general'];
|
||||||
|
|
||||||
paypalButtonLocations.forEach((location) => {
|
paypalButtonLocations.forEach((location) => {
|
||||||
|
|
|
@ -1021,7 +1021,8 @@ return array(
|
||||||
$partner_endpoint,
|
$partner_endpoint,
|
||||||
$container->get( 'dcc.status-cache' ),
|
$container->get( 'dcc.status-cache' ),
|
||||||
$container->get( 'api.helpers.dccapplies' ),
|
$container->get( 'api.helpers.dccapplies' ),
|
||||||
$container->get( 'onboarding.state' )
|
$container->get( 'onboarding.state' ),
|
||||||
|
$container->get( 'api.helper.failure-registry' )
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -1101,7 +1102,8 @@ return array(
|
||||||
$container->get( 'wcgateway.settings' ),
|
$container->get( 'wcgateway.settings' ),
|
||||||
$container->get( 'api.endpoint.partners' ),
|
$container->get( 'api.endpoint.partners' ),
|
||||||
$container->get( 'pui.status-cache' ),
|
$container->get( 'pui.status-cache' ),
|
||||||
$container->get( 'onboarding.state' )
|
$container->get( 'onboarding.state' ),
|
||||||
|
$container->get( 'api.helper.failure-registry' )
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
'wcgateway.pay-upon-invoice' => static function ( ContainerInterface $container ): PayUponInvoice {
|
'wcgateway.pay-upon-invoice' => static function ( ContainerInterface $container ): PayUponInvoice {
|
||||||
|
@ -1354,7 +1356,13 @@ return array(
|
||||||
'wcgateway.settings.pay-later.messaging-locations' => static function( ContainerInterface $container ): array {
|
'wcgateway.settings.pay-later.messaging-locations' => static function( ContainerInterface $container ): array {
|
||||||
$button_locations = $container->get( 'wcgateway.button.locations' );
|
$button_locations = $container->get( 'wcgateway.button.locations' );
|
||||||
unset( $button_locations['mini-cart'] );
|
unset( $button_locations['mini-cart'] );
|
||||||
return $button_locations;
|
return array_merge(
|
||||||
|
$button_locations,
|
||||||
|
array(
|
||||||
|
'shop' => __( 'Shop', 'woocommerce-paypal-payments' ),
|
||||||
|
'home' => __( 'Home', 'woocommerce-paypal-payments' ),
|
||||||
|
)
|
||||||
|
);
|
||||||
},
|
},
|
||||||
'wcgateway.button.default-locations' => static function( ContainerInterface $container ): array {
|
'wcgateway.button.default-locations' => static function( ContainerInterface $container ): array {
|
||||||
return array_keys( $container->get( 'wcgateway.settings.pay-later.messaging-locations' ) );
|
return array_keys( $container->get( 'wcgateway.settings.pay-later.messaging-locations' ) );
|
||||||
|
|
|
@ -211,16 +211,20 @@ class SettingsPageAssets {
|
||||||
wp_localize_script(
|
wp_localize_script(
|
||||||
'ppcp-gateway-settings',
|
'ppcp-gateway-settings',
|
||||||
'PayPalCommerceGatewaySettings',
|
'PayPalCommerceGatewaySettings',
|
||||||
array(
|
apply_filters(
|
||||||
'is_subscriptions_plugin_active' => $this->subscription_helper->plugin_is_active(),
|
'woocommerce_paypal_payments_admin_gateway_settings',
|
||||||
'client_id' => $this->client_id,
|
array(
|
||||||
'currency' => $this->currency,
|
'is_subscriptions_plugin_active' => $this->subscription_helper->plugin_is_active(),
|
||||||
'country' => $this->country,
|
'client_id' => $this->client_id,
|
||||||
'environment' => $this->environment->current_environment(),
|
'currency' => $this->currency,
|
||||||
'integration_date' => PAYPAL_INTEGRATION_DATE,
|
'country' => $this->country,
|
||||||
'is_pay_later_button_enabled' => $this->is_pay_later_button_enabled,
|
'environment' => $this->environment->current_environment(),
|
||||||
'disabled_sources' => $this->disabled_sources,
|
'integration_date' => PAYPAL_INTEGRATION_DATE,
|
||||||
'all_funding_sources' => $this->all_funding_sources,
|
'is_pay_later_button_enabled' => $this->is_pay_later_button_enabled,
|
||||||
|
'disabled_sources' => $this->disabled_sources,
|
||||||
|
'all_funding_sources' => $this->all_funding_sources,
|
||||||
|
'components' => array( 'buttons', 'funding-eligibility', 'messages' ),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -142,6 +142,20 @@ class PayUponInvoice {
|
||||||
$this->settings->persist();
|
$this->settings->persist();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
add_filter(
|
||||||
|
'ppcp_partner_referrals_option',
|
||||||
|
function ( array $option ): array {
|
||||||
|
if ( $option['valid'] ) {
|
||||||
|
return $option;
|
||||||
|
}
|
||||||
|
if ( $option['field'] === 'ppcp-onboarding-pui' ) {
|
||||||
|
$option['valid'] = true;
|
||||||
|
$option['value'] = ( $option['value'] ? '1' : '' );
|
||||||
|
}
|
||||||
|
return $option;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
add_filter(
|
add_filter(
|
||||||
'ppcp_partner_referrals_data',
|
'ppcp_partner_referrals_data',
|
||||||
function ( array $data ): array {
|
function ( array $data ): array {
|
||||||
|
|
|
@ -14,6 +14,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnersEndpoint;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatusProduct;
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatusProduct;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
|
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
|
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Helper\FailureRegistry;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||||
|
|
||||||
|
@ -37,6 +38,14 @@ class DCCProductStatus {
|
||||||
* @var bool|null
|
* @var bool|null
|
||||||
*/
|
*/
|
||||||
private $current_status_cache;
|
private $current_status_cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If there was a request failure.
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $has_request_failure = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The settings.
|
* The settings.
|
||||||
*
|
*
|
||||||
|
@ -65,6 +74,13 @@ class DCCProductStatus {
|
||||||
*/
|
*/
|
||||||
private $onboarding_state;
|
private $onboarding_state;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The API failure registry
|
||||||
|
*
|
||||||
|
* @var FailureRegistry
|
||||||
|
*/
|
||||||
|
private $api_failure_registry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DccProductStatus constructor.
|
* DccProductStatus constructor.
|
||||||
*
|
*
|
||||||
|
@ -73,19 +89,22 @@ class DCCProductStatus {
|
||||||
* @param Cache $cache The cache.
|
* @param Cache $cache The cache.
|
||||||
* @param DccApplies $dcc_applies The dcc applies helper.
|
* @param DccApplies $dcc_applies The dcc applies helper.
|
||||||
* @param State $onboarding_state The onboarding state.
|
* @param State $onboarding_state The onboarding state.
|
||||||
|
* @param FailureRegistry $api_failure_registry The API failure registry.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
Settings $settings,
|
Settings $settings,
|
||||||
PartnersEndpoint $partners_endpoint,
|
PartnersEndpoint $partners_endpoint,
|
||||||
Cache $cache,
|
Cache $cache,
|
||||||
DccApplies $dcc_applies,
|
DccApplies $dcc_applies,
|
||||||
State $onboarding_state
|
State $onboarding_state,
|
||||||
|
FailureRegistry $api_failure_registry
|
||||||
) {
|
) {
|
||||||
$this->settings = $settings;
|
$this->settings = $settings;
|
||||||
$this->partners_endpoint = $partners_endpoint;
|
$this->partners_endpoint = $partners_endpoint;
|
||||||
$this->cache = $cache;
|
$this->cache = $cache;
|
||||||
$this->dcc_applies = $dcc_applies;
|
$this->dcc_applies = $dcc_applies;
|
||||||
$this->onboarding_state = $onboarding_state;
|
$this->onboarding_state = $onboarding_state;
|
||||||
|
$this->api_failure_registry = $api_failure_registry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -111,9 +130,17 @@ class DCCProductStatus {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check API failure registry to prevent multiple failed API requests.
|
||||||
|
if ( $this->api_failure_registry->has_failure_in_timeframe( FailureRegistry::SELLER_STATUS_KEY, HOUR_IN_SECONDS ) ) {
|
||||||
|
$this->has_request_failure = true;
|
||||||
|
$this->current_status_cache = false;
|
||||||
|
return $this->current_status_cache;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$seller_status = $this->partners_endpoint->seller_status();
|
$seller_status = $this->partners_endpoint->seller_status();
|
||||||
} catch ( Throwable $error ) {
|
} catch ( Throwable $error ) {
|
||||||
|
$this->has_request_failure = true;
|
||||||
$this->current_status_cache = false;
|
$this->current_status_cache = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -149,4 +176,14 @@ class DCCProductStatus {
|
||||||
$this->current_status_cache = false;
|
$this->current_status_cache = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if there was a request failure.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function has_request_failure(): bool {
|
||||||
|
return $this->has_request_failure;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ use Throwable;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnersEndpoint;
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnersEndpoint;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatusProduct;
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatusProduct;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
|
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Helper\FailureRegistry;
|
||||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||||
|
|
||||||
|
@ -36,6 +37,14 @@ class PayUponInvoiceProductStatus {
|
||||||
* @var bool|null
|
* @var bool|null
|
||||||
*/
|
*/
|
||||||
private $current_status_cache;
|
private $current_status_cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If there was a request failure.
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $has_request_failure = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The settings.
|
* The settings.
|
||||||
*
|
*
|
||||||
|
@ -57,6 +66,13 @@ class PayUponInvoiceProductStatus {
|
||||||
*/
|
*/
|
||||||
private $onboarding_state;
|
private $onboarding_state;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The API failure registry
|
||||||
|
*
|
||||||
|
* @var FailureRegistry
|
||||||
|
*/
|
||||||
|
private $api_failure_registry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PayUponInvoiceProductStatus constructor.
|
* PayUponInvoiceProductStatus constructor.
|
||||||
*
|
*
|
||||||
|
@ -64,17 +80,20 @@ class PayUponInvoiceProductStatus {
|
||||||
* @param PartnersEndpoint $partners_endpoint The Partner Endpoint.
|
* @param PartnersEndpoint $partners_endpoint The Partner Endpoint.
|
||||||
* @param Cache $cache The cache.
|
* @param Cache $cache The cache.
|
||||||
* @param State $onboarding_state The onboarding state.
|
* @param State $onboarding_state The onboarding state.
|
||||||
|
* @param FailureRegistry $api_failure_registry The API failure registry.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
Settings $settings,
|
Settings $settings,
|
||||||
PartnersEndpoint $partners_endpoint,
|
PartnersEndpoint $partners_endpoint,
|
||||||
Cache $cache,
|
Cache $cache,
|
||||||
State $onboarding_state
|
State $onboarding_state,
|
||||||
|
FailureRegistry $api_failure_registry
|
||||||
) {
|
) {
|
||||||
$this->settings = $settings;
|
$this->settings = $settings;
|
||||||
$this->partners_endpoint = $partners_endpoint;
|
$this->partners_endpoint = $partners_endpoint;
|
||||||
$this->cache = $cache;
|
$this->cache = $cache;
|
||||||
$this->onboarding_state = $onboarding_state;
|
$this->onboarding_state = $onboarding_state;
|
||||||
|
$this->api_failure_registry = $api_failure_registry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -99,9 +118,17 @@ class PayUponInvoiceProductStatus {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check API failure registry to prevent multiple failed API requests.
|
||||||
|
if ( $this->api_failure_registry->has_failure_in_timeframe( FailureRegistry::SELLER_STATUS_KEY, HOUR_IN_SECONDS ) ) {
|
||||||
|
$this->has_request_failure = true;
|
||||||
|
$this->current_status_cache = false;
|
||||||
|
return $this->current_status_cache;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$seller_status = $this->partners_endpoint->seller_status();
|
$seller_status = $this->partners_endpoint->seller_status();
|
||||||
} catch ( Throwable $error ) {
|
} catch ( Throwable $error ) {
|
||||||
|
$this->has_request_failure = true;
|
||||||
$this->current_status_cache = false;
|
$this->current_status_cache = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -136,4 +163,14 @@ class PayUponInvoiceProductStatus {
|
||||||
$this->current_status_cache = false;
|
$this->current_status_cache = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns if there was a request failure.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function has_request_failure(): bool {
|
||||||
|
return $this->has_request_failure;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -456,7 +456,7 @@ return function ( ContainerInterface $container, array $fields ): array {
|
||||||
'description' => __( 'If you use your PayPal account with more than one installation, please use a distinct prefix to separate those installations. Please use only English letters and "-", "_" characters.', 'woocommerce-paypal-payments' ),
|
'description' => __( 'If you use your PayPal account with more than one installation, please use a distinct prefix to separate those installations. Please use only English letters and "-", "_" characters.', 'woocommerce-paypal-payments' ),
|
||||||
'maxlength' => 15,
|
'maxlength' => 15,
|
||||||
'custom_attributes' => array(
|
'custom_attributes' => array(
|
||||||
'pattern' => '[a-zA-Z_-]+',
|
'pattern' => '[a-zA-Z_\\-]+',
|
||||||
),
|
),
|
||||||
'default' => ( static function (): string {
|
'default' => ( static function (): string {
|
||||||
$site_url = get_site_url( get_current_blog_id() );
|
$site_url = get_site_url( get_current_blog_id() );
|
||||||
|
|
|
@ -623,6 +623,254 @@ return function ( ContainerInterface $container, array $fields ): array {
|
||||||
'requirements' => array( 'messages' ),
|
'requirements' => array( 'messages' ),
|
||||||
'gateway' => Settings::PAY_LATER_TAB_ID,
|
'gateway' => Settings::PAY_LATER_TAB_ID,
|
||||||
),
|
),
|
||||||
|
|
||||||
|
// Shop.
|
||||||
|
'pay_later_shop_messaging_heading' => array(
|
||||||
|
'heading' => __( 'Pay Later Messaging on the Shop page', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'ppcp-heading',
|
||||||
|
'screens' => array( State::STATE_ONBOARDED ),
|
||||||
|
'requirements' => array(),
|
||||||
|
'gateway' => Settings::PAY_LATER_TAB_ID,
|
||||||
|
),
|
||||||
|
'pay_later_shop_message_layout' => array(
|
||||||
|
'title' => __( 'Shop Messaging Layout', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'select',
|
||||||
|
'class' => array(),
|
||||||
|
'input_class' => array( 'wc-enhanced-select' ),
|
||||||
|
'default' => 'text',
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'The layout of the message.', 'woocommerce-paypal-payments' ),
|
||||||
|
'options' => array(
|
||||||
|
'text' => __( 'Text', 'woocommerce-paypal-payments' ),
|
||||||
|
'flex' => __( 'Banner', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'screens' => array( State::STATE_ONBOARDED ),
|
||||||
|
'requirements' => array( 'messages' ),
|
||||||
|
'gateway' => Settings::PAY_LATER_TAB_ID,
|
||||||
|
),
|
||||||
|
'pay_later_shop_message_logo' => array(
|
||||||
|
'title' => __( 'Shop Messaging Logo', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'select',
|
||||||
|
'class' => array(),
|
||||||
|
'input_class' => array( 'wc-enhanced-select' ),
|
||||||
|
'default' => 'inline',
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'What logo the text message contains. Only applicable, when the layout style Text is used.', 'woocommerce-paypal-payments' ),
|
||||||
|
'options' => array(
|
||||||
|
'primary' => __( 'Primary', 'woocommerce-paypal-payments' ),
|
||||||
|
'alternative' => __( 'Alternative', 'woocommerce-paypal-payments' ),
|
||||||
|
'inline' => __( 'Inline', 'woocommerce-paypal-payments' ),
|
||||||
|
'none' => __( 'None', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'screens' => array( State::STATE_ONBOARDED ),
|
||||||
|
'requirements' => array( 'messages' ),
|
||||||
|
'gateway' => Settings::PAY_LATER_TAB_ID,
|
||||||
|
),
|
||||||
|
'pay_later_shop_message_position' => array(
|
||||||
|
'title' => __( 'Shop Messaging Logo Position', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'select',
|
||||||
|
'class' => array(),
|
||||||
|
'input_class' => array( 'wc-enhanced-select' ),
|
||||||
|
'default' => 'left',
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'The position of the logo. Only applicable, when the layout style Text is used.', 'woocommerce-paypal-payments' ),
|
||||||
|
'options' => array(
|
||||||
|
'left' => __( 'Left', 'woocommerce-paypal-payments' ),
|
||||||
|
'right' => __( 'Right', 'woocommerce-paypal-payments' ),
|
||||||
|
'top' => __( 'Top', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'screens' => array( State::STATE_ONBOARDED ),
|
||||||
|
'requirements' => array( 'messages' ),
|
||||||
|
'gateway' => Settings::PAY_LATER_TAB_ID,
|
||||||
|
),
|
||||||
|
'pay_later_shop_message_color' => array(
|
||||||
|
'title' => __( 'Shop Messaging Text Color', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'select',
|
||||||
|
'class' => array(),
|
||||||
|
'input_class' => array( 'wc-enhanced-select' ),
|
||||||
|
'default' => 'black',
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'The color of the text. Only applicable, when the layout style Text is used.', 'woocommerce-paypal-payments' ),
|
||||||
|
'options' => array(
|
||||||
|
'black' => __( 'Black', 'woocommerce-paypal-payments' ),
|
||||||
|
'white' => __( 'White', 'woocommerce-paypal-payments' ),
|
||||||
|
'monochrome' => __( 'Monochrome', 'woocommerce-paypal-payments' ),
|
||||||
|
'grayscale' => __( 'Grayscale', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'screens' => array( State::STATE_ONBOARDED ),
|
||||||
|
'requirements' => array( 'messages' ),
|
||||||
|
'gateway' => Settings::PAY_LATER_TAB_ID,
|
||||||
|
),
|
||||||
|
'pay_later_shop_message_flex_color' => array(
|
||||||
|
'title' => __( 'Shop Messaging Color', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'select',
|
||||||
|
'class' => array(),
|
||||||
|
'input_class' => array( 'wc-enhanced-select' ),
|
||||||
|
'default' => $default_messaging_flex_color,
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'The color of the text. Only applicable, when the layout style Banner is used.', 'woocommerce-paypal-payments' ),
|
||||||
|
'options' => array(
|
||||||
|
'blue' => __( 'Blue', 'woocommerce-paypal-payments' ),
|
||||||
|
'black' => __( 'Black', 'woocommerce-paypal-payments' ),
|
||||||
|
'white' => __( 'White', 'woocommerce-paypal-payments' ),
|
||||||
|
'white-no-border' => __( 'White no border', 'woocommerce-paypal-payments' ),
|
||||||
|
'gray' => __( 'Gray', 'woocommerce-paypal-payments' ),
|
||||||
|
'monochrome' => __( 'Monochrome', 'woocommerce-paypal-payments' ),
|
||||||
|
'grayscale' => __( 'Grayscale', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'screens' => array( State::STATE_ONBOARDED ),
|
||||||
|
'requirements' => array( 'messages' ),
|
||||||
|
'gateway' => Settings::PAY_LATER_TAB_ID,
|
||||||
|
),
|
||||||
|
'pay_later_shop_message_flex_ratio' => array(
|
||||||
|
'title' => __( 'Shop Messaging Ratio', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'select',
|
||||||
|
'class' => array(),
|
||||||
|
'input_class' => array( 'wc-enhanced-select' ),
|
||||||
|
'default' => '8x1',
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'The width/height ratio of the banner. Only applicable, when the layout style Banner is used.', 'woocommerce-paypal-payments' ),
|
||||||
|
'options' => array(
|
||||||
|
'1x1' => __( '1x1', 'woocommerce-paypal-payments' ),
|
||||||
|
'1x4' => __( '1x4', 'woocommerce-paypal-payments' ),
|
||||||
|
'8x1' => __( '8x1', 'woocommerce-paypal-payments' ),
|
||||||
|
'20x1' => __( '20x1', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'screens' => array( State::STATE_ONBOARDED ),
|
||||||
|
'requirements' => array( 'messages' ),
|
||||||
|
'gateway' => Settings::PAY_LATER_TAB_ID,
|
||||||
|
),
|
||||||
|
'pay_later_shop_message_preview' => array(
|
||||||
|
'type' => 'ppcp-text',
|
||||||
|
'text' => $render_preview_element( 'ppcpShopMessagePreview', 'message', $messaging_message ),
|
||||||
|
'screens' => array( State::STATE_ONBOARDED ),
|
||||||
|
'requirements' => array( 'messages' ),
|
||||||
|
'gateway' => Settings::PAY_LATER_TAB_ID,
|
||||||
|
),
|
||||||
|
|
||||||
|
// Home.
|
||||||
|
'pay_later_home_messaging_heading' => array(
|
||||||
|
'heading' => __( 'Pay Later Messaging on the Home page', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'ppcp-heading',
|
||||||
|
'screens' => array( State::STATE_ONBOARDED ),
|
||||||
|
'requirements' => array(),
|
||||||
|
'gateway' => Settings::PAY_LATER_TAB_ID,
|
||||||
|
),
|
||||||
|
'pay_later_home_message_layout' => array(
|
||||||
|
'title' => __( 'Home Messaging Layout', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'select',
|
||||||
|
'class' => array(),
|
||||||
|
'input_class' => array( 'wc-enhanced-select' ),
|
||||||
|
'default' => 'text',
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'The layout of the message.', 'woocommerce-paypal-payments' ),
|
||||||
|
'options' => array(
|
||||||
|
'text' => __( 'Text', 'woocommerce-paypal-payments' ),
|
||||||
|
'flex' => __( 'Banner', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'screens' => array( State::STATE_ONBOARDED ),
|
||||||
|
'requirements' => array( 'messages' ),
|
||||||
|
'gateway' => Settings::PAY_LATER_TAB_ID,
|
||||||
|
),
|
||||||
|
'pay_later_home_message_logo' => array(
|
||||||
|
'title' => __( 'Home Messaging Logo', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'select',
|
||||||
|
'class' => array(),
|
||||||
|
'input_class' => array( 'wc-enhanced-select' ),
|
||||||
|
'default' => 'inline',
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'What logo the text message contains. Only applicable, when the layout style Text is used.', 'woocommerce-paypal-payments' ),
|
||||||
|
'options' => array(
|
||||||
|
'primary' => __( 'Primary', 'woocommerce-paypal-payments' ),
|
||||||
|
'alternative' => __( 'Alternative', 'woocommerce-paypal-payments' ),
|
||||||
|
'inline' => __( 'Inline', 'woocommerce-paypal-payments' ),
|
||||||
|
'none' => __( 'None', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'screens' => array( State::STATE_ONBOARDED ),
|
||||||
|
'requirements' => array( 'messages' ),
|
||||||
|
'gateway' => Settings::PAY_LATER_TAB_ID,
|
||||||
|
),
|
||||||
|
'pay_later_home_message_position' => array(
|
||||||
|
'title' => __( 'Home Messaging Logo Position', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'select',
|
||||||
|
'class' => array(),
|
||||||
|
'input_class' => array( 'wc-enhanced-select' ),
|
||||||
|
'default' => 'left',
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'The position of the logo. Only applicable, when the layout style Text is used.', 'woocommerce-paypal-payments' ),
|
||||||
|
'options' => array(
|
||||||
|
'left' => __( 'Left', 'woocommerce-paypal-payments' ),
|
||||||
|
'right' => __( 'Right', 'woocommerce-paypal-payments' ),
|
||||||
|
'top' => __( 'Top', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'screens' => array( State::STATE_ONBOARDED ),
|
||||||
|
'requirements' => array( 'messages' ),
|
||||||
|
'gateway' => Settings::PAY_LATER_TAB_ID,
|
||||||
|
),
|
||||||
|
'pay_later_home_message_color' => array(
|
||||||
|
'title' => __( 'Home Messaging Text Color', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'select',
|
||||||
|
'class' => array(),
|
||||||
|
'input_class' => array( 'wc-enhanced-select' ),
|
||||||
|
'default' => 'black',
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'The color of the text. Only applicable, when the layout style Text is used.', 'woocommerce-paypal-payments' ),
|
||||||
|
'options' => array(
|
||||||
|
'black' => __( 'Black', 'woocommerce-paypal-payments' ),
|
||||||
|
'white' => __( 'White', 'woocommerce-paypal-payments' ),
|
||||||
|
'monochrome' => __( 'Monochrome', 'woocommerce-paypal-payments' ),
|
||||||
|
'grayscale' => __( 'Grayscale', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'screens' => array( State::STATE_ONBOARDED ),
|
||||||
|
'requirements' => array( 'messages' ),
|
||||||
|
'gateway' => Settings::PAY_LATER_TAB_ID,
|
||||||
|
),
|
||||||
|
'pay_later_home_message_flex_color' => array(
|
||||||
|
'title' => __( 'Home Messaging Color', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'select',
|
||||||
|
'class' => array(),
|
||||||
|
'input_class' => array( 'wc-enhanced-select' ),
|
||||||
|
'default' => $default_messaging_flex_color,
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'The color of the text. Only applicable, when the layout style Banner is used.', 'woocommerce-paypal-payments' ),
|
||||||
|
'options' => array(
|
||||||
|
'blue' => __( 'Blue', 'woocommerce-paypal-payments' ),
|
||||||
|
'black' => __( 'Black', 'woocommerce-paypal-payments' ),
|
||||||
|
'white' => __( 'White', 'woocommerce-paypal-payments' ),
|
||||||
|
'white-no-border' => __( 'White no border', 'woocommerce-paypal-payments' ),
|
||||||
|
'gray' => __( 'Gray', 'woocommerce-paypal-payments' ),
|
||||||
|
'monochrome' => __( 'Monochrome', 'woocommerce-paypal-payments' ),
|
||||||
|
'grayscale' => __( 'Grayscale', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'screens' => array( State::STATE_ONBOARDED ),
|
||||||
|
'requirements' => array( 'messages' ),
|
||||||
|
'gateway' => Settings::PAY_LATER_TAB_ID,
|
||||||
|
),
|
||||||
|
'pay_later_home_message_flex_ratio' => array(
|
||||||
|
'title' => __( 'Home Messaging Ratio', 'woocommerce-paypal-payments' ),
|
||||||
|
'type' => 'select',
|
||||||
|
'class' => array(),
|
||||||
|
'input_class' => array( 'wc-enhanced-select' ),
|
||||||
|
'default' => '8x1',
|
||||||
|
'desc_tip' => true,
|
||||||
|
'description' => __( 'The width/height ratio of the banner. Only applicable, when the layout style Banner is used.', 'woocommerce-paypal-payments' ),
|
||||||
|
'options' => array(
|
||||||
|
'1x1' => __( '1x1', 'woocommerce-paypal-payments' ),
|
||||||
|
'1x4' => __( '1x4', 'woocommerce-paypal-payments' ),
|
||||||
|
'8x1' => __( '8x1', 'woocommerce-paypal-payments' ),
|
||||||
|
'20x1' => __( '20x1', 'woocommerce-paypal-payments' ),
|
||||||
|
),
|
||||||
|
'screens' => array( State::STATE_ONBOARDED ),
|
||||||
|
'requirements' => array( 'messages' ),
|
||||||
|
'gateway' => Settings::PAY_LATER_TAB_ID,
|
||||||
|
),
|
||||||
|
'pay_later_home_message_preview' => array(
|
||||||
|
'type' => 'ppcp-text',
|
||||||
|
'text' => $render_preview_element( 'ppcpHomeMessagePreview', 'message', $messaging_message ),
|
||||||
|
'screens' => array( State::STATE_ONBOARDED ),
|
||||||
|
'requirements' => array( 'messages' ),
|
||||||
|
'gateway' => Settings::PAY_LATER_TAB_ID,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
return array_merge( $fields, $pay_later_fields );
|
return array_merge( $fields, $pay_later_fields );
|
||||||
|
|
|
@ -264,6 +264,11 @@
|
||||||
<code>DAY_IN_SECONDS</code>
|
<code>DAY_IN_SECONDS</code>
|
||||||
</UndefinedConstant>
|
</UndefinedConstant>
|
||||||
</file>
|
</file>
|
||||||
|
<file src="modules/ppcp-api-client/src/Helper/FailureRegistry.php">
|
||||||
|
<UndefinedConstant occurrences="1">
|
||||||
|
<code>DAY_IN_SECONDS</code>
|
||||||
|
</UndefinedConstant>
|
||||||
|
</file>
|
||||||
<file src="modules/ppcp-button/services.php">
|
<file src="modules/ppcp-button/services.php">
|
||||||
<PossiblyFalseArgument occurrences="1">
|
<PossiblyFalseArgument occurrences="1">
|
||||||
<code>realpath( __FILE__ )</code>
|
<code>realpath( __FILE__ )</code>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue