mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-06 18:16:38 +08:00
Merge branch 'trunk' into PCP-2722-add-block-checkout-compatibility-to-advanced-card-processing
This commit is contained in:
commit
3d924e0a04
108 changed files with 10904 additions and 369 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -4,9 +4,8 @@
|
|||
node_modules
|
||||
.phpunit.result.cache
|
||||
yarn-error.log
|
||||
modules/ppcp-button/assets/*
|
||||
modules/ppcp-wc-gateway/assets/js
|
||||
modules/ppcp-wc-gateway/assets/css
|
||||
modules/*/vendor/*
|
||||
modules/*/assets/*
|
||||
*.zip
|
||||
.env
|
||||
.env.e2e
|
||||
|
|
|
@ -55,3 +55,13 @@ function as_unschedule_action($hook, $args = array(), $group = '') {}
|
|||
* @return int The action ID.
|
||||
*/
|
||||
function as_schedule_single_action( $timestamp, $hook, $args = array(), $group = '', $unique = false ) {}
|
||||
|
||||
/**
|
||||
* HTML API: WP_HTML_Tag_Processor class
|
||||
*/
|
||||
class WP_HTML_Tag_Processor {
|
||||
public function __construct( $html ) {}
|
||||
public function next_tag( $query = null ) {}
|
||||
public function set_attribute( $name, $value ) {}
|
||||
public function get_updated_html() {}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,20 @@
|
|||
*** Changelog ***
|
||||
|
||||
= 2.7.0 - 2024-04-30 =
|
||||
* Fix - Zero sum subscriptions cause CANNOT_BE_ZERO_OR_NEGATIVE when using Vault v3 #2152
|
||||
* Fix - Incorrect Pricing Issue with Variable Subscriptions in PayPal Subscriptions Mode #2156
|
||||
* Fix - Wrong return_url in multisite setup when using subdomains #2157
|
||||
* Fix - Fix the fundingSource is not defined error on Block Checkout #2185
|
||||
* Enhancement - Add the data-page-type attribute for JS SDK #2161
|
||||
* Enhancement - Save Card Last Digits in order meta for Advanced Card Payments #2149
|
||||
* Enhancement - Refactor the Pay Later Messaging block and add dedicated Cart/Checkout blocks #2153
|
||||
* Enhancement - "Next Payment" status not updated when using PayPal Subscriptions #2091
|
||||
* Enhancement - Optimize default settings for new store configurations #2158
|
||||
* Enhancement - Improve tooltip information for tagline #2154
|
||||
* Enhancement - Improve error message on certain exceptions #1354
|
||||
* Enhancement - Cart Pay Later block: Change the default insert position #2179
|
||||
* Enhancement - Messages Bootstrap: Add a render retry functionality #2181
|
||||
|
||||
= 2.6.1 - 2024-04-09 =
|
||||
* Fix - Payment tokens fixes and adjustments #2106
|
||||
* Fix - Pay upon Invoice: Add input validation to Experience Context fields #2092
|
||||
|
|
12
modules.php
12
modules.php
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
use WooCommerce\PayPalCommerce\PayLaterBlock\PayLaterBlockModule;
|
||||
use WooCommerce\PayPalCommerce\PayLaterWCBlocks\PayLaterWCBlocksModule;
|
||||
use WooCommerce\PayPalCommerce\PayLaterConfigurator\PayLaterConfiguratorModule;
|
||||
use WooCommerce\PayPalCommerce\PluginModule;
|
||||
|
||||
|
@ -72,9 +73,20 @@ return function ( string $root_dir ): iterable {
|
|||
$modules[] = ( require "$modules_dir/ppcp-paylater-block/module.php" )();
|
||||
}
|
||||
|
||||
if ( PayLaterWCBlocksModule::is_module_loading_required() ) {
|
||||
$modules[] = ( require "$modules_dir/ppcp-paylater-wc-blocks/module.php" )();
|
||||
}
|
||||
|
||||
if ( PayLaterConfiguratorModule::is_enabled() ) {
|
||||
$modules[] = ( require "$modules_dir/ppcp-paylater-configurator/module.php" )();
|
||||
}
|
||||
|
||||
if ( apply_filters(
|
||||
'woocommerce.feature-flags.woocommerce_paypal_payments.axo_enabled',
|
||||
getenv( 'PCP_AXO_ENABLED' ) === '1'
|
||||
) ) {
|
||||
$modules[] = ( require "$modules_dir/ppcp-axo/module.php" )();
|
||||
}
|
||||
|
||||
return $modules;
|
||||
};
|
||||
|
|
|
@ -9,6 +9,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace WooCommerce\PayPalCommerce\ApiClient;
|
||||
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\SdkClientToken;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\UserIdToken;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentMethodTokensEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentTokensEndpoint;
|
||||
|
@ -1633,4 +1634,11 @@ return array(
|
|||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
'api.sdk-client-token' => static function( ContainerInterface $container ): SdkClientToken {
|
||||
return new SdkClientToken(
|
||||
$container->get( 'api.host' ),
|
||||
$container->get( 'api.bearer' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
109
modules/ppcp-api-client/src/Authentication/SdkClientToken.php
Normal file
109
modules/ppcp-api-client/src/Authentication/SdkClientToken.php
Normal file
|
@ -0,0 +1,109 @@
|
|||
<?php
|
||||
/**
|
||||
* Generates user ID token for payer.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\ApiClient\Authentication
|
||||
*/
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\ApiClient\Authentication;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\RequestTrait;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WP_Error;
|
||||
|
||||
/**
|
||||
* Class SdkClientToken
|
||||
*/
|
||||
class SdkClientToken {
|
||||
|
||||
use RequestTrait;
|
||||
|
||||
/**
|
||||
* The host.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $host;
|
||||
|
||||
/**
|
||||
* The bearer.
|
||||
*
|
||||
* @var Bearer
|
||||
*/
|
||||
private $bearer;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* SdkClientToken constructor.
|
||||
*
|
||||
* @param string $host The host.
|
||||
* @param Bearer $bearer The bearer.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
public function __construct(
|
||||
string $host,
|
||||
Bearer $bearer,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
$this->host = $host;
|
||||
$this->bearer = $bearer;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `sdk_client_token` which uniquely identifies the payer.
|
||||
*
|
||||
* @param string $target_customer_id Vaulted customer id.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws PayPalApiException If the request fails.
|
||||
* @throws RuntimeException If something unexpected happens.
|
||||
*/
|
||||
public function sdk_client_token( string $target_customer_id = '' ): string {
|
||||
$bearer = $this->bearer->bearer();
|
||||
|
||||
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
$domain = wp_unslash( $_SERVER['HTTP_HOST'] ?? '' );
|
||||
|
||||
$url = trailingslashit( $this->host ) . 'v1/oauth2/token?grant_type=client_credentials&response_type=client_token&intent=sdk_init&domains[]=' . $domain;
|
||||
|
||||
if ( $target_customer_id ) {
|
||||
$url = add_query_arg(
|
||||
array(
|
||||
'target_customer_id' => $target_customer_id,
|
||||
),
|
||||
$url
|
||||
);
|
||||
}
|
||||
|
||||
$args = array(
|
||||
'method' => 'POST',
|
||||
'headers' => array(
|
||||
'Authorization' => 'Bearer ' . $bearer->token(),
|
||||
'Content-Type' => 'application/x-www-form-urlencoded',
|
||||
),
|
||||
);
|
||||
|
||||
$response = $this->request( $url, $args );
|
||||
if ( $response instanceof WP_Error ) {
|
||||
throw new RuntimeException( $response->get_error_message() );
|
||||
}
|
||||
|
||||
$json = json_decode( $response['body'] );
|
||||
$status_code = (int) wp_remote_retrieve_response_code( $response );
|
||||
if ( 200 !== $status_code ) {
|
||||
throw new PayPalApiException( $json, $status_code );
|
||||
}
|
||||
|
||||
return $json->access_token;
|
||||
}
|
||||
}
|
|
@ -9,6 +9,8 @@ declare(strict_types=1);
|
|||
|
||||
namespace WooCommerce\PayPalCommerce\ApiClient\Exception;
|
||||
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* Class PayPalApiException
|
||||
*/
|
||||
|
@ -17,7 +19,7 @@ class PayPalApiException extends RuntimeException {
|
|||
/**
|
||||
* The JSON response object of PayPal.
|
||||
*
|
||||
* @var \stdClass
|
||||
* @var stdClass
|
||||
*/
|
||||
private $response;
|
||||
|
||||
|
@ -31,10 +33,10 @@ class PayPalApiException extends RuntimeException {
|
|||
/**
|
||||
* PayPalApiException constructor.
|
||||
*
|
||||
* @param \stdClass|null $response The JSON object.
|
||||
* @param int $status_code The HTTP status code.
|
||||
* @param stdClass|null $response The JSON object.
|
||||
* @param int $status_code The HTTP status code.
|
||||
*/
|
||||
public function __construct( \stdClass $response = null, int $status_code = 0 ) {
|
||||
public function __construct( stdClass $response = null, int $status_code = 0 ) {
|
||||
if ( is_null( $response ) ) {
|
||||
$response = new \stdClass();
|
||||
}
|
||||
|
@ -65,7 +67,7 @@ class PayPalApiException extends RuntimeException {
|
|||
*/
|
||||
$this->response = $response;
|
||||
$this->status_code = $status_code;
|
||||
$message = $response->message;
|
||||
$message = $this->get_customer_friendly_message( $response );
|
||||
if ( $response->name ) {
|
||||
$message = '[' . $response->name . '] ' . $message;
|
||||
}
|
||||
|
@ -141,4 +143,40 @@ class PayPalApiException extends RuntimeException {
|
|||
|
||||
return $details;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a friendly message if the error detail is known.
|
||||
*
|
||||
* @param stdClass $json The response.
|
||||
* @return string
|
||||
*/
|
||||
public function get_customer_friendly_message( stdClass $json ): string {
|
||||
if ( empty( $json->details ) ) {
|
||||
return $json->message;
|
||||
}
|
||||
$improved_keys_messages = array(
|
||||
'PAYMENT_DENIED' => __( 'PayPal rejected the payment. Please reach out to the PayPal support for more information.', 'woocommerce-paypal-payments' ),
|
||||
'TRANSACTION_REFUSED' => __( 'The transaction has been refused by the payment processor. Please reach out to the PayPal support for more information.', 'woocommerce-paypal-payments' ),
|
||||
'DUPLICATE_INVOICE_ID' => __( 'The transaction has been refused because the Invoice ID already exists. Please create a new order or reach out to the store owner.', 'woocommerce-paypal-payments' ),
|
||||
'PAYER_CANNOT_PAY' => __( 'There was a problem processing this transaction. Please reach out to the store owner.', 'woocommerce-paypal-payments' ),
|
||||
'PAYEE_ACCOUNT_RESTRICTED' => __( 'There was a problem processing this transaction. Please reach out to the store owner.', 'woocommerce-paypal-payments' ),
|
||||
'AGREEMENT_ALREADY_CANCELLED' => __( 'The requested agreement is already canceled. Please reach out to the PayPal support for more information.', 'woocommerce-paypal-payments' ),
|
||||
);
|
||||
$improved_errors = array_filter(
|
||||
array_keys( $improved_keys_messages ),
|
||||
function ( $key ) use ( $json ): bool {
|
||||
foreach ( $json->details as $detail ) {
|
||||
if ( isset( $detail->issue ) && $detail->issue === $key ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
if ( $improved_errors ) {
|
||||
$improved_errors = array_values( $improved_errors );
|
||||
return $improved_keys_messages[ $improved_errors[0] ];
|
||||
}
|
||||
return $json->message;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ class ApplicationContextRepository {
|
|||
$payment_preference = $this->settings->has( 'payee_preferred' ) && $this->settings->get( 'payee_preferred' ) ?
|
||||
ApplicationContext::PAYMENT_METHOD_IMMEDIATE_PAYMENT_REQUIRED : ApplicationContext::PAYMENT_METHOD_UNRESTRICTED;
|
||||
$context = new ApplicationContext(
|
||||
network_home_url( \WC_AJAX::get_endpoint( ReturnUrlEndpoint::ENDPOINT ) ),
|
||||
home_url( \WC_AJAX::get_endpoint( ReturnUrlEndpoint::ENDPOINT ) ),
|
||||
(string) wc_get_checkout_url(),
|
||||
(string) $brand_name,
|
||||
$locale,
|
||||
|
|
BIN
modules/ppcp-applepay/assets/images/applepay.png
Normal file
BIN
modules/ppcp-applepay/assets/images/applepay.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
|
@ -68,6 +68,8 @@ return array(
|
|||
$device_eligibility_notes = __( 'The Apple Pay button will be visible both in previews and below the PayPal buttons in the shop.', 'woocommerce-paypal-payments' );
|
||||
}
|
||||
|
||||
$module_url = $container->get( 'applepay.url' );
|
||||
|
||||
// Connection tab fields.
|
||||
$fields = $insert_after(
|
||||
$fields,
|
||||
|
@ -91,10 +93,15 @@ return array(
|
|||
$connection_link = '<a href="' . $connection_url . '" style="pointer-events: auto">';
|
||||
return $insert_after(
|
||||
$fields,
|
||||
'allow_card_button_gateway',
|
||||
'digital_wallet_heading',
|
||||
array(
|
||||
'applepay_button_enabled' => array(
|
||||
'title' => __( 'Apple Pay Button', 'woocommerce-paypal-payments' ),
|
||||
'title_html' => sprintf(
|
||||
'<img src="%sassets/images/applepay.png" alt="%s" style="max-width: 150px; max-height: 45px;" />',
|
||||
$module_url,
|
||||
__( 'Apple Pay', 'woocommerce-paypal-payments' )
|
||||
),
|
||||
'type' => 'checkbox',
|
||||
'class' => array( 'ppcp-grayed-out-text' ),
|
||||
'input_class' => array( 'ppcp-disabled-checkbox' ),
|
||||
|
@ -109,7 +116,7 @@ return array(
|
|||
. '</p>',
|
||||
'default' => 'yes',
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'gateway' => 'paypal',
|
||||
'gateway' => 'dcc',
|
||||
'requirements' => array(),
|
||||
'custom_attributes' => array(
|
||||
'data-ppcp-display' => wp_json_encode(
|
||||
|
@ -122,6 +129,7 @@ return array(
|
|||
)
|
||||
),
|
||||
),
|
||||
'classes' => array( 'ppcp-valign-label-middle', 'ppcp-align-label-center' ),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
@ -129,10 +137,25 @@ return array(
|
|||
|
||||
return $insert_after(
|
||||
$fields,
|
||||
'allow_card_button_gateway',
|
||||
'digital_wallet_heading',
|
||||
array(
|
||||
'spacer' => array(
|
||||
'title' => '',
|
||||
'type' => 'ppcp-text',
|
||||
'text' => '',
|
||||
'class' => array(),
|
||||
'classes' => array( 'ppcp-active-spacer' ),
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'gateway' => 'dcc',
|
||||
'requirements' => array(),
|
||||
),
|
||||
'applepay_button_enabled' => array(
|
||||
'title' => __( 'Apple Pay Button', 'woocommerce-paypal-payments' ),
|
||||
'title_html' => sprintf(
|
||||
'<img src="%sassets/images/applepay.png" alt="%s" style="max-width: 150px; max-height: 45px;" />',
|
||||
$module_url,
|
||||
__( 'Apple Pay', 'woocommerce-paypal-payments' )
|
||||
),
|
||||
'type' => 'checkbox',
|
||||
'label' => __( 'Enable Apple Pay button', 'woocommerce-paypal-payments' )
|
||||
. '<p class="description">'
|
||||
|
@ -145,7 +168,7 @@ return array(
|
|||
. '</p>',
|
||||
'default' => 'yes',
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'gateway' => 'paypal',
|
||||
'gateway' => 'dcc',
|
||||
'requirements' => array(),
|
||||
'custom_attributes' => array(
|
||||
'data-ppcp-display' => wp_json_encode(
|
||||
|
@ -160,10 +183,12 @@ return array(
|
|||
->action_visible( 'applepay_button_type' )
|
||||
->action_visible( 'applepay_button_language' )
|
||||
->action_visible( 'applepay_checkout_data_mode' )
|
||||
->action_class( 'applepay_button_enabled', 'active' )
|
||||
->to_array(),
|
||||
)
|
||||
),
|
||||
),
|
||||
'classes' => array( 'ppcp-valign-label-middle', 'ppcp-align-label-center' ),
|
||||
),
|
||||
'applepay_button_domain_registration' => array(
|
||||
'title' => __( 'Domain Registration', 'woocommerce-paypal-payments' ),
|
||||
|
@ -183,7 +208,7 @@ return array(
|
|||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'class' => array(),
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'gateway' => 'paypal',
|
||||
'gateway' => 'dcc',
|
||||
'requirements' => array(),
|
||||
),
|
||||
'applepay_button_domain_validation' => array(
|
||||
|
@ -206,7 +231,7 @@ return array(
|
|||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'class' => array(),
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'gateway' => 'paypal',
|
||||
'gateway' => 'dcc',
|
||||
'requirements' => array(),
|
||||
),
|
||||
'applepay_button_device_eligibility' => array(
|
||||
|
@ -224,7 +249,7 @@ return array(
|
|||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'class' => array(),
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'gateway' => 'paypal',
|
||||
'gateway' => 'dcc',
|
||||
'requirements' => array(),
|
||||
),
|
||||
'applepay_button_type' => array(
|
||||
|
@ -241,7 +266,7 @@ return array(
|
|||
'default' => 'pay',
|
||||
'options' => PropertiesDictionary::button_types(),
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'gateway' => 'paypal',
|
||||
'gateway' => 'dcc',
|
||||
'requirements' => array(),
|
||||
),
|
||||
'applepay_button_color' => array(
|
||||
|
@ -259,7 +284,7 @@ return array(
|
|||
'default' => 'black',
|
||||
'options' => PropertiesDictionary::button_colors(),
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'gateway' => 'paypal',
|
||||
'gateway' => 'dcc',
|
||||
'requirements' => array(),
|
||||
),
|
||||
'applepay_button_language' => array(
|
||||
|
@ -276,7 +301,7 @@ return array(
|
|||
'default' => 'en',
|
||||
'options' => PropertiesDictionary::button_languages(),
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'gateway' => 'paypal',
|
||||
'gateway' => 'dcc',
|
||||
'requirements' => array(),
|
||||
),
|
||||
'applepay_checkout_data_mode' => array(
|
||||
|
@ -290,7 +315,7 @@ return array(
|
|||
'default' => PropertiesDictionary::BILLING_DATA_MODE_DEFAULT,
|
||||
'options' => PropertiesDictionary::billing_data_modes(),
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'gateway' => 'paypal',
|
||||
'gateway' => 'dcc',
|
||||
'requirements' => array(),
|
||||
),
|
||||
)
|
||||
|
|
|
@ -39,7 +39,7 @@ class ApplepayButton {
|
|||
|
||||
this.log = function() {
|
||||
if ( this.buttonConfig.is_debug ) {
|
||||
console.log('[ApplePayButton]', ...arguments);
|
||||
//console.log('[ApplePayButton]', ...arguments);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
14
modules/ppcp-axo/.babelrc
Normal file
14
modules/ppcp-axo/.babelrc
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"useBuiltIns": "usage",
|
||||
"corejs": "3.25.0"
|
||||
}
|
||||
],
|
||||
[
|
||||
"@babel/preset-react"
|
||||
]
|
||||
]
|
||||
}
|
3
modules/ppcp-axo/.gitignore
vendored
Normal file
3
modules/ppcp-axo/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
node_modules
|
||||
assets/js
|
||||
assets/css
|
BIN
modules/ppcp-axo/assets/images/fastlane.png
Normal file
BIN
modules/ppcp-axo/assets/images/fastlane.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
17
modules/ppcp-axo/composer.json
Normal file
17
modules/ppcp-axo/composer.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "woocommerce/ppcp-axo",
|
||||
"type": "dhii-mod",
|
||||
"description": "Axo module for PPCP",
|
||||
"license": "GPL-2.0",
|
||||
"require": {
|
||||
"php": "^7.2 | ^8.0",
|
||||
"dhii/module-interface": "^0.3.0-alpha1"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"WooCommerce\\PayPalCommerce\\Axo\\": "src"
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true
|
||||
}
|
386
modules/ppcp-axo/extensions.php
Normal file
386
modules/ppcp-axo/extensions.php
Normal file
|
@ -0,0 +1,386 @@
|
|||
<?php
|
||||
/**
|
||||
* The Axo module extensions.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Axo
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Axo;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Axo\Helper\PropertiesDictionary;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Helper\DisplayManager;
|
||||
|
||||
return array(
|
||||
|
||||
'wcgateway.settings.fields' => function ( ContainerInterface $container, array $fields ): array {
|
||||
|
||||
$insert_after = function( array $array, string $key, array $new ): array {
|
||||
$keys = array_keys( $array );
|
||||
$index = array_search( $key, $keys, true );
|
||||
$pos = false === $index ? count( $array ) : $index + 1;
|
||||
|
||||
return array_merge( array_slice( $array, 0, $pos ), $new, array_slice( $array, $pos ) );
|
||||
};
|
||||
|
||||
$display_manager = $container->get( 'wcgateway.display-manager' );
|
||||
assert( $display_manager instanceof DisplayManager );
|
||||
|
||||
$module_url = $container->get( 'axo.url' );
|
||||
|
||||
// Standard Payments tab fields.
|
||||
return $insert_after(
|
||||
$fields,
|
||||
'vault_enabled_dcc',
|
||||
array(
|
||||
'axo_heading' => array(
|
||||
'heading' => __( 'Fastlane', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'ppcp-heading',
|
||||
'description' => wp_kses_post(
|
||||
sprintf(
|
||||
// translators: %1$s and %2$s is a link tag.
|
||||
__(
|
||||
'Offer an accelerated checkout experience that recognizes guest shoppers and autofills their details so they can pay in seconds.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'<a
|
||||
rel="noreferrer noopener"
|
||||
href="https://woo.com/document/woocommerce-paypal-payments/#vaulting-a-card"
|
||||
>',
|
||||
'</a>'
|
||||
)
|
||||
),
|
||||
'screens' => array(
|
||||
State::STATE_ONBOARDED,
|
||||
),
|
||||
'requirements' => array( 'dcc', 'axo' ),
|
||||
'gateway' => array( 'dcc', 'axo' ),
|
||||
),
|
||||
'axo_enabled' => array(
|
||||
'title' => __( 'Fastlane', 'woocommerce-paypal-payments' ),
|
||||
'title_html' => sprintf(
|
||||
'<img src="%sassets/images/fastlane.png" alt="%s" style="max-width: 150px; max-height: 45px;" />',
|
||||
$module_url,
|
||||
__( 'Fastlane', 'woocommerce-paypal-payments' )
|
||||
),
|
||||
'type' => 'checkbox',
|
||||
'label' => __( 'Enable Fastlane by PayPal', 'woocommerce-paypal-payments' )
|
||||
. '<p class="description">'
|
||||
. __( 'Help accelerate checkout for guests with PayPal\'s autofill solution.', 'woocommerce-paypal-payments' )
|
||||
. '</p>',
|
||||
'default' => 'yes',
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'gateway' => array( 'dcc', 'axo' ),
|
||||
'requirements' => array( 'axo' ),
|
||||
'custom_attributes' => array(
|
||||
'data-ppcp-display' => wp_json_encode(
|
||||
array(
|
||||
$display_manager
|
||||
->rule()
|
||||
->condition_element( 'axo_enabled', '1' )
|
||||
->action_visible( 'axo_gateway_title' )
|
||||
->action_visible( 'axo_privacy' )
|
||||
->action_visible( 'axo_name_on_card' )
|
||||
->action_visible( 'axo_style_heading' )
|
||||
->action_class( 'axo_enabled', 'active' )
|
||||
->to_array(),
|
||||
$display_manager
|
||||
->rule()
|
||||
->condition_element( 'axo_enabled', '1' )
|
||||
->condition_js_variable( 'ppcpAxoShowStyles', true )
|
||||
->action_visible( 'axo_style_root_heading' )
|
||||
->action_visible( 'axo_style_root_bg_color' )
|
||||
->action_visible( 'axo_style_root_error_color' )
|
||||
->action_visible( 'axo_style_root_font_family' )
|
||||
->action_visible( 'axo_style_root_text_color_base' )
|
||||
->action_visible( 'axo_style_root_font_size_base' )
|
||||
->action_visible( 'axo_style_root_padding' )
|
||||
->action_visible( 'axo_style_root_primary_color' )
|
||||
->action_visible( 'axo_style_input_heading' )
|
||||
->action_visible( 'axo_style_input_bg_color' )
|
||||
->action_visible( 'axo_style_input_border_radius' )
|
||||
->action_visible( 'axo_style_input_border_color' )
|
||||
->action_visible( 'axo_style_input_border_width' )
|
||||
->action_visible( 'axo_style_input_text_color_base' )
|
||||
->action_visible( 'axo_style_input_focus_border_color' )
|
||||
->to_array(),
|
||||
)
|
||||
),
|
||||
),
|
||||
'classes' => array( 'ppcp-valign-label-middle', 'ppcp-align-label-center' ),
|
||||
),
|
||||
'axo_gateway_title' => array(
|
||||
'title' => __( 'Gateway Title', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'text',
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'desc_tip' => true,
|
||||
'description' => __(
|
||||
'This controls the title of the Fastlane gateway the user sees on checkout.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'default' => __(
|
||||
'Debit & Credit Cards',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'screens' => array(
|
||||
State::STATE_ONBOARDED,
|
||||
),
|
||||
'requirements' => array( 'axo' ),
|
||||
'gateway' => array( 'dcc', 'axo' ),
|
||||
),
|
||||
'axo_privacy' => array(
|
||||
'title' => __( 'Privacy', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'select',
|
||||
'label' => __(
|
||||
'This setting will control whether Fastlane branding is shown by email field.
|
||||
<p class="description">PayPal powers this accelerated checkout solution from Fastlane. Since you\'ll share consumers\' email addresses with PayPal, please consult your legal advisors on the apropriate privacy setting for your business.</p>',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'desc_tip' => true,
|
||||
'description' => __(
|
||||
'This setting will control whether Fastlane branding is shown by email field.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'class' => array(),
|
||||
'input_class' => array( 'wc-enhanced-select' ),
|
||||
'default' => 'yes',
|
||||
'options' => PropertiesDictionary::privacy_options(),
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'gateway' => array( 'dcc', 'axo' ),
|
||||
'requirements' => array( 'axo' ),
|
||||
),
|
||||
'axo_name_on_card' => array(
|
||||
'title' => __( 'Display Name on Card', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'checkbox',
|
||||
'default' => 'yes',
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'class' => array(),
|
||||
'label' => __( 'Enable this to display the "Name on Card" field for new Fastlane buyers.', 'woocommerce-paypal-payments' ),
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'gateway' => array(),
|
||||
'requirements' => array( 'axo' ),
|
||||
),
|
||||
'axo_style_heading' => array(
|
||||
'heading' => __( 'Advanced Style Settings (optional)', 'woocommerce-paypal-payments' ),
|
||||
'heading_html' => sprintf(
|
||||
// translators: %1$s and %2$s are the opening and closing of HTML <a> tag.
|
||||
__(
|
||||
'Advanced Style Settings (optional) %1$sSee more%2$s %3$sSee less%4$s',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'<a href="javascript:void(0)" id="ppcp-axo-style-more" onclick="jQuery(this).hide(); jQuery(\'#ppcp-axo-style-less\').show(); document.ppcpAxoShowStyles = true; jQuery(document).trigger(\'ppcp-display-change\');" style="font-weight: normal;">',
|
||||
'</a>',
|
||||
'<a href="javascript:void(0)" id="ppcp-axo-style-less" onclick="jQuery(this).hide(); jQuery(\'#ppcp-axo-style-more\').show(); document.ppcpAxoShowStyles = false; jQuery(document).trigger(\'ppcp-display-change\');" style="font-weight: normal; display: none;">',
|
||||
'</a>'
|
||||
),
|
||||
'type' => 'ppcp-heading',
|
||||
'description' => wp_kses_post(
|
||||
sprintf(
|
||||
// translators: %1$s and %2$s is a link tag.
|
||||
__(
|
||||
'Leave the default styling, or customize how Fastlane looks on your website. %1$sSee PayPal\'s developer docs%2$s for info',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'<a href="https://www.paypal.com/us/fastlane" target="_blank">',
|
||||
'</a>'
|
||||
)
|
||||
),
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'class' => array(),
|
||||
'screens' => array(
|
||||
State::STATE_ONBOARDED,
|
||||
),
|
||||
'requirements' => array( 'dcc', 'axo' ),
|
||||
'gateway' => array( 'dcc', 'axo' ),
|
||||
),
|
||||
|
||||
'axo_style_root_heading' => array(
|
||||
'heading' => __( 'Root Settings', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'ppcp-heading',
|
||||
'description' => __(
|
||||
'These apply to the overall Fastlane checkout module.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'requirements' => array( 'dcc', 'axo' ),
|
||||
'gateway' => array( 'dcc', 'axo' ),
|
||||
),
|
||||
'axo_style_root_bg_color' => array(
|
||||
'title' => __( 'Background Color', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'text',
|
||||
'placeholder' => '#ffffff',
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'default' => '',
|
||||
'screens' => array(
|
||||
State::STATE_ONBOARDED,
|
||||
),
|
||||
'requirements' => array( 'axo' ),
|
||||
'gateway' => array( 'dcc', 'axo' ),
|
||||
),
|
||||
'axo_style_root_primary_color' => array(
|
||||
'title' => __( 'Primary Color', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'text',
|
||||
'placeholder' => '#0057F',
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'default' => '',
|
||||
'screens' => array(
|
||||
State::STATE_ONBOARDED,
|
||||
),
|
||||
'requirements' => array( 'axo' ),
|
||||
'gateway' => array( 'dcc', 'axo' ),
|
||||
),
|
||||
'axo_style_root_error_color' => array(
|
||||
'title' => __( 'Error Color', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'text',
|
||||
'placeholder' => '#D9360B',
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'default' => '',
|
||||
'screens' => array(
|
||||
State::STATE_ONBOARDED,
|
||||
),
|
||||
'requirements' => array( 'axo' ),
|
||||
'gateway' => array( 'dcc', 'axo' ),
|
||||
),
|
||||
'axo_style_root_font_family' => array(
|
||||
'title' => __( 'Font Family', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'text',
|
||||
'placeholder' => 'PayPal-Open',
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'default' => '',
|
||||
'screens' => array(
|
||||
State::STATE_ONBOARDED,
|
||||
),
|
||||
'requirements' => array( 'axo' ),
|
||||
'gateway' => array( 'dcc', 'axo' ),
|
||||
),
|
||||
'axo_style_root_text_color_base' => array(
|
||||
'title' => __( 'Text Color Base', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'text',
|
||||
'placeholder' => '#010B0D',
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'default' => '',
|
||||
'screens' => array(
|
||||
State::STATE_ONBOARDED,
|
||||
),
|
||||
'requirements' => array( 'axo' ),
|
||||
'gateway' => array( 'dcc', 'axo' ),
|
||||
),
|
||||
'axo_style_root_font_size_base' => array(
|
||||
'title' => __( 'Font Size Base', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'text',
|
||||
'placeholder' => '16px',
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'default' => '',
|
||||
'screens' => array(
|
||||
State::STATE_ONBOARDED,
|
||||
),
|
||||
'requirements' => array( 'axo' ),
|
||||
'gateway' => array( 'dcc', 'axo' ),
|
||||
),
|
||||
'axo_style_root_padding' => array(
|
||||
'title' => __( 'Padding', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'text',
|
||||
'placeholder' => '4px',
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'default' => '',
|
||||
'screens' => array(
|
||||
State::STATE_ONBOARDED,
|
||||
),
|
||||
'requirements' => array( 'axo' ),
|
||||
'gateway' => array( 'dcc', 'axo' ),
|
||||
),
|
||||
'axo_style_input_heading' => array(
|
||||
'heading' => __( 'Input Settings', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'ppcp-heading',
|
||||
'description' => __(
|
||||
'These apply to the customer input fields on your Fastlane module.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'requirements' => array( 'dcc', 'axo' ),
|
||||
'gateway' => array( 'dcc', 'axo' ),
|
||||
),
|
||||
'axo_style_input_bg_color' => array(
|
||||
'title' => __( 'Background Color', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'text',
|
||||
'placeholder' => '#ffffff',
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'default' => '',
|
||||
'screens' => array(
|
||||
State::STATE_ONBOARDED,
|
||||
),
|
||||
'requirements' => array( 'axo' ),
|
||||
'gateway' => array( 'dcc', 'axo' ),
|
||||
),
|
||||
'axo_style_input_border_radius' => array(
|
||||
'title' => __( 'Border Radius', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'text',
|
||||
'placeholder' => '0.25em',
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'default' => '',
|
||||
'screens' => array(
|
||||
State::STATE_ONBOARDED,
|
||||
),
|
||||
'requirements' => array( 'axo' ),
|
||||
'gateway' => array( 'dcc', 'axo' ),
|
||||
),
|
||||
'axo_style_input_border_color' => array(
|
||||
'title' => __( 'Border Color', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'text',
|
||||
'placeholder' => '#DADDDD',
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'default' => '',
|
||||
'screens' => array(
|
||||
State::STATE_ONBOARDED,
|
||||
),
|
||||
'requirements' => array( 'axo' ),
|
||||
'gateway' => array( 'dcc', 'axo' ),
|
||||
),
|
||||
'axo_style_input_border_width' => array(
|
||||
'title' => __( 'Border Width', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'text',
|
||||
'placeholder' => '1px',
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'default' => '',
|
||||
'screens' => array(
|
||||
State::STATE_ONBOARDED,
|
||||
),
|
||||
'requirements' => array( 'axo' ),
|
||||
'gateway' => array( 'dcc', 'axo' ),
|
||||
),
|
||||
'axo_style_input_text_color_base' => array(
|
||||
'title' => __( 'Text Color Base', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'text',
|
||||
'placeholder' => '#010B0D',
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'default' => '',
|
||||
'screens' => array(
|
||||
State::STATE_ONBOARDED,
|
||||
),
|
||||
'requirements' => array( 'axo' ),
|
||||
'gateway' => array( 'dcc', 'axo' ),
|
||||
),
|
||||
'axo_style_input_focus_border_color' => array(
|
||||
'title' => __( 'Focus Border Color', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'text',
|
||||
'placeholder' => '#0057FF',
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'default' => '',
|
||||
'screens' => array(
|
||||
State::STATE_ONBOARDED,
|
||||
),
|
||||
'requirements' => array( 'axo' ),
|
||||
'gateway' => array( 'dcc', 'axo' ),
|
||||
),
|
||||
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
);
|
16
modules/ppcp-axo/module.php
Normal file
16
modules/ppcp-axo/module.php
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
/**
|
||||
* The Axo module.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Axo
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Axo;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
||||
|
||||
return static function (): ModuleInterface {
|
||||
return new AxoModule();
|
||||
};
|
34
modules/ppcp-axo/package.json
Normal file
34
modules/ppcp-axo/package.json
Normal file
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"name": "ppcp-axo",
|
||||
"version": "1.0.0",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"browserslist": [
|
||||
"> 0.5%",
|
||||
"Safari >= 8",
|
||||
"Chrome >= 41",
|
||||
"Firefox >= 43",
|
||||
"Edge >= 14"
|
||||
],
|
||||
"dependencies": {
|
||||
"@paypal/paypal-js": "^6.0.0",
|
||||
"core-js": "^3.25.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.19",
|
||||
"@babel/preset-env": "^7.19",
|
||||
"@babel/preset-react": "^7.18.6",
|
||||
"@woocommerce/dependency-extraction-webpack-plugin": "^2.2.0",
|
||||
"babel-loader": "^8.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"file-loader": "^6.2.0",
|
||||
"sass": "^1.42.1",
|
||||
"sass-loader": "^12.1.0",
|
||||
"webpack": "^5.76",
|
||||
"webpack-cli": "^4.10"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "cross-env BABEL_ENV=default NODE_ENV=production webpack",
|
||||
"watch": "cross-env BABEL_ENV=default NODE_ENV=production webpack --watch",
|
||||
"dev": "cross-env BABEL_ENV=default webpack --watch"
|
||||
}
|
||||
}
|
45
modules/ppcp-axo/resources/css/styles.scss
Normal file
45
modules/ppcp-axo/resources/css/styles.scss
Normal file
|
@ -0,0 +1,45 @@
|
|||
.ppcp-axo-watermark-container {
|
||||
max-width: 200px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.ppcp-axo-payment-container {
|
||||
padding: 1rem 0;
|
||||
background-color: #ffffff;
|
||||
|
||||
&.hidden {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.ppcp-axo-email-widget {
|
||||
border: 1px solid #cccccc;
|
||||
background-color: #eeeeee;
|
||||
padding: 0.5rem 1rem;
|
||||
margin-bottom: 1rem;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.ppcp-axo-field-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ppcp-axo-customer-details {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.axo-checkout-header-section {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 1em;
|
||||
}
|
||||
|
||||
.ppcp-axo-order-button {
|
||||
float: none;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
margin: var(--global-md-spacing) 0 1em;
|
||||
padding: 0.6em 1em;
|
||||
}
|
815
modules/ppcp-axo/resources/js/AxoManager.js
Normal file
815
modules/ppcp-axo/resources/js/AxoManager.js
Normal file
|
@ -0,0 +1,815 @@
|
|||
import Fastlane from "./Connection/Fastlane";
|
||||
import {log} from "./Helper/Debug";
|
||||
import DomElementCollection from "./Components/DomElementCollection";
|
||||
import ShippingView from "./Views/ShippingView";
|
||||
import BillingView from "./Views/BillingView";
|
||||
import CardView from "./Views/CardView";
|
||||
import PayPalInsights from "./Insights/PayPalInsights";
|
||||
import {disable,enable} from "../../../ppcp-button/resources/js/modules/Helper/ButtonDisabler";
|
||||
import {getCurrentPaymentMethod} from "../../../ppcp-button/resources/js/modules/Helper/CheckoutMethodState";
|
||||
|
||||
class AxoManager {
|
||||
|
||||
constructor(axoConfig, ppcpConfig) {
|
||||
this.axoConfig = axoConfig;
|
||||
this.ppcpConfig = ppcpConfig;
|
||||
|
||||
this.initialized = false;
|
||||
this.fastlane = new Fastlane();
|
||||
this.$ = jQuery;
|
||||
|
||||
this.hideGatewaySelection = false;
|
||||
|
||||
this.status = {
|
||||
active: false,
|
||||
validEmail: false,
|
||||
hasProfile: false,
|
||||
useEmailWidget: this.useEmailWidget()
|
||||
};
|
||||
|
||||
this.data = {
|
||||
email: null,
|
||||
billing: null,
|
||||
shipping: null,
|
||||
card: null,
|
||||
};
|
||||
|
||||
this.el = new DomElementCollection();
|
||||
|
||||
this.styles = {
|
||||
root: {
|
||||
backgroundColorPrimary: '#ffffff'
|
||||
}
|
||||
};
|
||||
|
||||
this.locale = 'en_us';
|
||||
|
||||
this.registerEventHandlers();
|
||||
|
||||
this.shippingView = new ShippingView(this.el.shippingAddressContainer.selector, this.el);
|
||||
this.billingView = new BillingView(this.el.billingAddressContainer.selector, this.el);
|
||||
this.cardView = new CardView(this.el.paymentContainer.selector + '-details', this.el, this);
|
||||
|
||||
document.axoDebugSetStatus = (key, value) => {
|
||||
this.setStatus(key, value);
|
||||
}
|
||||
|
||||
document.axoDebugObject = () => {
|
||||
console.log(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
if (
|
||||
this.axoConfig?.insights?.enabled
|
||||
&& this.axoConfig?.insights?.client_id
|
||||
&& this.axoConfig?.insights?.session_id
|
||||
) {
|
||||
PayPalInsights.config(this.axoConfig?.insights?.client_id, { debug: true });
|
||||
PayPalInsights.setSessionId(this.axoConfig?.insights?.session_id);
|
||||
PayPalInsights.trackJsLoad();
|
||||
|
||||
if (document.querySelector('.woocommerce-checkout')) {
|
||||
PayPalInsights.trackBeginCheckout({
|
||||
amount: this.axoConfig?.insights?.amount,
|
||||
page_type: 'checkout',
|
||||
user_data: {
|
||||
country: 'US',
|
||||
is_store_member: false,
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.triggerGatewayChange();
|
||||
}
|
||||
|
||||
registerEventHandlers() {
|
||||
|
||||
this.$(document).on('change', 'input[name=payment_method]', (ev) => {
|
||||
const map = {
|
||||
'ppcp-axo-gateway': 'card',
|
||||
'ppcp-gateway': 'paypal',
|
||||
}
|
||||
|
||||
PayPalInsights.trackSelectPaymentMethod({
|
||||
payment_method_selected: map[ev.target.value] || 'other',
|
||||
page_type: 'checkout'
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Listen to Gateway Radio button changes.
|
||||
this.el.gatewayRadioButton.on('change', (ev) => {
|
||||
if (ev.target.checked) {
|
||||
this.activateAxo();
|
||||
} else {
|
||||
this.deactivateAxo();
|
||||
}
|
||||
});
|
||||
|
||||
this.$(document).on('updated_checkout payment_method_selected', () => {
|
||||
this.triggerGatewayChange();
|
||||
});
|
||||
|
||||
// On checkout form submitted.
|
||||
this.el.submitButton.on('click', () => {
|
||||
this.onClickSubmitButton();
|
||||
return false;
|
||||
})
|
||||
|
||||
// Click change shipping address link.
|
||||
this.el.changeShippingAddressLink.on('click', async () => {
|
||||
if (this.status.hasProfile) {
|
||||
const { selectionChanged, selectedAddress } = await this.fastlane.profile.showShippingAddressSelector();
|
||||
|
||||
if (selectionChanged) {
|
||||
this.setShipping(selectedAddress);
|
||||
this.shippingView.refresh();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Click change billing address link.
|
||||
this.el.changeBillingAddressLink.on('click', async () => {
|
||||
if (this.status.hasProfile) {
|
||||
this.el.changeCardLink.trigger('click');
|
||||
}
|
||||
});
|
||||
|
||||
// Click change card link.
|
||||
this.el.changeCardLink.on('click', async () => {
|
||||
const response = await this.fastlane.profile.showCardSelector();
|
||||
|
||||
if (response.selectionChanged) {
|
||||
this.setCard(response.selectedCard);
|
||||
this.setBilling({
|
||||
address: response.selectedCard.paymentSource.card.billingAddress
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Cancel "continuation" mode.
|
||||
this.el.showGatewaySelectionLink.on('click', async () => {
|
||||
this.hideGatewaySelection = false;
|
||||
this.$('.wc_payment_methods label').show();
|
||||
this.cardView.refresh();
|
||||
});
|
||||
|
||||
// Prevents sending checkout form when pressing Enter key on input field
|
||||
// and triggers customer lookup
|
||||
this.$('form.woocommerce-checkout input').on('keydown', async (ev) => {
|
||||
if(ev.key === 'Enter' && getCurrentPaymentMethod() === 'ppcp-axo-gateway' ) {
|
||||
ev.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
// Listening to status update event
|
||||
document.addEventListener('axo_status_updated', (ev) => {
|
||||
const termsField = document.querySelector("[name='terms-field']");
|
||||
if(termsField) {
|
||||
const status = ev.detail;
|
||||
const shouldHide = status.active && status.validEmail === false && status.hasProfile === false;
|
||||
|
||||
termsField.parentElement.style.display = shouldHide ? 'none' : 'block';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
rerender() {
|
||||
/**
|
||||
* active | 0 1 1 1
|
||||
* validEmail | * 0 1 1
|
||||
* hasProfile | * * 0 1
|
||||
* --------------------------------
|
||||
* defaultSubmitButton | 1 0 0 0
|
||||
* defaultEmailField | 1 0 0 0
|
||||
* defaultFormFields | 1 0 1 0
|
||||
* extraFormFields | 0 0 0 1
|
||||
* axoEmailField | 0 1 0 0
|
||||
* axoProfileViews | 0 0 0 1
|
||||
* axoPaymentContainer | 0 0 1 1
|
||||
* axoSubmitButton | 0 0 1 1
|
||||
*/
|
||||
const scenario = this.identifyScenario(
|
||||
this.status.active,
|
||||
this.status.validEmail,
|
||||
this.status.hasProfile
|
||||
);
|
||||
|
||||
log('Scenario', scenario);
|
||||
|
||||
// Reset some elements to a default status.
|
||||
this.el.watermarkContainer.hide();
|
||||
|
||||
if (scenario.defaultSubmitButton) {
|
||||
this.el.defaultSubmitButton.show();
|
||||
} else {
|
||||
this.el.defaultSubmitButton.hide();
|
||||
}
|
||||
|
||||
if (scenario.defaultEmailField) {
|
||||
this.el.fieldBillingEmail.show();
|
||||
} else {
|
||||
this.el.fieldBillingEmail.hide();
|
||||
}
|
||||
|
||||
if (scenario.defaultFormFields) {
|
||||
this.el.customerDetails.show();
|
||||
} else {
|
||||
this.el.customerDetails.hide();
|
||||
}
|
||||
|
||||
if (scenario.extraFormFields) {
|
||||
this.el.customerDetails.show();
|
||||
// Hiding of unwanted will be handled by the axoProfileViews handler.
|
||||
}
|
||||
|
||||
if (scenario.axoEmailField) {
|
||||
this.showAxoEmailField();
|
||||
this.el.watermarkContainer.show();
|
||||
|
||||
// Move watermark to after email.
|
||||
this.$(this.el.fieldBillingEmail.selector).append(
|
||||
this.$(this.el.watermarkContainer.selector)
|
||||
);
|
||||
|
||||
} else {
|
||||
this.el.emailWidgetContainer.hide();
|
||||
if (!scenario.defaultEmailField) {
|
||||
this.el.fieldBillingEmail.hide();
|
||||
}
|
||||
}
|
||||
|
||||
if (scenario.axoProfileViews) {
|
||||
this.el.billingAddressContainer.hide();
|
||||
|
||||
this.shippingView.activate();
|
||||
this.billingView.activate();
|
||||
this.cardView.activate();
|
||||
|
||||
// Move watermark to after shipping.
|
||||
this.$(this.el.shippingAddressContainer.selector).after(
|
||||
this.$(this.el.watermarkContainer.selector)
|
||||
);
|
||||
|
||||
this.el.watermarkContainer.show();
|
||||
|
||||
} else {
|
||||
this.shippingView.deactivate();
|
||||
this.billingView.deactivate();
|
||||
this.cardView.deactivate();
|
||||
}
|
||||
|
||||
if (scenario.axoPaymentContainer) {
|
||||
this.el.paymentContainer.show();
|
||||
} else {
|
||||
this.el.paymentContainer.hide();
|
||||
}
|
||||
|
||||
if (scenario.axoSubmitButton) {
|
||||
this.el.submitButtonContainer.show();
|
||||
} else {
|
||||
this.el.submitButtonContainer.hide();
|
||||
}
|
||||
|
||||
this.ensureBillingFieldsConsistency();
|
||||
this.ensureShippingFieldsConsistency();
|
||||
}
|
||||
|
||||
identifyScenario(active, validEmail, hasProfile) {
|
||||
let response = {
|
||||
defaultSubmitButton: false,
|
||||
defaultEmailField: false,
|
||||
defaultFormFields: false,
|
||||
extraFormFields: false,
|
||||
axoEmailField: false,
|
||||
axoProfileViews: false,
|
||||
axoPaymentContainer: false,
|
||||
axoSubmitButton: false,
|
||||
}
|
||||
|
||||
if (active && validEmail && hasProfile) {
|
||||
response.extraFormFields = true;
|
||||
response.axoProfileViews = true;
|
||||
response.axoPaymentContainer = true;
|
||||
response.axoSubmitButton = true;
|
||||
return response;
|
||||
}
|
||||
if (active && validEmail && !hasProfile) {
|
||||
response.defaultFormFields = true;
|
||||
response.axoEmailField = true;
|
||||
response.axoPaymentContainer = true;
|
||||
response.axoSubmitButton = true;
|
||||
return response;
|
||||
}
|
||||
if (active && !validEmail) {
|
||||
response.axoEmailField = true;
|
||||
return response;
|
||||
}
|
||||
if (!active) {
|
||||
response.defaultSubmitButton = true;
|
||||
response.defaultEmailField = true;
|
||||
response.defaultFormFields = true;
|
||||
return response;
|
||||
}
|
||||
throw new Error('Invalid scenario.');
|
||||
}
|
||||
|
||||
ensureBillingFieldsConsistency() {
|
||||
const $billingFields = this.$('.woocommerce-billing-fields .form-row:visible');
|
||||
const $billingHeaders = this.$('.woocommerce-billing-fields h3');
|
||||
if (this.billingView.isActive()) {
|
||||
if ($billingFields.length) {
|
||||
$billingHeaders.show();
|
||||
} else {
|
||||
$billingHeaders.hide();
|
||||
}
|
||||
} else {
|
||||
$billingHeaders.show();
|
||||
}
|
||||
}
|
||||
|
||||
ensureShippingFieldsConsistency() {
|
||||
const $shippingFields = this.$('.woocommerce-shipping-fields .form-row:visible');
|
||||
const $shippingHeaders = this.$('.woocommerce-shipping-fields h3');
|
||||
if (this.shippingView.isActive()) {
|
||||
if ($shippingFields.length) {
|
||||
$shippingHeaders.show();
|
||||
} else {
|
||||
$shippingHeaders.hide();
|
||||
}
|
||||
} else {
|
||||
$shippingHeaders.show();
|
||||
}
|
||||
}
|
||||
|
||||
showAxoEmailField() {
|
||||
if (this.status.useEmailWidget) {
|
||||
this.el.emailWidgetContainer.show();
|
||||
this.el.fieldBillingEmail.hide();
|
||||
} else {
|
||||
this.el.emailWidgetContainer.hide();
|
||||
this.el.fieldBillingEmail.show();
|
||||
}
|
||||
}
|
||||
|
||||
setStatus(key, value) {
|
||||
this.status[key] = value;
|
||||
|
||||
log('Status updated', JSON.parse(JSON.stringify(this.status)));
|
||||
|
||||
document.dispatchEvent(new CustomEvent("axo_status_updated", {detail: this.status}));
|
||||
|
||||
this.rerender();
|
||||
}
|
||||
|
||||
activateAxo() {
|
||||
this.initPlacements();
|
||||
this.initFastlane();
|
||||
this.setStatus('active', true);
|
||||
|
||||
const emailInput = document.querySelector(this.el.fieldBillingEmail.selector + ' input');
|
||||
if (emailInput && this.lastEmailCheckedIdentity !== emailInput.value) {
|
||||
this.onChangeEmail();
|
||||
}
|
||||
}
|
||||
|
||||
deactivateAxo() {
|
||||
this.setStatus('active', false);
|
||||
}
|
||||
|
||||
initPlacements() {
|
||||
const wrapper = this.el.axoCustomerDetails;
|
||||
|
||||
// Customer details container.
|
||||
if (!document.querySelector(wrapper.selector)) {
|
||||
document.querySelector(wrapper.anchorSelector).insertAdjacentHTML('afterbegin', `
|
||||
<div id="${wrapper.id}" class="${wrapper.className}"></div>
|
||||
`);
|
||||
}
|
||||
|
||||
const wrapperElement = document.querySelector(wrapper.selector);
|
||||
|
||||
// Billing view container.
|
||||
const bc = this.el.billingAddressContainer;
|
||||
if (!document.querySelector(bc.selector)) {
|
||||
wrapperElement.insertAdjacentHTML('beforeend', `
|
||||
<div id="${bc.id}" class="${bc.className}"></div>
|
||||
`);
|
||||
}
|
||||
|
||||
// Shipping view container.
|
||||
const sc = this.el.shippingAddressContainer;
|
||||
if (!document.querySelector(sc.selector)) {
|
||||
wrapperElement.insertAdjacentHTML('beforeend', `
|
||||
<div id="${sc.id}" class="${sc.className}"></div>
|
||||
`);
|
||||
}
|
||||
|
||||
// Watermark container
|
||||
const wc = this.el.watermarkContainer;
|
||||
if (!document.querySelector(wc.selector)) {
|
||||
this.emailInput = document.querySelector(this.el.fieldBillingEmail.selector + ' input');
|
||||
this.emailInput.insertAdjacentHTML('afterend', `
|
||||
<div class="${wc.className}" id="${wc.id}"></div>
|
||||
`);
|
||||
}
|
||||
|
||||
// Payment container
|
||||
const pc = this.el.paymentContainer;
|
||||
if (!document.querySelector(pc.selector)) {
|
||||
const gatewayPaymentContainer = document.querySelector('.payment_method_ppcp-axo-gateway');
|
||||
gatewayPaymentContainer.insertAdjacentHTML('beforeend', `
|
||||
<div id="${pc.id}" class="${pc.className} hidden">
|
||||
<div id="${pc.id}-form" class="${pc.className}-form"></div>
|
||||
<div id="${pc.id}-details" class="${pc.className}-details"></div>
|
||||
</div>
|
||||
`);
|
||||
}
|
||||
|
||||
if (this.useEmailWidget()) {
|
||||
|
||||
// Display email widget.
|
||||
const ec = this.el.emailWidgetContainer;
|
||||
if (!document.querySelector(ec.selector)) {
|
||||
wrapperElement.insertAdjacentHTML('afterbegin', `
|
||||
<div id="${ec.id}" class="${ec.className}">
|
||||
--- EMAIL WIDGET PLACEHOLDER ---
|
||||
</div>
|
||||
`);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Move email to the AXO container.
|
||||
let emailRow = document.querySelector(this.el.fieldBillingEmail.selector);
|
||||
wrapperElement.prepend(emailRow);
|
||||
}
|
||||
}
|
||||
|
||||
async initFastlane() {
|
||||
if (this.initialized) {
|
||||
return;
|
||||
}
|
||||
this.initialized = true;
|
||||
|
||||
await this.connect();
|
||||
this.renderWatermark();
|
||||
this.watchEmail();
|
||||
}
|
||||
|
||||
async connect() {
|
||||
if (this.axoConfig.environment.is_sandbox) {
|
||||
window.localStorage.setItem('axoEnv', 'sandbox');
|
||||
}
|
||||
|
||||
await this.fastlane.connect({
|
||||
locale: this.locale,
|
||||
styles: this.styles
|
||||
});
|
||||
|
||||
this.fastlane.setLocale('en_us');
|
||||
}
|
||||
|
||||
triggerGatewayChange() {
|
||||
this.el.gatewayRadioButton.trigger('change');
|
||||
}
|
||||
|
||||
async renderWatermark(includeAdditionalInfo = true) {
|
||||
(await this.fastlane.FastlaneWatermarkComponent({
|
||||
includeAdditionalInfo
|
||||
})).render(this.el.watermarkContainer.selector);
|
||||
}
|
||||
|
||||
watchEmail() {
|
||||
|
||||
if (this.useEmailWidget()) {
|
||||
|
||||
// TODO
|
||||
|
||||
} else {
|
||||
|
||||
this.emailInput = document.querySelector(this.el.fieldBillingEmail.selector + ' input');
|
||||
this.emailInput.addEventListener('change', async ()=> {
|
||||
this.onChangeEmail();
|
||||
});
|
||||
|
||||
if (this.emailInput.value) {
|
||||
this.onChangeEmail();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async onChangeEmail () {
|
||||
this.clearData();
|
||||
|
||||
if (!this.status.active) {
|
||||
log('Email checking skipped, AXO not active.');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.emailInput) {
|
||||
log('Email field not initialized.');
|
||||
return;
|
||||
}
|
||||
|
||||
log('Email changed: ' + (this.emailInput ? this.emailInput.value : '<empty>'));
|
||||
|
||||
this.$(this.el.paymentContainer.selector + '-detail').html('');
|
||||
this.$(this.el.paymentContainer.selector + '-form').html('');
|
||||
|
||||
this.setStatus('validEmail', false);
|
||||
this.setStatus('hasProfile', false);
|
||||
|
||||
this.hideGatewaySelection = false;
|
||||
|
||||
this.lastEmailCheckedIdentity = this.emailInput.value;
|
||||
|
||||
if (!this.emailInput.value || !this.emailInput.checkValidity()) {
|
||||
log('The email address is not valid.');
|
||||
return;
|
||||
}
|
||||
|
||||
this.data.email = this.emailInput.value;
|
||||
this.billingView.setData(this.data);
|
||||
|
||||
if (!this.fastlane.identity) {
|
||||
log('Not initialized.');
|
||||
return;
|
||||
}
|
||||
|
||||
PayPalInsights.trackSubmitCheckoutEmail({
|
||||
page_type: 'checkout'
|
||||
});
|
||||
|
||||
await this.lookupCustomerByEmail();
|
||||
}
|
||||
|
||||
async lookupCustomerByEmail() {
|
||||
const lookupResponse = await this.fastlane.identity.lookupCustomerByEmail(this.emailInput.value);
|
||||
|
||||
if (lookupResponse.customerContextId) {
|
||||
// Email is associated with a Connect profile or a PayPal member.
|
||||
// Authenticate the customer to get access to their profile.
|
||||
log('Email is associated with a Connect profile or a PayPal member');
|
||||
|
||||
const authResponse = await this.fastlane.identity.triggerAuthenticationFlow(lookupResponse.customerContextId);
|
||||
|
||||
log('AuthResponse', authResponse);
|
||||
|
||||
if (authResponse.authenticationState === 'succeeded') {
|
||||
log(JSON.stringify(authResponse));
|
||||
|
||||
this.setShipping(authResponse.profileData.shippingAddress);
|
||||
|
||||
const billingAddress = authResponse.profileData?.card?.paymentSource?.card?.billingAddress;
|
||||
if(billingAddress) {
|
||||
this.setBilling({
|
||||
address: billingAddress,
|
||||
phoneNumber: authResponse.profileData.shippingAddress.phoneNumber.nationalNumber ?? ''
|
||||
});
|
||||
this.setCard(authResponse.profileData.card);
|
||||
}
|
||||
|
||||
this.setStatus('validEmail', true);
|
||||
this.setStatus('hasProfile', true);
|
||||
|
||||
this.hideGatewaySelection = true;
|
||||
this.$('.wc_payment_methods label').hide();
|
||||
|
||||
await this.renderWatermark(false);
|
||||
|
||||
this.rerender();
|
||||
|
||||
} else {
|
||||
// authentication failed or canceled by the customer
|
||||
// set status as guest customer
|
||||
log("Authentication Failed")
|
||||
|
||||
this.setStatus('validEmail', true);
|
||||
this.setStatus('hasProfile', false);
|
||||
|
||||
await this.renderWatermark(true);
|
||||
|
||||
this.cardComponent = (await this.fastlane.FastlaneCardComponent(
|
||||
this.cardComponentData()
|
||||
)).render(this.el.paymentContainer.selector + '-form');
|
||||
}
|
||||
|
||||
} else {
|
||||
// No profile found with this email address.
|
||||
// This is a guest customer.
|
||||
log('No profile found with this email address.');
|
||||
|
||||
this.setStatus('validEmail', true);
|
||||
this.setStatus('hasProfile', false);
|
||||
|
||||
await this.renderWatermark(true);
|
||||
|
||||
this.cardComponent = (await this.fastlane.FastlaneCardComponent(
|
||||
this.cardComponentData()
|
||||
)).render(this.el.paymentContainer.selector + '-form');
|
||||
}
|
||||
}
|
||||
|
||||
clearData() {
|
||||
this.data = {
|
||||
email: null,
|
||||
billing: null,
|
||||
shipping: null,
|
||||
card: null,
|
||||
};
|
||||
}
|
||||
|
||||
setShipping(shipping) {
|
||||
this.data.shipping = shipping;
|
||||
this.shippingView.setData(this.data);
|
||||
}
|
||||
|
||||
setBilling(billing) {
|
||||
this.data.billing = billing;
|
||||
this.billingView.setData(this.data);
|
||||
}
|
||||
|
||||
setCard(card) {
|
||||
this.data.card = card;
|
||||
this.cardView.setData(this.data);
|
||||
}
|
||||
|
||||
onClickSubmitButton() {
|
||||
// TODO: validate data.
|
||||
|
||||
if (this.data.card) { // Ryan flow
|
||||
log('Ryan flow.');
|
||||
|
||||
this.$('#ship-to-different-address-checkbox').prop('checked', 'checked');
|
||||
|
||||
let data = {};
|
||||
this.billingView.toSubmitData(data);
|
||||
this.shippingView.toSubmitData(data);
|
||||
this.cardView.toSubmitData(data);
|
||||
|
||||
this.ensureBillingPhoneNumber(data);
|
||||
|
||||
this.submit(this.data.card.id, data);
|
||||
|
||||
} else { // Gary flow
|
||||
log('Gary flow.');
|
||||
|
||||
try {
|
||||
this.cardComponent.getPaymentToken(
|
||||
this.tokenizeData()
|
||||
).then((response) => {
|
||||
this.submit(response.id);
|
||||
});
|
||||
} catch (e) {
|
||||
log('Error tokenizing.');
|
||||
alert('Error tokenizing data.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cardComponentData() {
|
||||
const fields = {
|
||||
cardholderName: {
|
||||
enabled: true
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
fields: fields,
|
||||
styles: this.deleteKeysWithEmptyString(this.axoConfig.style_options)
|
||||
}
|
||||
}
|
||||
|
||||
tokenizeData() {
|
||||
return {
|
||||
name: {
|
||||
fullName: this.billingView.fullName()
|
||||
},
|
||||
billingAddress: {
|
||||
addressLine1: this.billingView.inputValue('street1'),
|
||||
addressLine2: this.billingView.inputValue('street2'),
|
||||
adminArea1: this.billingView.inputValue('city'),
|
||||
adminArea2: this.billingView.inputValue('stateCode'),
|
||||
postalCode: this.billingView.inputValue('postCode'),
|
||||
countryCode: this.billingView.inputValue('countryCode'),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
submit(nonce, data) {
|
||||
// Send the nonce and previously captured device data to server to complete checkout
|
||||
if (!this.el.axoNonceInput.get()) {
|
||||
this.$('form.woocommerce-checkout').append(`<input type="hidden" id="${this.el.axoNonceInput.id}" name="axo_nonce" value="" />`);
|
||||
}
|
||||
|
||||
this.el.axoNonceInput.get().value = nonce;
|
||||
|
||||
PayPalInsights.trackEndCheckout({
|
||||
amount: this.axoConfig?.insights?.amount,
|
||||
page_type: 'checkout',
|
||||
payment_method_selected: 'card',
|
||||
user_data: {
|
||||
country: 'US',
|
||||
is_store_member: false,
|
||||
}
|
||||
});
|
||||
|
||||
if (data) {
|
||||
|
||||
// Ryan flow.
|
||||
const form = document.querySelector('form.woocommerce-checkout');
|
||||
const formData = new FormData(form);
|
||||
|
||||
this.showLoading();
|
||||
|
||||
// Fill in form data.
|
||||
Object.keys(data).forEach((key) => {
|
||||
formData.set(key, data[key]);
|
||||
});
|
||||
|
||||
// Set type of user (Ryan) to be received on WC gateway process payment request.
|
||||
formData.set('fastlane_member', true);
|
||||
|
||||
fetch(wc_checkout_params.checkout_url, { // TODO: maybe create a new endpoint to process_payment.
|
||||
method: "POST",
|
||||
body: formData
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(responseData => {
|
||||
if (responseData.result === 'failure') {
|
||||
if (responseData.messages) {
|
||||
const $notices = this.$('.woocommerce-notices-wrapper').eq(0);
|
||||
$notices.html(responseData.messages);
|
||||
this.$('html, body').animate({
|
||||
scrollTop: $notices.offset().top
|
||||
}, 500);
|
||||
}
|
||||
console.error('Failure:', responseData);
|
||||
this.hideLoading();
|
||||
return;
|
||||
}
|
||||
if (responseData.redirect) {
|
||||
window.location.href = responseData.redirect;
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
this.hideLoading();
|
||||
});
|
||||
|
||||
} else {
|
||||
// Gary flow.
|
||||
this.el.defaultSubmitButton.click();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
showLoading() {
|
||||
const submitContainerSelector = '.woocommerce-checkout-payment';
|
||||
jQuery('form.woocommerce-checkout').append('<div class="blockUI blockOverlay" style="z-index: 1000; border: medium; margin: 0px; padding: 0px; width: 100%; height: 100%; top: 0px; left: 0px; background: rgb(255, 255, 255); opacity: 0.6; cursor: default; position: absolute;"></div>');
|
||||
disable(submitContainerSelector);
|
||||
}
|
||||
|
||||
hideLoading() {
|
||||
const submitContainerSelector = '.woocommerce-checkout-payment';
|
||||
jQuery('form.woocommerce-checkout .blockOverlay').remove();
|
||||
enable(submitContainerSelector);
|
||||
}
|
||||
|
||||
useEmailWidget() {
|
||||
return this.axoConfig?.widgets?.email === 'use_widget';
|
||||
}
|
||||
|
||||
deleteKeysWithEmptyString = (obj) => {
|
||||
for(let key of Object.keys(obj)){
|
||||
if (obj[key] === ''){
|
||||
delete obj[key];
|
||||
}
|
||||
else if (typeof obj[key] === 'object'){
|
||||
obj[key] = this.deleteKeysWithEmptyString(obj[key]);
|
||||
if (Object.keys(obj[key]).length === 0 ) delete obj[key];
|
||||
}
|
||||
}
|
||||
|
||||
return Array.isArray(obj) ? obj.filter(val => val) : obj;
|
||||
}
|
||||
|
||||
ensureBillingPhoneNumber(data) {
|
||||
if (data.billing_phone === '') {
|
||||
let phone = '';
|
||||
const cc = this.data?.shipping?.phoneNumber?.countryCode;
|
||||
const number = this.data?.shipping?.phoneNumber?.nationalNumber;
|
||||
|
||||
if (cc) {
|
||||
phone = `+${cc} `;
|
||||
}
|
||||
phone += number;
|
||||
|
||||
data.billing_phone = phone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default AxoManager;
|
39
modules/ppcp-axo/resources/js/Components/DomElement.js
Normal file
39
modules/ppcp-axo/resources/js/Components/DomElement.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
class DomElement {
|
||||
|
||||
constructor(config) {
|
||||
this.$ = jQuery;
|
||||
this.config = config;
|
||||
this.selector = this.config.selector;
|
||||
this.id = this.config.id || null;
|
||||
this.className = this.config.className || null;
|
||||
this.attributes = this.config.attributes || null;
|
||||
this.anchorSelector = this.config.anchorSelector || null;
|
||||
}
|
||||
|
||||
trigger(action) {
|
||||
this.$(this.selector).trigger(action);
|
||||
}
|
||||
|
||||
on(action, callable) {
|
||||
this.$(document).on(action, this.selector, callable);
|
||||
}
|
||||
|
||||
hide() {
|
||||
this.$(this.selector).hide();
|
||||
}
|
||||
|
||||
show() {
|
||||
this.$(this.selector).show();
|
||||
}
|
||||
|
||||
click() {
|
||||
this.get().click();
|
||||
}
|
||||
|
||||
get() {
|
||||
return document.querySelector(this.selector);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default DomElement;
|
|
@ -0,0 +1,95 @@
|
|||
import DomElement from "./DomElement";
|
||||
|
||||
class DomElementCollection {
|
||||
|
||||
constructor() {
|
||||
this.gatewayRadioButton = new DomElement({
|
||||
selector: '#payment_method_ppcp-axo-gateway',
|
||||
});
|
||||
|
||||
this.defaultSubmitButton = new DomElement({
|
||||
selector: '#place_order',
|
||||
});
|
||||
|
||||
this.paymentContainer = new DomElement({
|
||||
id: 'ppcp-axo-payment-container',
|
||||
selector: '#ppcp-axo-payment-container',
|
||||
className: 'ppcp-axo-payment-container'
|
||||
});
|
||||
|
||||
this.watermarkContainer = new DomElement({
|
||||
id: 'ppcp-axo-watermark-container',
|
||||
selector: '#ppcp-axo-watermark-container',
|
||||
className: 'ppcp-axo-watermark-container'
|
||||
});
|
||||
|
||||
this.customerDetails = new DomElement({
|
||||
selector: '#customer_details > *:not(#ppcp-axo-customer-details)'
|
||||
});
|
||||
|
||||
this.axoCustomerDetails = new DomElement({
|
||||
id: 'ppcp-axo-customer-details',
|
||||
selector: '#ppcp-axo-customer-details',
|
||||
className: 'ppcp-axo-customer-details',
|
||||
anchorSelector: '#customer_details'
|
||||
});
|
||||
|
||||
this.emailWidgetContainer = new DomElement({
|
||||
id: 'ppcp-axo-email-widget',
|
||||
selector: '#ppcp-axo-email-widget',
|
||||
className: 'ppcp-axo-email-widget'
|
||||
});
|
||||
|
||||
this.shippingAddressContainer = new DomElement({
|
||||
id: 'ppcp-axo-shipping-address-container',
|
||||
selector: '#ppcp-axo-shipping-address-container',
|
||||
className: 'ppcp-axo-shipping-address-container'
|
||||
});
|
||||
|
||||
this.billingAddressContainer = new DomElement({
|
||||
id: 'ppcp-axo-billing-address-container',
|
||||
selector: '#ppcp-axo-billing-address-container',
|
||||
className: 'ppcp-axo-billing-address-container'
|
||||
});
|
||||
|
||||
this.fieldBillingEmail = new DomElement({
|
||||
selector: '#billing_email_field'
|
||||
});
|
||||
|
||||
this.submitButtonContainer = new DomElement({
|
||||
selector: '#ppcp-axo-submit-button-container',
|
||||
});
|
||||
|
||||
this.submitButton = new DomElement({
|
||||
selector: '#ppcp-axo-submit-button-container button'
|
||||
});
|
||||
|
||||
this.changeShippingAddressLink = new DomElement({
|
||||
selector: '*[data-ppcp-axo-change-shipping-address]',
|
||||
attributes: 'data-ppcp-axo-change-shipping-address',
|
||||
});
|
||||
|
||||
this.changeBillingAddressLink = new DomElement({
|
||||
selector: '*[data-ppcp-axo-change-billing-address]',
|
||||
attributes: 'data-ppcp-axo-change-billing-address',
|
||||
});
|
||||
|
||||
this.changeCardLink = new DomElement({
|
||||
selector: '*[data-ppcp-axo-change-card]',
|
||||
attributes: 'data-ppcp-axo-change-card',
|
||||
});
|
||||
|
||||
this.showGatewaySelectionLink = new DomElement({
|
||||
selector: '*[data-ppcp-axo-show-gateway-selection]',
|
||||
attributes: 'data-ppcp-axo-show-gateway-selection',
|
||||
});
|
||||
|
||||
this.axoNonceInput = new DomElement({
|
||||
id: 'ppcp-axo-nonce',
|
||||
selector: '#ppcp-axo-nonce',
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
export default DomElementCollection;
|
153
modules/ppcp-axo/resources/js/Components/FormFieldGroup.js
Normal file
153
modules/ppcp-axo/resources/js/Components/FormFieldGroup.js
Normal file
|
@ -0,0 +1,153 @@
|
|||
|
||||
class FormFieldGroup {
|
||||
|
||||
constructor(config) {
|
||||
this.data = {};
|
||||
|
||||
this.baseSelector = config.baseSelector;
|
||||
this.contentSelector = config.contentSelector;
|
||||
this.fields = config.fields || {};
|
||||
this.template = config.template;
|
||||
|
||||
this.active = false;
|
||||
}
|
||||
|
||||
setData(data) {
|
||||
this.data = data;
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
dataValue(fieldKey) {
|
||||
if (!fieldKey || !this.fields[fieldKey]) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (typeof this.fields[fieldKey].valueCallback === 'function') {
|
||||
return this.fields[fieldKey].valueCallback(this.data);
|
||||
}
|
||||
|
||||
const path = this.fields[fieldKey].valuePath;
|
||||
|
||||
if (!path) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const value = path.split('.').reduce((acc, key) => (acc && acc[key] !== undefined) ? acc[key] : undefined, this.data);
|
||||
return value ? value : '';
|
||||
}
|
||||
|
||||
activate() {
|
||||
this.active = true;
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
deactivate() {
|
||||
this.active = false;
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
toggle() {
|
||||
this.active ? this.deactivate() : this.activate();
|
||||
}
|
||||
|
||||
refresh() {
|
||||
let content = document.querySelector(this.contentSelector);
|
||||
|
||||
if (!content) {
|
||||
return;
|
||||
}
|
||||
|
||||
content.innerHTML = '';
|
||||
|
||||
if (!this.active) {
|
||||
this.hideField(this.contentSelector);
|
||||
} else {
|
||||
this.showField(this.contentSelector);
|
||||
}
|
||||
|
||||
Object.keys(this.fields).forEach((key) => {
|
||||
const field = this.fields[key];
|
||||
|
||||
if (this.active && !field.showInput) {
|
||||
this.hideField(field.selector);
|
||||
} else {
|
||||
this.showField(field.selector);
|
||||
}
|
||||
});
|
||||
|
||||
if (typeof this.template === 'function') {
|
||||
content.innerHTML = this.template({
|
||||
value: (fieldKey) => {
|
||||
return this.dataValue(fieldKey);
|
||||
},
|
||||
isEmpty: () => {
|
||||
let isEmpty = true;
|
||||
Object.keys(this.fields).forEach((fieldKey) => {
|
||||
if (this.dataValue(fieldKey)) {
|
||||
isEmpty = false;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return isEmpty;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
showField(selector) {
|
||||
const field = document.querySelector(this.baseSelector + ' ' + selector);
|
||||
if (field) {
|
||||
field.classList.remove('ppcp-axo-field-hidden');
|
||||
}
|
||||
}
|
||||
|
||||
hideField(selector) {
|
||||
const field = document.querySelector(this.baseSelector + ' ' + selector);
|
||||
if (field) {
|
||||
field.classList.add('ppcp-axo-field-hidden');
|
||||
}
|
||||
}
|
||||
|
||||
inputElement(name) {
|
||||
const baseSelector = this.fields[name].selector;
|
||||
|
||||
const select = document.querySelector(baseSelector + ' select');
|
||||
if (select) {
|
||||
return select;
|
||||
}
|
||||
|
||||
const input = document.querySelector(baseSelector + ' input');
|
||||
if (input) {
|
||||
return input;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
inputValue(name) {
|
||||
const el = this.inputElement(name);
|
||||
return el ? el.value : '';
|
||||
}
|
||||
|
||||
toSubmitData(data) {
|
||||
Object.keys(this.fields).forEach((fieldKey) => {
|
||||
const field = this.fields[fieldKey];
|
||||
|
||||
if (!field.valuePath || !field.selector) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const inputElement = this.inputElement(fieldKey);
|
||||
|
||||
if (!inputElement) {
|
||||
return true;
|
||||
}
|
||||
|
||||
data[inputElement.name] = this.dataValue(fieldKey);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default FormFieldGroup;
|
42
modules/ppcp-axo/resources/js/Connection/Fastlane.js
Normal file
42
modules/ppcp-axo/resources/js/Connection/Fastlane.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
|
||||
class Fastlane {
|
||||
|
||||
construct() {
|
||||
this.connection = null;
|
||||
this.identity = null;
|
||||
this.profile = null;
|
||||
this.FastlaneCardComponent = null;
|
||||
this.FastlanePaymentComponent = null;
|
||||
this.FastlaneWatermarkComponent = null;
|
||||
}
|
||||
|
||||
connect(config) {
|
||||
return new Promise((resolve, reject) => {
|
||||
window.paypal.Fastlane(config)
|
||||
.then((result) => {
|
||||
this.init(result);
|
||||
resolve();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error)
|
||||
reject();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
init(connection) {
|
||||
this.connection = connection;
|
||||
this.identity = this.connection.identity;
|
||||
this.profile = this.connection.profile;
|
||||
this.FastlaneCardComponent = this.connection.FastlaneCardComponent;
|
||||
this.FastlanePaymentComponent = this.connection.FastlanePaymentComponent;
|
||||
this.FastlaneWatermarkComponent = this.connection.FastlaneWatermarkComponent
|
||||
}
|
||||
|
||||
setLocale(locale) {
|
||||
this.connection.setLocale(locale);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Fastlane;
|
4
modules/ppcp-axo/resources/js/Helper/Debug.js
Normal file
4
modules/ppcp-axo/resources/js/Helper/Debug.js
Normal file
|
@ -0,0 +1,4 @@
|
|||
|
||||
export function log(...args) {
|
||||
//console.log('[AXO] ', ...args);
|
||||
}
|
58
modules/ppcp-axo/resources/js/Insights/PayPalInsights.js
Normal file
58
modules/ppcp-axo/resources/js/Insights/PayPalInsights.js
Normal file
|
@ -0,0 +1,58 @@
|
|||
|
||||
class PayPalInsights {
|
||||
|
||||
constructor() {
|
||||
window.paypalInsightDataLayer = window.paypalInsightDataLayer || [];
|
||||
document.paypalInsight = () => {
|
||||
paypalInsightDataLayer.push(arguments);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {PayPalInsights}
|
||||
*/
|
||||
static init() {
|
||||
if (!PayPalInsights.instance) {
|
||||
PayPalInsights.instance = new PayPalInsights();
|
||||
}
|
||||
return PayPalInsights.instance;
|
||||
}
|
||||
|
||||
static track(eventName, data) {
|
||||
PayPalInsights.init();
|
||||
paypalInsight('event', eventName, data);
|
||||
}
|
||||
|
||||
static config (clientId, data) {
|
||||
PayPalInsights.init();
|
||||
paypalInsight('config', clientId, data);
|
||||
}
|
||||
|
||||
static setSessionId (sessionId) {
|
||||
PayPalInsights.init();
|
||||
paypalInsight('set', { session_id: sessionId });
|
||||
}
|
||||
|
||||
static trackJsLoad () {
|
||||
PayPalInsights.track('js_load', { timestamp: Date.now() });
|
||||
}
|
||||
|
||||
static trackBeginCheckout (data) {
|
||||
PayPalInsights.track('begin_checkout', data);
|
||||
}
|
||||
|
||||
static trackSubmitCheckoutEmail (data) {
|
||||
PayPalInsights.track('submit_checkout_email', data);
|
||||
}
|
||||
|
||||
static trackSelectPaymentMethod (data) {
|
||||
PayPalInsights.track('select_payment_method', data);
|
||||
}
|
||||
|
||||
static trackEndCheckout (data) {
|
||||
PayPalInsights.track('end_checkout', data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default PayPalInsights;
|
136
modules/ppcp-axo/resources/js/Views/BillingView.js
Normal file
136
modules/ppcp-axo/resources/js/Views/BillingView.js
Normal file
|
@ -0,0 +1,136 @@
|
|||
import FormFieldGroup from "../Components/FormFieldGroup";
|
||||
|
||||
class BillingView {
|
||||
|
||||
constructor(selector, elements) {
|
||||
this.el = elements;
|
||||
|
||||
this.group = new FormFieldGroup({
|
||||
baseSelector: '.woocommerce-checkout',
|
||||
contentSelector: selector,
|
||||
template: (data) => {
|
||||
const valueOfSelect = (selectSelector, key) => {
|
||||
if (!key) {
|
||||
return '';
|
||||
}
|
||||
const selectElement = document.querySelector(selectSelector);
|
||||
|
||||
if (!selectElement) {
|
||||
return key;
|
||||
}
|
||||
|
||||
const option = selectElement.querySelector(`option[value="${key}"]`);
|
||||
return option ? option.textContent : key;
|
||||
}
|
||||
|
||||
if (data.isEmpty()) {
|
||||
return `
|
||||
<div style="margin-bottom: 20px;">
|
||||
<div class="axo-checkout-header-section">
|
||||
<h3>Billing</h3>
|
||||
<a href="javascript:void(0)" ${this.el.changeBillingAddressLink.attributes}>Edit</a>
|
||||
</div>
|
||||
<div>Please fill in your billing details.</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
return `
|
||||
<div style="margin-bottom: 20px;">
|
||||
<div class="axo-checkout-header-section">
|
||||
<h3>Billing</h3>
|
||||
<a href="javascript:void(0)" ${this.el.changeBillingAddressLink.attributes}>Edit</a>
|
||||
</div>
|
||||
<div>${data.value('email')}</div>
|
||||
<div>${data.value('company')}</div>
|
||||
<div>${data.value('firstName')} ${data.value('lastName')}</div>
|
||||
<div>${data.value('street1')}</div>
|
||||
<div>${data.value('street2')}</div>
|
||||
<div>${data.value('postCode')} ${data.value('city')}</div>
|
||||
<div>${valueOfSelect('#billing_state', data.value('stateCode'))}</div>
|
||||
<div>${valueOfSelect('#billing_country', data.value('countryCode'))}</div>
|
||||
</div>
|
||||
`;
|
||||
},
|
||||
fields: {
|
||||
email: {
|
||||
'valuePath': 'email',
|
||||
},
|
||||
firstName: {
|
||||
'selector': '#billing_first_name_field',
|
||||
'valuePath': null
|
||||
},
|
||||
lastName: {
|
||||
'selector': '#billing_last_name_field',
|
||||
'valuePath': null
|
||||
},
|
||||
street1: {
|
||||
'selector': '#billing_address_1_field',
|
||||
'valuePath': 'billing.address.addressLine1',
|
||||
},
|
||||
street2: {
|
||||
'selector': '#billing_address_2_field',
|
||||
'valuePath': null
|
||||
},
|
||||
postCode: {
|
||||
'selector': '#billing_postcode_field',
|
||||
'valuePath': 'billing.address.postalCode',
|
||||
},
|
||||
city: {
|
||||
'selector': '#billing_city_field',
|
||||
'valuePath': 'billing.address.adminArea2',
|
||||
},
|
||||
stateCode: {
|
||||
'selector': '#billing_state_field',
|
||||
'valuePath': 'billing.address.adminArea1',
|
||||
},
|
||||
countryCode: {
|
||||
'selector': '#billing_country_field',
|
||||
'valuePath': 'billing.address.countryCode',
|
||||
},
|
||||
company: {
|
||||
'selector': '#billing_company_field',
|
||||
'valuePath': null,
|
||||
},
|
||||
phone: {
|
||||
'selector': '#billing_phone_field',
|
||||
'valuePath': 'billing.phoneNumber'
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
isActive() {
|
||||
return this.group.active;
|
||||
}
|
||||
|
||||
activate() {
|
||||
this.group.activate();
|
||||
}
|
||||
|
||||
deactivate() {
|
||||
this.group.deactivate();
|
||||
}
|
||||
|
||||
refresh() {
|
||||
this.group.refresh();
|
||||
}
|
||||
|
||||
setData(data) {
|
||||
this.group.setData(data);
|
||||
}
|
||||
|
||||
inputValue(name) {
|
||||
return this.group.inputValue(name);
|
||||
}
|
||||
|
||||
fullName() {
|
||||
return `${this.inputValue('firstName')} ${this.inputValue('lastName')}`.trim();
|
||||
}
|
||||
|
||||
toSubmitData(data) {
|
||||
return this.group.toSubmitData(data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default BillingView;
|
117
modules/ppcp-axo/resources/js/Views/CardView.js
Normal file
117
modules/ppcp-axo/resources/js/Views/CardView.js
Normal file
|
@ -0,0 +1,117 @@
|
|||
import FormFieldGroup from "../Components/FormFieldGroup";
|
||||
|
||||
class CardView {
|
||||
|
||||
constructor(selector, elements, manager) {
|
||||
this.el = elements;
|
||||
this.manager = manager;
|
||||
|
||||
this.group = new FormFieldGroup({
|
||||
baseSelector: '.ppcp-axo-payment-container',
|
||||
contentSelector: selector,
|
||||
template: (data) => {
|
||||
const selectOtherPaymentMethod = () => {
|
||||
if (!this.manager.hideGatewaySelection) {
|
||||
return '';
|
||||
}
|
||||
return `<p style="margin-top: 40px; text-align: center;"><a href="javascript:void(0)" ${this.el.showGatewaySelectionLink.attributes}>Select other payment method</a></p>`;
|
||||
};
|
||||
|
||||
if (data.isEmpty()) {
|
||||
return `
|
||||
<div style="margin-bottom: 20px; text-align: center;">
|
||||
<div style="border:2px solid #cccccc; border-radius: 10px; padding: 26px 20px; margin-bottom: 20px; background-color:#f6f6f6">
|
||||
<div>Please fill in your card details.</div>
|
||||
</div>
|
||||
<h4><a href="javascript:void(0)" ${this.el.changeCardLink.attributes}>Add card details</a></h4>
|
||||
${selectOtherPaymentMethod()}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
const expiry = data.value('expiry').split('-');
|
||||
|
||||
const cardIcons = {
|
||||
'VISA': 'visa-dark.svg',
|
||||
'MASTER_CARD': 'mastercard-dark.svg',
|
||||
'AMEX': 'amex.svg',
|
||||
'DISCOVER': 'discover.svg',
|
||||
};
|
||||
|
||||
return `
|
||||
<div style="margin-bottom: 20px;">
|
||||
<div class="axo-checkout-header-section">
|
||||
<h3>Card Details</h3>
|
||||
<a href="javascript:void(0)" ${this.el.changeCardLink.attributes}>Edit</a>
|
||||
</div>
|
||||
<div style="border:2px solid #cccccc; border-radius: 10px; padding: 16px 20px; background-color:#f6f6f6">
|
||||
<div style="float: right;">
|
||||
<img
|
||||
class="ppcp-card-icon"
|
||||
title="${data.value('brand')}"
|
||||
src="/wp-content/plugins/woocommerce-paypal-payments/modules/ppcp-wc-gateway/assets/images/${cardIcons[data.value('brand')]}"
|
||||
alt="${data.value('brand')}"
|
||||
>
|
||||
</div>
|
||||
<div style="font-family: monospace; font-size: 1rem; margin-top: 10px;">${data.value('lastDigits') ? '**** **** **** ' + data.value('lastDigits'): ''}</div>
|
||||
<div>${expiry[1]}/${expiry[0]}</div>
|
||||
<div style="text-transform: uppercase">${data.value('name')}</div>
|
||||
</div>
|
||||
${selectOtherPaymentMethod()}
|
||||
</div>
|
||||
`;
|
||||
},
|
||||
fields: {
|
||||
brand: {
|
||||
'valuePath': 'card.paymentSource.card.brand',
|
||||
},
|
||||
expiry: {
|
||||
'valuePath': 'card.paymentSource.card.expiry',
|
||||
},
|
||||
lastDigits: {
|
||||
'valuePath': 'card.paymentSource.card.lastDigits',
|
||||
},
|
||||
name: {
|
||||
'valuePath': 'card.paymentSource.card.name',
|
||||
},
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
activate() {
|
||||
this.group.activate();
|
||||
}
|
||||
|
||||
deactivate() {
|
||||
this.group.deactivate();
|
||||
}
|
||||
|
||||
refresh() {
|
||||
this.group.refresh();
|
||||
}
|
||||
|
||||
setData(data) {
|
||||
this.group.setData(data);
|
||||
}
|
||||
|
||||
toSubmitData(data) {
|
||||
const name = this.group.dataValue('name');
|
||||
const { firstName, lastName } = this.splitName(name);
|
||||
|
||||
data['billing_first_name'] = firstName;
|
||||
data['billing_last_name'] = lastName ? lastName : firstName;
|
||||
|
||||
return this.group.toSubmitData(data);
|
||||
}
|
||||
|
||||
splitName(fullName) {
|
||||
let nameParts = fullName.trim().split(' ');
|
||||
let firstName = nameParts[0];
|
||||
let lastName = nameParts.length > 1 ? nameParts[nameParts.length - 1] : '';
|
||||
|
||||
return { firstName, lastName };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default CardView;
|
143
modules/ppcp-axo/resources/js/Views/ShippingView.js
Normal file
143
modules/ppcp-axo/resources/js/Views/ShippingView.js
Normal file
|
@ -0,0 +1,143 @@
|
|||
import FormFieldGroup from "../Components/FormFieldGroup";
|
||||
|
||||
class ShippingView {
|
||||
|
||||
constructor(selector, elements) {
|
||||
this.el = elements;
|
||||
|
||||
this.group = new FormFieldGroup({
|
||||
baseSelector: '.woocommerce-checkout',
|
||||
contentSelector: selector,
|
||||
template: (data) => {
|
||||
const valueOfSelect = (selectSelector, key) => {
|
||||
if (!key) {
|
||||
return '';
|
||||
}
|
||||
const selectElement = document.querySelector(selectSelector);
|
||||
|
||||
if (!selectElement) {
|
||||
return key;
|
||||
}
|
||||
|
||||
const option = selectElement.querySelector(`option[value="${key}"]`);
|
||||
return option ? option.textContent : key;
|
||||
}
|
||||
|
||||
if (data.isEmpty()) {
|
||||
return `
|
||||
<div style="margin-bottom: 20px;">
|
||||
<div class="axo-checkout-header-section">
|
||||
<h3>Shipping</h3>
|
||||
<a href="javascript:void(0)" ${this.el.changeShippingAddressLink.attributes}>Edit</a>
|
||||
</div>
|
||||
<div>Please fill in your shipping details.</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
return `
|
||||
<div style="margin-bottom: 20px;">
|
||||
<div class="axo-checkout-header-section">
|
||||
<h3>Shipping</h3>
|
||||
<a href="javascript:void(0)" ${this.el.changeShippingAddressLink.attributes}>Edit</a>
|
||||
</div>
|
||||
<div>${data.value('email')}</div>
|
||||
<div>${data.value('company')}</div>
|
||||
<div>${data.value('firstName')} ${data.value('lastName')}</div>
|
||||
<div>${data.value('street1')}</div>
|
||||
<div>${data.value('street2')}</div>
|
||||
<div>${data.value('city')}, ${valueOfSelect('#billing_state', data.value('stateCode'))} ${data.value('postCode')} </div>
|
||||
<div>${valueOfSelect('#billing_country', data.value('countryCode'))}</div>
|
||||
<div>${data.value('phone')}</div>
|
||||
</div>
|
||||
`;
|
||||
},
|
||||
fields: {
|
||||
email: {
|
||||
'valuePath': 'email',
|
||||
},
|
||||
firstName: {
|
||||
'key': 'firstName',
|
||||
'selector': '#shipping_first_name_field',
|
||||
'valuePath': 'shipping.name.firstName',
|
||||
},
|
||||
lastName: {
|
||||
'selector': '#shipping_last_name_field',
|
||||
'valuePath': 'shipping.name.lastName',
|
||||
},
|
||||
street1: {
|
||||
'selector': '#shipping_address_1_field',
|
||||
'valuePath': 'shipping.address.addressLine1',
|
||||
},
|
||||
street2: {
|
||||
'selector': '#shipping_address_2_field',
|
||||
'valuePath': null
|
||||
},
|
||||
postCode: {
|
||||
'selector': '#shipping_postcode_field',
|
||||
'valuePath': 'shipping.address.postalCode',
|
||||
},
|
||||
city: {
|
||||
'selector': '#shipping_city_field',
|
||||
'valuePath': 'shipping.address.adminArea2',
|
||||
},
|
||||
stateCode: {
|
||||
'selector': '#shipping_state_field',
|
||||
'valuePath': 'shipping.address.adminArea1',
|
||||
},
|
||||
countryCode: {
|
||||
'selector': '#shipping_country_field',
|
||||
'valuePath': 'shipping.address.countryCode',
|
||||
},
|
||||
company: {
|
||||
'selector': '#shipping_company_field',
|
||||
'valuePath': null,
|
||||
},
|
||||
shipDifferentAddress: {
|
||||
'selector': '#ship-to-different-address',
|
||||
'valuePath': null,
|
||||
},
|
||||
phone: {
|
||||
//'selector': '#billing_phone_field', // There is no shipping phone field.
|
||||
'valueCallback': function (data) {
|
||||
let phone = '';
|
||||
const cc = data?.shipping?.phoneNumber?.countryCode;
|
||||
const number = data?.shipping?.phoneNumber?.nationalNumber;
|
||||
|
||||
if (cc) {
|
||||
phone = `+${cc} `;
|
||||
}
|
||||
phone += number;
|
||||
return phone;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
isActive() {
|
||||
return this.group.active;
|
||||
}
|
||||
|
||||
activate() {
|
||||
this.group.activate();
|
||||
}
|
||||
|
||||
deactivate() {
|
||||
this.group.deactivate();
|
||||
}
|
||||
|
||||
refresh() {
|
||||
this.group.refresh();
|
||||
}
|
||||
|
||||
setData(data) {
|
||||
this.group.setData(data);
|
||||
}
|
||||
|
||||
toSubmitData(data) {
|
||||
return this.group.toSubmitData(data);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ShippingView;
|
33
modules/ppcp-axo/resources/js/boot.js
Normal file
33
modules/ppcp-axo/resources/js/boot.js
Normal file
|
@ -0,0 +1,33 @@
|
|||
import AxoManager from "./AxoManager";
|
||||
import {loadPaypalScript} from "../../../ppcp-button/resources/js/modules/Helper/ScriptLoading";
|
||||
|
||||
(function ({
|
||||
axoConfig,
|
||||
ppcpConfig,
|
||||
jQuery
|
||||
}) {
|
||||
|
||||
const bootstrap = () => {
|
||||
new AxoManager(axoConfig, ppcpConfig);
|
||||
}
|
||||
|
||||
document.addEventListener(
|
||||
'DOMContentLoaded',
|
||||
() => {
|
||||
if (!typeof (PayPalCommerceGateway)) {
|
||||
console.error('AXO could not be configured.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Load PayPal
|
||||
loadPaypalScript(ppcpConfig, () => {
|
||||
bootstrap();
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
})({
|
||||
axoConfig: window.wc_ppcp_axo,
|
||||
ppcpConfig: window.PayPalCommerceGateway,
|
||||
jQuery: window.jQuery
|
||||
});
|
148
modules/ppcp-axo/services.php
Normal file
148
modules/ppcp-axo/services.php
Normal file
|
@ -0,0 +1,148 @@
|
|||
<?php
|
||||
/**
|
||||
* The Axo module services.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Axo
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Axo;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Axo\Assets\AxoManager;
|
||||
use WooCommerce\PayPalCommerce\Axo\Gateway\AxoGateway;
|
||||
use WooCommerce\PayPalCommerce\Axo\Helper\ApmApplies;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
|
||||
return array(
|
||||
|
||||
// If AXO can be configured.
|
||||
'axo.eligible' => static function ( ContainerInterface $container ): bool {
|
||||
$apm_applies = $container->get( 'axo.helpers.apm-applies' );
|
||||
assert( $apm_applies instanceof ApmApplies );
|
||||
|
||||
return $apm_applies->for_country_currency() && $apm_applies->for_settings();
|
||||
},
|
||||
|
||||
'axo.helpers.apm-applies' => static function ( ContainerInterface $container ) : ApmApplies {
|
||||
return new ApmApplies(
|
||||
$container->get( 'axo.supported-country-currency-matrix' ),
|
||||
$container->get( 'api.shop.currency' ),
|
||||
$container->get( 'api.shop.country' )
|
||||
);
|
||||
},
|
||||
|
||||
// If AXO is configured and onboarded.
|
||||
'axo.available' => static function ( ContainerInterface $container ): bool {
|
||||
return true;
|
||||
},
|
||||
|
||||
'axo.url' => static function ( ContainerInterface $container ): string {
|
||||
$path = realpath( __FILE__ );
|
||||
if ( false === $path ) {
|
||||
return '';
|
||||
}
|
||||
return plugins_url(
|
||||
'/modules/ppcp-axo/',
|
||||
dirname( $path, 3 ) . '/woocommerce-paypal-payments.php'
|
||||
);
|
||||
},
|
||||
|
||||
'axo.manager' => static function ( ContainerInterface $container ): AxoManager {
|
||||
return new AxoManager(
|
||||
$container->get( 'axo.url' ),
|
||||
$container->get( 'ppcp.asset-version' ),
|
||||
$container->get( 'session.handler' ),
|
||||
$container->get( 'wcgateway.settings' ),
|
||||
$container->get( 'onboarding.environment' ),
|
||||
$container->get( 'wcgateway.settings.status' ),
|
||||
$container->get( 'api.shop.currency' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
|
||||
'axo.gateway' => static function ( ContainerInterface $container ): AxoGateway {
|
||||
return new AxoGateway(
|
||||
$container->get( 'wcgateway.settings.render' ),
|
||||
$container->get( 'wcgateway.settings' ),
|
||||
$container->get( 'wcgateway.url' ),
|
||||
$container->get( 'wcgateway.order-processor' ),
|
||||
$container->get( 'axo.card_icons' ),
|
||||
$container->get( 'axo.card_icons.axo' ),
|
||||
$container->get( 'api.endpoint.order' ),
|
||||
$container->get( 'api.factory.purchase-unit' ),
|
||||
$container->get( 'api.factory.shipping-preference' ),
|
||||
$container->get( 'wcgateway.transaction-url-provider' ),
|
||||
$container->get( 'onboarding.environment' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
|
||||
'axo.card_icons' => static function ( ContainerInterface $container ): array {
|
||||
return array(
|
||||
array(
|
||||
'title' => 'Visa',
|
||||
'file' => 'visa-dark.svg',
|
||||
),
|
||||
array(
|
||||
'title' => 'MasterCard',
|
||||
'file' => 'mastercard-dark.svg',
|
||||
),
|
||||
array(
|
||||
'title' => 'American Express',
|
||||
'file' => 'amex.svg',
|
||||
),
|
||||
array(
|
||||
'title' => 'Discover',
|
||||
'file' => 'discover.svg',
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
'axo.card_icons.axo' => static function ( ContainerInterface $container ): array {
|
||||
return array(
|
||||
array(
|
||||
'title' => 'Dinersclub',
|
||||
'file' => 'dinersclub-light.svg',
|
||||
),
|
||||
array(
|
||||
'title' => 'Discover',
|
||||
'file' => 'discover-light.svg',
|
||||
),
|
||||
array(
|
||||
'title' => 'JCB',
|
||||
'file' => 'jcb-light.svg',
|
||||
),
|
||||
array(
|
||||
'title' => 'MasterCard',
|
||||
'file' => 'mastercard-light.svg',
|
||||
),
|
||||
array(
|
||||
'title' => 'UnionPay',
|
||||
'file' => 'unionpay-light.svg',
|
||||
),
|
||||
array(
|
||||
'title' => 'Visa',
|
||||
'file' => 'visa-light.svg',
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* The matrix which countries and currency combinations can be used for AXO.
|
||||
*/
|
||||
'axo.supported-country-currency-matrix' => static function ( ContainerInterface $container ) : array {
|
||||
/**
|
||||
* Returns which countries and currency combinations can be used for AXO.
|
||||
*/
|
||||
return apply_filters(
|
||||
'woocommerce_paypal_payments_axo_supported_country_currency_matrix',
|
||||
array(
|
||||
'US' => array(
|
||||
'USD',
|
||||
),
|
||||
)
|
||||
);
|
||||
},
|
||||
|
||||
);
|
230
modules/ppcp-axo/src/Assets/AxoManager.php
Normal file
230
modules/ppcp-axo/src/Assets/AxoManager.php
Normal file
|
@ -0,0 +1,230 @@
|
|||
<?php
|
||||
/**
|
||||
* The AXO AxoManager
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\WcGateway\Assets
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Axo\Assets;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Helper\SettingsStatus;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
|
||||
/**
|
||||
* Class AxoManager.
|
||||
*
|
||||
* @param string $module_url The URL to the module.
|
||||
*/
|
||||
class AxoManager {
|
||||
|
||||
/**
|
||||
* The URL to the module.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $module_url;
|
||||
|
||||
/**
|
||||
* The assets version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $version;
|
||||
|
||||
/**
|
||||
* The settings.
|
||||
*
|
||||
* @var Settings
|
||||
*/
|
||||
private $settings;
|
||||
|
||||
/**
|
||||
* The environment object.
|
||||
*
|
||||
* @var Environment
|
||||
*/
|
||||
private $environment;
|
||||
|
||||
/**
|
||||
* The Settings status helper.
|
||||
*
|
||||
* @var SettingsStatus
|
||||
*/
|
||||
private $settings_status;
|
||||
|
||||
/**
|
||||
* 3-letter currency code of the shop.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $currency;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* Session handler.
|
||||
*
|
||||
* @var SessionHandler
|
||||
*/
|
||||
private $session_handler;
|
||||
|
||||
/**
|
||||
* AxoManager constructor.
|
||||
*
|
||||
* @param string $module_url The URL to the module.
|
||||
* @param string $version The assets version.
|
||||
* @param SessionHandler $session_handler The Session handler.
|
||||
* @param Settings $settings The Settings.
|
||||
* @param Environment $environment The environment object.
|
||||
* @param SettingsStatus $settings_status The Settings status helper.
|
||||
* @param string $currency 3-letter currency code of the shop.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
public function __construct(
|
||||
string $module_url,
|
||||
string $version,
|
||||
SessionHandler $session_handler,
|
||||
Settings $settings,
|
||||
Environment $environment,
|
||||
SettingsStatus $settings_status,
|
||||
string $currency,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
|
||||
$this->module_url = $module_url;
|
||||
$this->version = $version;
|
||||
$this->session_handler = $session_handler;
|
||||
$this->settings = $settings;
|
||||
$this->environment = $environment;
|
||||
$this->settings_status = $settings_status;
|
||||
$this->currency = $currency;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues scripts/styles.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function enqueue() {
|
||||
|
||||
// Register styles.
|
||||
wp_register_style(
|
||||
'wc-ppcp-axo',
|
||||
untrailingslashit( $this->module_url ) . '/assets/css/styles.css',
|
||||
array(),
|
||||
$this->version
|
||||
);
|
||||
wp_enqueue_style( 'wc-ppcp-axo' );
|
||||
|
||||
// Register scripts.
|
||||
wp_register_script(
|
||||
'wc-ppcp-axo',
|
||||
untrailingslashit( $this->module_url ) . '/assets/js/boot.js',
|
||||
array(),
|
||||
$this->version,
|
||||
true
|
||||
);
|
||||
wp_enqueue_script( 'wc-ppcp-axo' );
|
||||
|
||||
wp_localize_script(
|
||||
'wc-ppcp-axo',
|
||||
'wc_ppcp_axo',
|
||||
$this->script_data()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The configuration for AXO.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function script_data() {
|
||||
return array(
|
||||
'environment' => array(
|
||||
'is_sandbox' => $this->environment->current_environment() === 'sandbox',
|
||||
),
|
||||
'widgets' => array(
|
||||
'email' => 'render',
|
||||
),
|
||||
'insights' => array(
|
||||
'enabled' => true,
|
||||
'client_id' => ( $this->settings->has( 'client_id' ) ? $this->settings->get( 'client_id' ) : null ),
|
||||
'session_id' =>
|
||||
substr(
|
||||
method_exists( WC()->session, 'get_customer_unique_id' ) ? md5( WC()->session->get_customer_unique_id() ) : '',
|
||||
0,
|
||||
16
|
||||
),
|
||||
'amount' => array(
|
||||
'currency_code' => get_woocommerce_currency(),
|
||||
'value' => WC()->cart->get_total( 'numeric' ),
|
||||
),
|
||||
),
|
||||
'style_options' => array(
|
||||
'root' => array(
|
||||
'backgroundColor' => $this->settings->has( 'axo_style_root_bg_color' ) ? $this->settings->get( 'axo_style_root_bg_color' ) : '',
|
||||
'errorColor' => $this->settings->has( 'axo_style_root_error_color' ) ? $this->settings->get( 'axo_style_root_error_color' ) : '',
|
||||
'fontFamily' => $this->settings->has( 'axo_style_root_font_family' ) ? $this->settings->get( 'axo_style_root_font_family' ) : '',
|
||||
'textColorBase' => $this->settings->has( 'axo_style_root_text_color_base' ) ? $this->settings->get( 'axo_style_root_text_color_base' ) : '',
|
||||
'fontSizeBase' => $this->settings->has( 'axo_style_root_font_size_base' ) ? $this->settings->get( 'axo_style_root_font_size_base' ) : '',
|
||||
'padding' => $this->settings->has( 'axo_style_root_padding' ) ? $this->settings->get( 'axo_style_root_padding' ) : '',
|
||||
'primaryColor' => $this->settings->has( 'axo_style_root_primary_color' ) ? $this->settings->get( 'axo_style_root_primary_color' ) : '',
|
||||
),
|
||||
'input' => array(
|
||||
'backgroundColor' => $this->settings->has( 'axo_style_input_bg_color' ) ? $this->settings->get( 'axo_style_input_bg_color' ) : '',
|
||||
'borderRadius' => $this->settings->has( 'axo_style_input_border_radius' ) ? $this->settings->get( 'axo_style_input_border_radius' ) : '',
|
||||
'borderColor' => $this->settings->has( 'axo_style_input_border_color' ) ? $this->settings->get( 'axo_style_input_border_color' ) : '',
|
||||
'borderWidth' => $this->settings->has( 'axo_style_input_border_width' ) ? $this->settings->get( 'axo_style_input_border_width' ) : '',
|
||||
'textColorBase' => $this->settings->has( 'axo_style_input_text_color_base' ) ? $this->settings->get( 'axo_style_input_text_color_base' ) : '',
|
||||
'focusBorderColor' => $this->settings->has( 'axo_style_input_focus_border_color' ) ? $this->settings->get( 'axo_style_input_focus_border_color' ) : '',
|
||||
),
|
||||
),
|
||||
'name_on_card' => $this->settings->has( 'axo_name_on_card' ) ? $this->settings->get( 'axo_name_on_card' ) : '',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the action name that PayPal AXO button will use for rendering on the checkout page.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function checkout_button_renderer_hook(): string {
|
||||
/**
|
||||
* The filter returning the action name that PayPal AXO button will use for rendering on the checkout page.
|
||||
*/
|
||||
return (string) apply_filters( 'woocommerce_paypal_payments_checkout_axo_renderer_hook', 'woocommerce_review_order_after_submit' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the HTML for the AXO submit button.
|
||||
*/
|
||||
public function render_checkout_button(): void {
|
||||
$id = 'ppcp-axo-submit-button-container';
|
||||
|
||||
/**
|
||||
* The WC filter returning the WC order button text.
|
||||
* phpcs:disable WordPress.WP.I18n.TextDomainMismatch
|
||||
*/
|
||||
$label = apply_filters( 'woocommerce_order_button_text', __( 'Place order', 'woocommerce' ) );
|
||||
|
||||
printf(
|
||||
'<div id="%1$s" style="display: none;">
|
||||
<button type="button" class="button alt ppcp-axo-order-button">%2$s</button>
|
||||
</div>',
|
||||
esc_attr( $id ),
|
||||
esc_html( $label )
|
||||
);
|
||||
}
|
||||
|
||||
}
|
269
modules/ppcp-axo/src/AxoModule.php
Normal file
269
modules/ppcp-axo/src/AxoModule.php
Normal file
|
@ -0,0 +1,269 @@
|
|||
<?php
|
||||
/**
|
||||
* The Axo module.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Axo
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Axo;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Authentication\SdkClientToken;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\Axo\Assets\AxoManager;
|
||||
use WooCommerce\PayPalCommerce\Button\Assets\SmartButtonInterface;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingOptionsRenderer;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
|
||||
/**
|
||||
* Class AxoModule
|
||||
*/
|
||||
class AxoModule implements ModuleInterface {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function setup(): ServiceProviderInterface {
|
||||
return new ServiceProvider(
|
||||
require __DIR__ . '/../services.php',
|
||||
require __DIR__ . '/../extensions.php'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function run( ContainerInterface $c ): void {
|
||||
$module = $this;
|
||||
|
||||
add_filter(
|
||||
'woocommerce_payment_gateways',
|
||||
/**
|
||||
* Param types removed to avoid third-party issues.
|
||||
*
|
||||
* @psalm-suppress MissingClosureParamType
|
||||
*/
|
||||
function ( $methods ) use ( $c ): array {
|
||||
if ( ! is_array( $methods ) ) {
|
||||
return $methods;
|
||||
}
|
||||
|
||||
$gateway = $c->get( 'axo.gateway' );
|
||||
|
||||
// Check if the module is applicable, correct country, currency, ... etc.
|
||||
if ( ! $c->get( 'axo.eligible' ) ) {
|
||||
return $methods;
|
||||
}
|
||||
|
||||
// Add the gateway in admin area.
|
||||
if ( is_admin() ) {
|
||||
$methods[] = $gateway;
|
||||
return $methods;
|
||||
}
|
||||
|
||||
if ( is_user_logged_in() ) {
|
||||
return $methods;
|
||||
}
|
||||
|
||||
$methods[] = $gateway;
|
||||
return $methods;
|
||||
},
|
||||
1,
|
||||
9
|
||||
);
|
||||
|
||||
// Hides credit card gateway on checkout when using Fastlane.
|
||||
add_filter(
|
||||
'woocommerce_available_payment_gateways',
|
||||
/**
|
||||
* Param types removed to avoid third-party issues.
|
||||
*
|
||||
* @psalm-suppress MissingClosureParamType
|
||||
*/
|
||||
function ( $methods ) use ( $c ): array {
|
||||
if ( ! is_array( $methods ) || ! $c->get( 'axo.eligible' ) ) {
|
||||
return $methods;
|
||||
}
|
||||
|
||||
$settings = $c->get( 'wcgateway.settings' );
|
||||
assert( $settings instanceof Settings );
|
||||
|
||||
if ( apply_filters(
|
||||
'woocommerce_paypal_payments_axo_hide_credit_card_gateway',
|
||||
$this->hide_credit_card_when_using_fastlane( $methods, $settings )
|
||||
) ) {
|
||||
unset( $methods[ CreditCardGateway::ID ] );
|
||||
}
|
||||
|
||||
return $methods;
|
||||
}
|
||||
);
|
||||
|
||||
add_action(
|
||||
'init',
|
||||
static function () use ( $c, $module ) {
|
||||
|
||||
// Check if the module is applicable, correct country, currency, ... etc.
|
||||
if ( ! $c->get( 'axo.eligible' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$manager = $c->get( 'axo.manager' );
|
||||
assert( $manager instanceof AxoManager );
|
||||
|
||||
// Enqueue frontend scripts.
|
||||
add_action(
|
||||
'wp_enqueue_scripts',
|
||||
static function () use ( $c, $manager ) {
|
||||
$smart_button = $c->get( 'button.smart-button' );
|
||||
assert( $smart_button instanceof SmartButtonInterface );
|
||||
|
||||
if ( $smart_button->should_load_ppcp_script() ) {
|
||||
$manager->enqueue();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Render submit button.
|
||||
add_action(
|
||||
$manager->checkout_button_renderer_hook(),
|
||||
static function () use ( $c, $manager ) {
|
||||
$manager->render_checkout_button();
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Param types removed to avoid third-party issues.
|
||||
*
|
||||
* @psalm-suppress MissingClosureParamType
|
||||
*/
|
||||
add_filter(
|
||||
'woocommerce_paypal_payments_sdk_components_hook',
|
||||
function( $components ) {
|
||||
$components[] = 'fastlane';
|
||||
return $components;
|
||||
}
|
||||
);
|
||||
|
||||
add_action(
|
||||
'wp_head',
|
||||
function () {
|
||||
// phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript
|
||||
echo '<script async src="https://www.paypalobjects.com/insights/v1/paypal-insights.sandbox.min.js"></script>';
|
||||
}
|
||||
);
|
||||
|
||||
add_filter(
|
||||
'woocommerce_paypal_payments_localized_script_data',
|
||||
function( array $localized_script_data ) use ( $c, $module ) {
|
||||
$api = $c->get( 'api.sdk-client-token' );
|
||||
assert( $api instanceof SdkClientToken );
|
||||
|
||||
$logger = $c->get( 'woocommerce.logger.woocommerce' );
|
||||
assert( $logger instanceof LoggerInterface );
|
||||
|
||||
return $module->add_sdk_client_token_to_script_data( $api, $logger, $localized_script_data );
|
||||
}
|
||||
);
|
||||
|
||||
add_filter(
|
||||
'ppcp_onboarding_dcc_table_rows',
|
||||
/**
|
||||
* Param types removed to avoid third-party issues.
|
||||
*
|
||||
* @psalm-suppress MissingClosureParamType
|
||||
*/
|
||||
function ( $rows, $renderer ): array {
|
||||
if ( ! is_array( $rows ) ) {
|
||||
return $rows;
|
||||
}
|
||||
|
||||
if ( $renderer instanceof OnboardingOptionsRenderer ) {
|
||||
$rows[] = $renderer->render_table_row(
|
||||
__( 'Fastlane by PayPal', 'woocommerce-paypal-payments' ),
|
||||
__( 'Yes', 'woocommerce-paypal-payments' ),
|
||||
__( 'Help accelerate guest checkout with PayPal\'s autofill solution.', 'woocommerce-paypal-payments' )
|
||||
);
|
||||
}
|
||||
return $rows;
|
||||
},
|
||||
10,
|
||||
2
|
||||
);
|
||||
|
||||
},
|
||||
1
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds id token to localized script data.
|
||||
*
|
||||
* @param SdkClientToken $api User id token api.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
* @param array $localized_script_data The localized script data.
|
||||
* @return array
|
||||
*/
|
||||
private function add_sdk_client_token_to_script_data(
|
||||
SdkClientToken $api,
|
||||
LoggerInterface $logger,
|
||||
array $localized_script_data
|
||||
): array {
|
||||
try {
|
||||
$target_customer_id = '';
|
||||
if ( is_user_logged_in() ) {
|
||||
$target_customer_id = get_user_meta( get_current_user_id(), '_ppcp_target_customer_id', true );
|
||||
if ( ! $target_customer_id ) {
|
||||
$target_customer_id = get_user_meta( get_current_user_id(), 'ppcp_customer_id', true );
|
||||
}
|
||||
}
|
||||
|
||||
$sdk_client_token = $api->sdk_client_token( $target_customer_id );
|
||||
$localized_script_data['axo'] = array(
|
||||
'sdk_client_token' => $sdk_client_token,
|
||||
);
|
||||
|
||||
} catch ( RuntimeException $exception ) {
|
||||
$error = $exception->getMessage();
|
||||
if ( is_a( $exception, PayPalApiException::class ) ) {
|
||||
$error = $exception->get_details( $error );
|
||||
}
|
||||
|
||||
$logger->error( $error );
|
||||
}
|
||||
|
||||
return $localized_script_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key for the module.
|
||||
*
|
||||
* @return string|void
|
||||
*/
|
||||
public function getKey() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Condition to evaluate if Credit Card gateway should be hidden.
|
||||
*
|
||||
* @param array $methods WC payment methods.
|
||||
* @param Settings $settings The settings.
|
||||
* @return bool
|
||||
*/
|
||||
private function hide_credit_card_when_using_fastlane( array $methods, Settings $settings ): bool {
|
||||
$is_axo_enabled = $settings->has( 'axo_enabled' ) && $settings->get( 'axo_enabled' ) ?? false;
|
||||
|
||||
return ! is_admin()
|
||||
&& is_user_logged_in() === false
|
||||
&& isset( $methods[ CreditCardGateway::ID ] )
|
||||
&& $is_axo_enabled;
|
||||
}
|
||||
}
|
363
modules/ppcp-axo/src/Gateway/AxoGateway.php
Normal file
363
modules/ppcp-axo/src/Gateway/AxoGateway.php
Normal file
|
@ -0,0 +1,363 @@
|
|||
<?php
|
||||
/**
|
||||
* The AXO Gateway
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\WcGateway\Gateway
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Axo\Gateway;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WC_Order;
|
||||
use WC_Payment_Gateway;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\ApplicationContext;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\ShippingPreferenceFactory;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\GatewaySettingsRendererTrait;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\TransactionUrlProvider;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderMetaTrait;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderProcessor;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\SettingsRenderer;
|
||||
|
||||
/**
|
||||
* Class AXOGateway.
|
||||
*/
|
||||
class AxoGateway extends WC_Payment_Gateway {
|
||||
use OrderMetaTrait, GatewaySettingsRendererTrait;
|
||||
|
||||
const ID = 'ppcp-axo-gateway';
|
||||
|
||||
/**
|
||||
* The Settings Renderer.
|
||||
*
|
||||
* @var SettingsRenderer
|
||||
*/
|
||||
protected $settings_renderer;
|
||||
|
||||
/**
|
||||
* The settings.
|
||||
*
|
||||
* @var ContainerInterface
|
||||
*/
|
||||
protected $ppcp_settings;
|
||||
|
||||
/**
|
||||
* The WcGateway module URL.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $wcgateway_module_url;
|
||||
|
||||
/**
|
||||
* The processor for orders.
|
||||
*
|
||||
* @var OrderProcessor
|
||||
*/
|
||||
protected $order_processor;
|
||||
|
||||
/**
|
||||
* The card icons.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $card_icons;
|
||||
|
||||
/**
|
||||
* The AXO card icons.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $card_icons_axo;
|
||||
|
||||
/**
|
||||
* The order endpoint.
|
||||
*
|
||||
* @var OrderEndpoint
|
||||
*/
|
||||
protected $order_endpoint;
|
||||
|
||||
/**
|
||||
* The purchase unit factory.
|
||||
*
|
||||
* @var PurchaseUnitFactory
|
||||
*/
|
||||
protected $purchase_unit_factory;
|
||||
|
||||
/**
|
||||
* The shipping preference factory.
|
||||
*
|
||||
* @var ShippingPreferenceFactory
|
||||
*/
|
||||
protected $shipping_preference_factory;
|
||||
|
||||
/**
|
||||
* The transaction url provider.
|
||||
*
|
||||
* @var TransactionUrlProvider
|
||||
*/
|
||||
protected $transaction_url_provider;
|
||||
|
||||
/**
|
||||
* The environment.
|
||||
*
|
||||
* @var Environment
|
||||
*/
|
||||
protected $environment;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* AXOGateway constructor.
|
||||
*
|
||||
* @param SettingsRenderer $settings_renderer The settings renderer.
|
||||
* @param ContainerInterface $ppcp_settings The settings.
|
||||
* @param string $wcgateway_module_url The WcGateway module URL.
|
||||
* @param OrderProcessor $order_processor The Order processor.
|
||||
* @param array $card_icons The card icons.
|
||||
* @param array $card_icons_axo The card icons.
|
||||
* @param OrderEndpoint $order_endpoint The order endpoint.
|
||||
* @param PurchaseUnitFactory $purchase_unit_factory The purchase unit factory.
|
||||
* @param ShippingPreferenceFactory $shipping_preference_factory The shipping preference factory.
|
||||
* @param TransactionUrlProvider $transaction_url_provider The transaction url provider.
|
||||
* @param Environment $environment The environment.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
public function __construct(
|
||||
SettingsRenderer $settings_renderer,
|
||||
ContainerInterface $ppcp_settings,
|
||||
string $wcgateway_module_url,
|
||||
OrderProcessor $order_processor,
|
||||
array $card_icons,
|
||||
array $card_icons_axo,
|
||||
OrderEndpoint $order_endpoint,
|
||||
PurchaseUnitFactory $purchase_unit_factory,
|
||||
ShippingPreferenceFactory $shipping_preference_factory,
|
||||
TransactionUrlProvider $transaction_url_provider,
|
||||
Environment $environment,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
$this->id = self::ID;
|
||||
|
||||
$this->settings_renderer = $settings_renderer;
|
||||
$this->ppcp_settings = $ppcp_settings;
|
||||
$this->wcgateway_module_url = $wcgateway_module_url;
|
||||
$this->order_processor = $order_processor;
|
||||
$this->card_icons = $card_icons;
|
||||
$this->card_icons_axo = $card_icons_axo;
|
||||
|
||||
$this->method_title = __( 'Fastlane Debit & Credit Cards', 'woocommerce-paypal-payments' );
|
||||
$this->method_description = __( 'PayPal Fastlane offers an accelerated checkout experience that recognizes guest shoppers and autofills their details so they can pay in seconds.', 'woocommerce-paypal-payments' );
|
||||
|
||||
$is_axo_enabled = $this->ppcp_settings->has( 'axo_enabled' ) && $this->ppcp_settings->get( 'axo_enabled' );
|
||||
$this->update_option( 'enabled', $is_axo_enabled ? 'yes' : 'no' );
|
||||
|
||||
$this->title = $this->ppcp_settings->has( 'axo_gateway_title' )
|
||||
? $this->ppcp_settings->get( 'axo_gateway_title' )
|
||||
: $this->get_option( 'title', $this->method_title );
|
||||
|
||||
$this->description = $this->get_option( 'description', '' );
|
||||
|
||||
$this->init_form_fields();
|
||||
$this->init_settings();
|
||||
|
||||
add_action(
|
||||
'woocommerce_update_options_payment_gateways_' . $this->id,
|
||||
array(
|
||||
$this,
|
||||
'process_admin_options',
|
||||
)
|
||||
);
|
||||
|
||||
$this->order_endpoint = $order_endpoint;
|
||||
$this->purchase_unit_factory = $purchase_unit_factory;
|
||||
$this->shipping_preference_factory = $shipping_preference_factory;
|
||||
$this->logger = $logger;
|
||||
|
||||
$this->transaction_url_provider = $transaction_url_provider;
|
||||
$this->environment = $environment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the form fields.
|
||||
*/
|
||||
public function init_form_fields() {
|
||||
$this->form_fields = array(
|
||||
'enabled' => array(
|
||||
'title' => __( 'Enable/Disable', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'checkbox',
|
||||
'label' => __( 'AXO', 'woocommerce-paypal-payments' ),
|
||||
'default' => 'no',
|
||||
'desc_tip' => true,
|
||||
'description' => __( 'Enable/Disable AXO payment gateway.', 'woocommerce-paypal-payments' ),
|
||||
),
|
||||
'ppcp' => array(
|
||||
'type' => 'ppcp',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the order.
|
||||
*
|
||||
* @param int $order_id The WC order ID.
|
||||
* @return array
|
||||
*/
|
||||
public function process_payment( $order_id ) {
|
||||
$wc_order = wc_get_order( $order_id );
|
||||
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
$fastlane_member = wc_clean( wp_unslash( $_POST['fastlane_member'] ?? '' ) );
|
||||
if ( $fastlane_member ) {
|
||||
$payment_method_title = __( 'Debit & Credit Cards (via Fastlane by PayPal)', 'woocommerce-paypal-payments' );
|
||||
$wc_order->set_payment_method_title( $payment_method_title );
|
||||
$wc_order->save();
|
||||
}
|
||||
|
||||
$purchase_unit = $this->purchase_unit_factory->from_wc_order( $wc_order );
|
||||
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
$nonce = wc_clean( wp_unslash( $_POST['axo_nonce'] ?? '' ) );
|
||||
|
||||
try {
|
||||
$shipping_preference = $this->shipping_preference_factory->from_state(
|
||||
$purchase_unit,
|
||||
'checkout'
|
||||
);
|
||||
|
||||
$payment_source_properties = new \stdClass();
|
||||
$payment_source_properties->single_use_token = $nonce;
|
||||
|
||||
$payment_source = new PaymentSource(
|
||||
'card',
|
||||
$payment_source_properties
|
||||
);
|
||||
|
||||
$order = $this->order_endpoint->create(
|
||||
array( $purchase_unit ),
|
||||
$shipping_preference,
|
||||
null,
|
||||
null,
|
||||
'',
|
||||
ApplicationContext::USER_ACTION_CONTINUE,
|
||||
'',
|
||||
array(),
|
||||
$payment_source
|
||||
);
|
||||
|
||||
$this->order_processor->process_captured_and_authorized( $wc_order, $order );
|
||||
|
||||
} catch ( RuntimeException $exception ) {
|
||||
$error = $exception->getMessage();
|
||||
if ( is_a( $exception, PayPalApiException::class ) ) {
|
||||
$error = $exception->get_details( $error );
|
||||
}
|
||||
|
||||
$this->logger->error( $error );
|
||||
wc_add_notice( $error, 'error' );
|
||||
|
||||
$wc_order->update_status(
|
||||
'failed',
|
||||
$error
|
||||
);
|
||||
|
||||
return array(
|
||||
'result' => 'failure',
|
||||
'redirect' => wc_get_checkout_url(),
|
||||
);
|
||||
}
|
||||
|
||||
WC()->cart->empty_cart();
|
||||
|
||||
$result = array(
|
||||
'result' => 'success',
|
||||
'redirect' => $this->get_return_url( $wc_order ),
|
||||
);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the icons of the gateway.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_icon() {
|
||||
$icon = parent::get_icon();
|
||||
$icons = $this->card_icons;
|
||||
$icons_src = esc_url( $this->wcgateway_module_url ) . 'assets/images/';
|
||||
|
||||
if ( empty( $this->card_icons ) ) {
|
||||
return $icon;
|
||||
}
|
||||
|
||||
$images = array();
|
||||
|
||||
foreach ( $icons as $card ) {
|
||||
$images[] = '<img
|
||||
class="ppcp-card-icon"
|
||||
title="' . $card['title'] . '"
|
||||
src="' . $icons_src . $card['file'] . '"
|
||||
> ';
|
||||
}
|
||||
|
||||
return implode( '', $images );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return transaction url for this gateway and given order.
|
||||
*
|
||||
* @param WC_Order $order WC order to get transaction url by.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_transaction_url( $order ): string {
|
||||
$this->view_transaction_url = $this->transaction_url_provider->get_transaction_url_base( $order );
|
||||
|
||||
return parent::get_transaction_url( $order );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the gateway's title.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_title() {
|
||||
if ( is_admin() ) {
|
||||
// $theorder and other things for retrieving the order or post info are not available
|
||||
// in the constructor, so must do it here.
|
||||
global $theorder;
|
||||
if ( $theorder instanceof WC_Order ) {
|
||||
if ( $theorder->get_payment_method() === self::ID ) {
|
||||
$payment_method_title = $theorder->get_payment_method_title();
|
||||
if ( $payment_method_title ) {
|
||||
$this->title = $payment_method_title;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return parent::get_title();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the settings renderer.
|
||||
*
|
||||
* @return SettingsRenderer
|
||||
*/
|
||||
protected function settings_renderer(): SettingsRenderer {
|
||||
return $this->settings_renderer;
|
||||
}
|
||||
}
|
82
modules/ppcp-axo/src/Helper/ApmApplies.php
Normal file
82
modules/ppcp-axo/src/Helper/ApmApplies.php
Normal file
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
/**
|
||||
* ApmApplies helper.
|
||||
* Checks if AXO is available for a given country and currency.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Axo\Helper
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Axo\Helper;
|
||||
|
||||
/**
|
||||
* Class ApmApplies
|
||||
*/
|
||||
class ApmApplies {
|
||||
|
||||
/**
|
||||
* The matrix which countries and currency combinations can be used for AXO.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $allowed_country_currency_matrix;
|
||||
|
||||
/**
|
||||
* 3-letter currency code of the shop.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $currency;
|
||||
|
||||
/**
|
||||
* 2-letter country code of the shop.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $country;
|
||||
|
||||
/**
|
||||
* DccApplies constructor.
|
||||
*
|
||||
* @param array $allowed_country_currency_matrix The matrix which countries and currency combinations can be used for AXO.
|
||||
* @param string $currency 3-letter currency code of the shop.
|
||||
* @param string $country 2-letter country code of the shop.
|
||||
*/
|
||||
public function __construct(
|
||||
array $allowed_country_currency_matrix,
|
||||
string $currency,
|
||||
string $country
|
||||
) {
|
||||
$this->allowed_country_currency_matrix = $allowed_country_currency_matrix;
|
||||
$this->currency = $currency;
|
||||
$this->country = $country;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether AXO can be used in the current country and the current currency used.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function for_country_currency(): bool {
|
||||
if ( ! in_array( $this->country, array_keys( $this->allowed_country_currency_matrix ), true ) ) {
|
||||
return false;
|
||||
}
|
||||
return in_array( $this->currency, $this->allowed_country_currency_matrix[ $this->country ], true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the settings are compatible with AXO.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function for_settings(): bool {
|
||||
if ( get_option( 'woocommerce_ship_to_destination' ) === 'billing_only' ) { // Force shipping to the customer billing address.
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
29
modules/ppcp-axo/src/Helper/PropertiesDictionary.php
Normal file
29
modules/ppcp-axo/src/Helper/PropertiesDictionary.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
/**
|
||||
* Properties of the AXO module.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Axo\Helper
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Axo\Helper;
|
||||
|
||||
/**
|
||||
* Class PropertiesDictionary
|
||||
*/
|
||||
class PropertiesDictionary {
|
||||
|
||||
/**
|
||||
* Returns the list of possible privacy options.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function privacy_options(): array {
|
||||
return array(
|
||||
'yes' => __( 'Yes (Recommended)', 'woocommerce-paypal-payments' ),
|
||||
'no' => __( 'No', 'woocommerce-paypal-payments' ),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
39
modules/ppcp-axo/webpack.config.js
Normal file
39
modules/ppcp-axo/webpack.config.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
const path = require('path');
|
||||
const isProduction = process.env.NODE_ENV === 'production';
|
||||
|
||||
const DependencyExtractionWebpackPlugin = require( '@woocommerce/dependency-extraction-webpack-plugin' );
|
||||
|
||||
module.exports = {
|
||||
devtool: isProduction ? 'source-map' : 'eval-source-map',
|
||||
mode: isProduction ? 'production' : 'development',
|
||||
target: 'web',
|
||||
plugins: [ new DependencyExtractionWebpackPlugin() ],
|
||||
entry: {
|
||||
'boot': path.resolve('./resources/js/boot.js'),
|
||||
'styles': path.resolve('./resources/css/styles.scss')
|
||||
},
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'assets/'),
|
||||
filename: 'js/[name].js',
|
||||
},
|
||||
module: {
|
||||
rules: [{
|
||||
test: /\.js?$/,
|
||||
exclude: /node_modules/,
|
||||
loader: 'babel-loader',
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
exclude: /node_modules/,
|
||||
use: [
|
||||
{
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
name: 'css/[name].css',
|
||||
}
|
||||
},
|
||||
{loader:'sass-loader'}
|
||||
]
|
||||
}]
|
||||
}
|
||||
};
|
2213
modules/ppcp-axo/yarn.lock
Normal file
2213
modules/ppcp-axo/yarn.lock
Normal file
File diff suppressed because it is too large
Load diff
156
modules/ppcp-blocks/composer.lock
generated
Normal file
156
modules/ppcp-blocks/composer.lock
generated
Normal file
|
@ -0,0 +1,156 @@
|
|||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "30c5bd428bece98b555ddc0b2da044f3",
|
||||
"packages": [
|
||||
{
|
||||
"name": "container-interop/service-provider",
|
||||
"version": "v0.4.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/container-interop/service-provider.git",
|
||||
"reference": "e04441ca21ef03e10dce70b0af29269281eec6dc"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/container-interop/service-provider/zipball/e04441ca21ef03e10dce70b0af29269281eec6dc",
|
||||
"reference": "e04441ca21ef03e10dce70b0af29269281eec6dc",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"psr/container": "^1.0 || ^2.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Interop\\Container\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "Promoting container interoperability through standard service providers",
|
||||
"homepage": "https://github.com/container-interop/service-provider",
|
||||
"support": {
|
||||
"issues": "https://github.com/container-interop/service-provider/issues",
|
||||
"source": "https://github.com/container-interop/service-provider/tree/v0.4.1"
|
||||
},
|
||||
"time": "2023-12-14T14:50:12+00:00"
|
||||
},
|
||||
{
|
||||
"name": "dhii/module-interface",
|
||||
"version": "v0.3.0-alpha2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Dhii/module-interface.git",
|
||||
"reference": "0e39f167d7ed8990c82f5d2e6084159d1a502a5b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Dhii/module-interface/zipball/0e39f167d7ed8990c82f5d2e6084159d1a502a5b",
|
||||
"reference": "0e39f167d7ed8990c82f5d2e6084159d1a502a5b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"container-interop/service-provider": "^0.4",
|
||||
"php": "^7.1 | ^8.0",
|
||||
"psr/container": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7.0 | ^8.0 | ^9.0",
|
||||
"slevomat/coding-standard": "^6.0",
|
||||
"vimeo/psalm": "^3.11.7 | ^4.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-develop": "0.3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Dhii\\Modular\\Module\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Dhii Team",
|
||||
"email": "development@dhii.co"
|
||||
}
|
||||
],
|
||||
"description": "Interfaces for modules",
|
||||
"support": {
|
||||
"issues": "https://github.com/Dhii/module-interface/issues",
|
||||
"source": "https://github.com/Dhii/module-interface/tree/v0.3.0-alpha2"
|
||||
},
|
||||
"time": "2021-08-23T08:23:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/container",
|
||||
"version": "1.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/container.git",
|
||||
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea",
|
||||
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.4.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Container\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "https://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common Container Interface (PHP FIG PSR-11)",
|
||||
"homepage": "https://github.com/php-fig/container",
|
||||
"keywords": [
|
||||
"PSR-11",
|
||||
"container",
|
||||
"container-interface",
|
||||
"container-interop",
|
||||
"psr"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-fig/container/issues",
|
||||
"source": "https://github.com/php-fig/container/tree/1.1.2"
|
||||
},
|
||||
"time": "2021-11-05T16:50:12+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "dev",
|
||||
"stability-flags": [],
|
||||
"prefer-stable": true,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
"php": "^7.2 | ^8.0"
|
||||
},
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.3.0"
|
||||
}
|
|
@ -10,13 +10,16 @@
|
|||
"Edge >= 14"
|
||||
],
|
||||
"dependencies": {
|
||||
"core-js": "^3.25.0"
|
||||
"@paypal/react-paypal-js": "^8.2.0",
|
||||
"core-js": "^3.25.0",
|
||||
"react": "^17.0.0",
|
||||
"react-dom": "^17.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.19",
|
||||
"@babel/preset-env": "^7.19",
|
||||
"@babel/preset-react": "^7.18.6",
|
||||
"@woocommerce/dependency-extraction-webpack-plugin": "^2.2.0",
|
||||
"@woocommerce/dependency-extraction-webpack-plugin": "2.2.0",
|
||||
"babel-loader": "^8.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"file-loader": "^6.2.0",
|
||||
|
|
|
@ -16,6 +16,7 @@ import {
|
|||
import {
|
||||
loadPaypalScriptPromise
|
||||
} from '../../../ppcp-button/resources/js/modules/Helper/ScriptLoading'
|
||||
import { PayPalScriptProvider, PayPalButtons } from "@paypal/react-paypal-js";
|
||||
import {
|
||||
normalizeStyleForFundingSource
|
||||
} from '../../../ppcp-button/resources/js/modules/Helper/Style'
|
||||
|
@ -120,8 +121,13 @@ const PayPalComponent = ({
|
|||
};
|
||||
|
||||
const createSubscription = async (data, actions) => {
|
||||
let planId = config.scriptData.subscription_plan_id;
|
||||
if (config.scriptData.variable_paypal_subscription_variation_from_cart !== '') {
|
||||
planId = config.scriptData.variable_paypal_subscription_variation_from_cart;
|
||||
}
|
||||
|
||||
return actions.subscription.create({
|
||||
'plan_id': config.scriptData.subscription_plan_id
|
||||
'plan_id': planId
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -502,6 +508,27 @@ const PayPalComponent = ({
|
|||
);
|
||||
}
|
||||
|
||||
const BlockEditorPayPalComponent = () => {
|
||||
|
||||
const urlParams = {
|
||||
clientId: 'test',
|
||||
...config.scriptData.url_params,
|
||||
dataNamespace: 'ppcp-blocks-editor-paypal-buttons',
|
||||
components: 'buttons',
|
||||
}
|
||||
return (
|
||||
<PayPalScriptProvider
|
||||
options={urlParams}
|
||||
>
|
||||
<PayPalButtons
|
||||
onClick={(data, actions) => {
|
||||
return false;
|
||||
}}
|
||||
/>
|
||||
</PayPalScriptProvider>
|
||||
)
|
||||
}
|
||||
|
||||
const features = ['products'];
|
||||
let block_enabled = true;
|
||||
|
||||
|
@ -566,7 +593,7 @@ if (block_enabled) {
|
|||
name: config.id,
|
||||
label: <div dangerouslySetInnerHTML={{__html: config.title}}/>,
|
||||
content: <PayPalComponent isEditing={false}/>,
|
||||
edit: <PayPalComponent isEditing={true}/>,
|
||||
edit: <BlockEditorPayPalComponent />,
|
||||
ariaLabel: config.title,
|
||||
canMakePayment: () => {
|
||||
return true;
|
||||
|
@ -582,7 +609,7 @@ if (block_enabled) {
|
|||
paymentMethodId: config.id,
|
||||
label: <div dangerouslySetInnerHTML={{__html: config.title}}/>,
|
||||
content: <PayPalComponent isEditing={false} fundingSource={fundingSource}/>,
|
||||
edit: <PayPalComponent isEditing={true} fundingSource={fundingSource}/>,
|
||||
edit: <BlockEditorPayPalComponent />,
|
||||
ariaLabel: config.title,
|
||||
canMakePayment: async () => {
|
||||
if (!paypalScriptPromise) {
|
||||
|
|
|
@ -111,6 +111,13 @@ class BlocksModule implements ModuleInterface {
|
|||
}
|
||||
);
|
||||
|
||||
add_filter(
|
||||
'woocommerce_paypal_payments_sdk_components_hook',
|
||||
function( array $components ) {
|
||||
$components[] = 'buttons';
|
||||
return $components;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1005,6 +1005,28 @@
|
|||
"@jridgewell/resolve-uri" "3.1.0"
|
||||
"@jridgewell/sourcemap-codec" "1.4.14"
|
||||
|
||||
"@paypal/paypal-js@^8.0.4":
|
||||
version "8.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@paypal/paypal-js/-/paypal-js-8.0.4.tgz#abe9f40f519b1d2c306adddfbe733be03eb26ce5"
|
||||
integrity sha512-91g5fhRBHGEBoikDzQT6uBn3PzlJQ75g0c3MvqVJqN0XRm5kHa9wz+6+Uaq8QQuxRzz5C2x55Zg057CW6EuwpQ==
|
||||
dependencies:
|
||||
promise-polyfill "^8.3.0"
|
||||
|
||||
"@paypal/react-paypal-js@^8.2.0":
|
||||
version "8.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@paypal/react-paypal-js/-/react-paypal-js-8.2.0.tgz#4b1a142bbb68e62dca4a92da4a6b5568f54901f0"
|
||||
integrity sha512-SworUfu0BNNcqoh0O53Ke4MFpx2m3qJRu3hayXvlluEEXJpKqGSV5aaSGFhbsZqi8hnbsx/hZR7BQbmqsggiGQ==
|
||||
dependencies:
|
||||
"@paypal/paypal-js" "^8.0.4"
|
||||
"@paypal/sdk-constants" "^1.0.122"
|
||||
|
||||
"@paypal/sdk-constants@^1.0.122":
|
||||
version "1.0.145"
|
||||
resolved "https://registry.yarnpkg.com/@paypal/sdk-constants/-/sdk-constants-1.0.145.tgz#f373cd3b7cf0409c28e121629b8f1855faf2e77b"
|
||||
integrity sha512-2tclrVX3L44YRJ09H4kkqma/UeAjRJarwH5SyPip10O5S+2ByE1HiyspAJ6hIWSjMngFVqjNyUCnrGcuQA3ldg==
|
||||
dependencies:
|
||||
hi-base32 "^0.5.0"
|
||||
|
||||
"@types/eslint-scope@^3.7.3":
|
||||
version "3.7.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16"
|
||||
|
@ -1179,7 +1201,7 @@
|
|||
resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.7.0.tgz#e1993689ac42d2b16e9194376cfb6753f6254db1"
|
||||
integrity sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==
|
||||
|
||||
"@woocommerce/dependency-extraction-webpack-plugin@^2.2.0":
|
||||
"@woocommerce/dependency-extraction-webpack-plugin@2.2.0":
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@woocommerce/dependency-extraction-webpack-plugin/-/dependency-extraction-webpack-plugin-2.2.0.tgz#230d674a67585bc32e31bc28485bec99b41dbd1f"
|
||||
integrity sha512-0wDY3EIUwWrPm0KrWvt1cf2SZDSX7CzBXvv4TyCqWOPuVPvC/ajyY8kD1HTFI80q6/RHoxWf3BYCmhuBzPbe9A==
|
||||
|
@ -1599,6 +1621,11 @@ has@^1.0.3:
|
|||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
|
||||
hi-base32@^0.5.0:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/hi-base32/-/hi-base32-0.5.1.tgz#1279f2ddae2673219ea5870c2121d2a33132857e"
|
||||
integrity sha512-EmBBpvdYh/4XxsnUybsPag6VikPYnN30td+vQk+GI3qpahVEG9+gTkG0aXVxTjBqQ5T6ijbWIu77O+C5WFWsnA==
|
||||
|
||||
immutable@^4.0.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.1.0.tgz#f795787f0db780183307b9eb2091fcac1f6fafef"
|
||||
|
@ -1674,7 +1701,7 @@ jest-worker@^27.4.5:
|
|||
merge-stream "^2.0.0"
|
||||
supports-color "^8.0.0"
|
||||
|
||||
js-tokens@^4.0.0:
|
||||
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
||||
|
@ -1745,6 +1772,13 @@ lodash.debounce@^4.0.8:
|
|||
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
||||
integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
|
||||
|
||||
loose-envify@^1.1.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
|
||||
dependencies:
|
||||
js-tokens "^3.0.0 || ^4.0.0"
|
||||
|
||||
make-dir@^3.0.2, make-dir@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
|
||||
|
@ -1789,6 +1823,11 @@ normalize-path@^3.0.0, normalize-path@~3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
||||
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
|
||||
|
||||
object-assign@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
|
||||
|
||||
p-limit@^2.2.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
|
||||
|
@ -1840,6 +1879,11 @@ pkg-dir@^4.1.0, pkg-dir@^4.2.0:
|
|||
dependencies:
|
||||
find-up "^4.0.0"
|
||||
|
||||
promise-polyfill@^8.3.0:
|
||||
version "8.3.0"
|
||||
resolved "https://registry.yarnpkg.com/promise-polyfill/-/promise-polyfill-8.3.0.tgz#9284810268138d103807b11f4e23d5e945a4db63"
|
||||
integrity sha512-H5oELycFml5yto/atYqmjyigJoAo3+OXwolYiH7OfQuYlAqhxNvTfiNMbV9hsC6Yp83yE5r2KTVmtrG6R9i6Pg==
|
||||
|
||||
punycode@^2.1.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||
|
@ -1852,6 +1896,23 @@ randombytes@^2.1.0:
|
|||
dependencies:
|
||||
safe-buffer "^5.1.0"
|
||||
|
||||
react-dom@^17.0.0:
|
||||
version "17.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"
|
||||
integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
scheduler "^0.20.2"
|
||||
|
||||
react@^17.0.0:
|
||||
version "17.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
|
||||
integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
readdirp@~3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
|
||||
|
@ -1957,6 +2018,14 @@ sass@^1.42.1:
|
|||
immutable "^4.0.0"
|
||||
source-map-js ">=0.6.2 <2.0.0"
|
||||
|
||||
scheduler@^0.20.2:
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"
|
||||
integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
schema-utils@^2.6.5:
|
||||
version "2.7.1"
|
||||
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7"
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
.ppc-button-wrapper #ppcp-messages:first-child {
|
||||
.ppc-button-wrapper .ppcp-messages:first-child {
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,11 +9,11 @@ class CartActionHandler {
|
|||
this.errorHandler = errorHandler;
|
||||
}
|
||||
|
||||
subscriptionsConfiguration() {
|
||||
subscriptionsConfiguration(subscription_plan_id) {
|
||||
return {
|
||||
createSubscription: (data, actions) => {
|
||||
return actions.subscription.create({
|
||||
'plan_id': this.config.subscription_plan_id
|
||||
'plan_id': subscription_plan_id
|
||||
});
|
||||
},
|
||||
onApprove: (data, actions) => {
|
||||
|
|
|
@ -12,7 +12,7 @@ class CheckoutActionHandler {
|
|||
this.spinner = spinner;
|
||||
}
|
||||
|
||||
subscriptionsConfiguration() {
|
||||
subscriptionsConfiguration(subscription_plan_id) {
|
||||
return {
|
||||
createSubscription: async (data, actions) => {
|
||||
try {
|
||||
|
@ -22,7 +22,7 @@ class CheckoutActionHandler {
|
|||
}
|
||||
|
||||
return actions.subscription.create({
|
||||
'plan_id': this.config.subscription_plan_id
|
||||
'plan_id': subscription_plan_id
|
||||
});
|
||||
},
|
||||
onApprove: (data, actions) => {
|
||||
|
|
|
@ -90,7 +90,12 @@ class CartBootstrap {
|
|||
PayPalCommerceGateway.data_client_id.has_subscriptions
|
||||
&& PayPalCommerceGateway.data_client_id.paypal_subscriptions_enabled
|
||||
) {
|
||||
this.renderer.render(actionHandler.subscriptionsConfiguration());
|
||||
let subscription_plan_id = PayPalCommerceGateway.subscription_plan_id
|
||||
if(PayPalCommerceGateway.variable_paypal_subscription_variation_from_cart !== '') {
|
||||
subscription_plan_id = PayPalCommerceGateway.variable_paypal_subscription_variation_from_cart
|
||||
}
|
||||
|
||||
this.renderer.render(actionHandler.subscriptionsConfiguration(subscription_plan_id));
|
||||
|
||||
if(!PayPalCommerceGateway.subscription_product_allowed) {
|
||||
this.gateway.button.is_disabled = true;
|
||||
|
|
|
@ -106,7 +106,11 @@ class CheckoutBootstap {
|
|||
PayPalCommerceGateway.data_client_id.has_subscriptions
|
||||
&& PayPalCommerceGateway.data_client_id.paypal_subscriptions_enabled
|
||||
) {
|
||||
this.renderer.render(actionHandler.subscriptionsConfiguration(), {}, actionHandler.configuration());
|
||||
let subscription_plan_id = PayPalCommerceGateway.subscription_plan_id
|
||||
if(PayPalCommerceGateway.variable_paypal_subscription_variation_from_cart !== '') {
|
||||
subscription_plan_id = PayPalCommerceGateway.variable_paypal_subscription_variation_from_cart
|
||||
}
|
||||
this.renderer.render(actionHandler.subscriptionsConfiguration(subscription_plan_id), {}, actionHandler.configuration());
|
||||
|
||||
if(!PayPalCommerceGateway.subscription_product_allowed) {
|
||||
this.gateway.button.is_disabled = true;
|
||||
|
|
|
@ -11,22 +11,20 @@ class MessagesBootstrap {
|
|||
}
|
||||
}
|
||||
|
||||
init() {
|
||||
async init() {
|
||||
if (this.gateway.messages?.block?.enabled) {
|
||||
this.discoverBlocks();
|
||||
await this.attemptDiscoverBlocks(3); // Try up to 3 times
|
||||
}
|
||||
jQuery(document.body).on('ppcp_cart_rendered ppcp_checkout_rendered', () => {
|
||||
this.render();
|
||||
});
|
||||
jQuery(document.body).on('ppcp_script_data_changed', (e, data) => {
|
||||
this.gateway = data;
|
||||
|
||||
this.render();
|
||||
});
|
||||
jQuery(document.body).on('ppcp_cart_total_updated ppcp_checkout_total_updated ppcp_product_total_updated ppcp_block_cart_total_updated', (e, amount) => {
|
||||
if (this.lastAmount !== amount) {
|
||||
this.lastAmount = amount;
|
||||
|
||||
this.render();
|
||||
}
|
||||
});
|
||||
|
@ -34,13 +32,39 @@ class MessagesBootstrap {
|
|||
this.render();
|
||||
}
|
||||
|
||||
attemptDiscoverBlocks(retries) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.discoverBlocks().then(found => {
|
||||
if (!found && retries > 0) {
|
||||
setTimeout(() => {
|
||||
this.attemptDiscoverBlocks(retries - 1).then(resolve);
|
||||
}, 2000); // Wait 2 seconds before retrying
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
discoverBlocks() {
|
||||
Array.from(document.querySelectorAll('.ppcp-paylater-message-block')).forEach(blockElement => {
|
||||
const config = {wrapper: '#' + blockElement.id};
|
||||
if (!blockElement.getAttribute('data-pp-placement')) {
|
||||
config.placement = this.gateway.messages.placement;
|
||||
return new Promise((resolve) => {
|
||||
const elements = document.querySelectorAll('.ppcp-messages');
|
||||
if (elements.length === 0) {
|
||||
resolve(false);
|
||||
return;
|
||||
}
|
||||
this.renderers.push(new MessageRenderer(config));
|
||||
|
||||
Array.from(elements).forEach(blockElement => {
|
||||
if (!blockElement.id) {
|
||||
blockElement.id = `ppcp-message-${Math.random().toString(36).substr(2, 9)}`; // Ensure each block has a unique ID
|
||||
}
|
||||
const config = {wrapper: '#' + blockElement.id};
|
||||
if (!blockElement.getAttribute('data-pp-placement')) {
|
||||
config.placement = this.gateway.messages.placement;
|
||||
}
|
||||
this.renderers.push(new MessageRenderer(config));
|
||||
});
|
||||
resolve(true);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ import {loadScript} from "@paypal/paypal-js";
|
|||
import widgetBuilder from "../Renderer/WidgetBuilder";
|
||||
import merge from "deepmerge";
|
||||
import {keysToCamelCase} from "./Utils";
|
||||
import {getCurrentPaymentMethod} from "./CheckoutMethodState";
|
||||
|
||||
// This component may be used by multiple modules. This assures that options are shared between all instances.
|
||||
let options = window.ppcpWidgetBuilder = window.ppcpWidgetBuilder || {
|
||||
|
@ -60,6 +61,13 @@ export const loadPaypalScript = (config, onLoaded, onError = null) => {
|
|||
scriptOptions = merge(scriptOptions, config.script_attributes);
|
||||
}
|
||||
|
||||
// Axo SDK options
|
||||
const sdkClientToken = config?.axo?.sdk_client_token;
|
||||
if(sdkClientToken) {
|
||||
scriptOptions['data-sdk-client-token'] = sdkClientToken;
|
||||
scriptOptions['data-client-metadata-id'] = 'ppcp-cm-id';
|
||||
}
|
||||
|
||||
// Load PayPal script for special case with data-client-token
|
||||
if (config.data_client_id?.set_attribute) {
|
||||
dataClientIdAttributeHandler(scriptOptions, config.data_client_id, callback, errorCallback);
|
||||
|
@ -68,7 +76,7 @@ export const loadPaypalScript = (config, onLoaded, onError = null) => {
|
|||
|
||||
// Adds data-user-id-token to script options.
|
||||
const userIdToken = config?.save_payment_methods?.id_token;
|
||||
if(userIdToken) {
|
||||
if(userIdToken && !sdkClientToken) {
|
||||
scriptOptions['data-user-id-token'] = userIdToken;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ use WooCommerce\PayPalCommerce\Button\Helper\ContextTrait;
|
|||
use WooCommerce\PayPalCommerce\Button\Helper\MessagesApply;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||
use WooCommerce\PayPalCommerce\PayLaterBlock\PayLaterBlockModule;
|
||||
use WooCommerce\PayPalCommerce\PayLaterWCBlocks\PayLaterWCBlocksModule;
|
||||
use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CreatePaymentToken;
|
||||
use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CreateSetupToken;
|
||||
use WooCommerce\PayPalCommerce\SavePaymentMethods\Endpoint\CreatePaymentTokenForGuest;
|
||||
|
@ -438,7 +439,20 @@ class SmartButton implements SmartButtonInterface {
|
|||
wp_is_block_theme()
|
||||
);
|
||||
|
||||
$get_hook = function ( string $location ) use ( $default_pay_order_hook, $is_block_theme ): ?array {
|
||||
$has_paylater_block =
|
||||
(
|
||||
PayLaterBlockModule::is_block_enabled( $this->settings_status ) &&
|
||||
has_block( 'woocommerce-paypal-payments/paylater-messages' )
|
||||
) ||
|
||||
(
|
||||
PayLaterWCBlocksModule::is_block_enabled( $this->settings_status, $location ) &&
|
||||
(
|
||||
has_block( 'woocommerce-paypal-payments/checkout-paylater-messages' ) ||
|
||||
has_block( 'woocommerce-paypal-payments/cart-paylater-messages' )
|
||||
)
|
||||
);
|
||||
|
||||
$get_hook = function ( string $location ) use ( $default_pay_order_hook, $is_block_theme, $has_paylater_block ): ?array {
|
||||
switch ( $location ) {
|
||||
case 'checkout':
|
||||
return $this->messages_renderer_hook( $location, 'woocommerce_review_order_before_payment', 10 );
|
||||
|
@ -457,11 +471,14 @@ class SmartButton implements SmartButtonInterface {
|
|||
? $this->messages_renderer_block( $location, 'core/navigation', 10 )
|
||||
: $this->messages_renderer_hook( $location, 'loop_start', 20 );
|
||||
default:
|
||||
return null;
|
||||
return $has_paylater_block
|
||||
? $this->messages_renderer_hook( $location, 'ppcp_paylater_message_block', 10 )
|
||||
: null;
|
||||
}
|
||||
};
|
||||
|
||||
$hook = $get_hook( $location );
|
||||
|
||||
if ( ! $hook ) {
|
||||
return false;
|
||||
}
|
||||
|
@ -492,7 +509,7 @@ class SmartButton implements SmartButtonInterface {
|
|||
function () {
|
||||
echo '
|
||||
<script>
|
||||
document.querySelector("#payment").before(document.querySelector("#ppcp-messages"))
|
||||
document.querySelector("#payment").before(document.querySelector(".ppcp-messages"))
|
||||
</script>';
|
||||
}
|
||||
);
|
||||
|
@ -601,10 +618,6 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages
|
|||
return false;
|
||||
}
|
||||
|
||||
if ( in_array( $this->context(), array( 'checkout-block', 'cart-block' ), true ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->should_load_buttons() || $this->should_load_messages() || $this->can_render_dcc();
|
||||
}
|
||||
|
||||
|
@ -655,7 +668,11 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages
|
|||
|
||||
$messaging_enabled_for_current_location = $this->settings_status->is_pay_later_messaging_enabled_for_location( $location );
|
||||
|
||||
$has_paylater_block = has_block( 'woocommerce-paypal-payments/paylater-messages' ) && PayLaterBlockModule::is_block_enabled( $this->settings_status );
|
||||
$has_paylater_block = PayLaterBlockModule::is_block_enabled( $this->settings_status ) && has_block( 'woocommerce-paypal-payments/paylater-messages' );
|
||||
|
||||
if ( 'cart-block' === $location || 'checkout-block' === $location ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch ( $location ) {
|
||||
case 'checkout':
|
||||
|
@ -667,9 +684,6 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages
|
|||
return $messaging_enabled_for_current_location;
|
||||
case 'block-editor':
|
||||
return true;
|
||||
case 'checkout-block':
|
||||
case 'cart-block':
|
||||
return $has_paylater_block || $this->is_block_editor();
|
||||
default:
|
||||
return $has_paylater_block;
|
||||
}
|
||||
|
@ -789,7 +803,7 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages
|
|||
*/
|
||||
do_action( "ppcp_before_{$location_hook}_message_wrapper" );
|
||||
|
||||
$messages_placeholder = '<div id="ppcp-messages" data-partner-attribution-id="Woo_PPCP"></div>';
|
||||
$messages_placeholder = '<div class="ppcp-messages" data-partner-attribution-id="Woo_PPCP"></div>';
|
||||
|
||||
if ( is_array( $block_params ) && ( $block_params['blockName'] ?? false ) ) {
|
||||
$this->render_after_block(
|
||||
|
@ -888,7 +902,20 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages
|
|||
|
||||
$styling_per_location = $this->settings->has( 'pay_later_enable_styling_per_messaging_location' ) && $this->settings->get( 'pay_later_enable_styling_per_messaging_location' );
|
||||
$location = $styling_per_location ? $location : 'general';
|
||||
$setting_name_prefix = "pay_later_{$location}_message";
|
||||
|
||||
// Map checkout-block and cart-block message options to checkout and cart options.
|
||||
switch ( $location ) {
|
||||
case 'checkout-block':
|
||||
$location = 'checkout';
|
||||
break;
|
||||
case 'cart-block':
|
||||
$location = 'cart';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
$setting_name_prefix = "pay_later_{$location}_message";
|
||||
|
||||
$layout = $this->settings->has( "{$setting_name_prefix}_layout" ) ? $this->settings->get( "{$setting_name_prefix}_layout" ) : 'text';
|
||||
$logo_type = $this->settings->has( "{$setting_name_prefix}_logo" ) ? $this->settings->get( "{$setting_name_prefix}_logo" ) : 'primary';
|
||||
|
@ -899,7 +926,7 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages
|
|||
$text_size = $this->settings->has( "{$setting_name_prefix}_text_size" ) ? $this->settings->get( "{$setting_name_prefix}_text_size" ) : '12';
|
||||
|
||||
return array(
|
||||
'wrapper' => '#ppcp-messages',
|
||||
'wrapper' => '.ppcp-messages',
|
||||
'is_hidden' => ! $this->is_pay_later_filter_enabled_for_location( $this->context() ),
|
||||
'block' => array(
|
||||
'enabled' => PayLaterBlockModule::is_block_enabled( $this->settings_status ),
|
||||
|
@ -1111,6 +1138,7 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages
|
|||
'subscription_plan_id' => $this->subscription_helper->paypal_subscription_id(),
|
||||
'vault_v3_enabled' => $this->vault_v3_enabled,
|
||||
'variable_paypal_subscription_variations' => $this->subscription_helper->variable_paypal_subscription_variations(),
|
||||
'variable_paypal_subscription_variation_from_cart' => $this->subscription_helper->paypal_subscription_variation_from_cart(),
|
||||
'subscription_product_allowed' => $this->subscription_helper->checkout_subscription_product_allowed(),
|
||||
'locations_with_subscription_product' => $this->subscription_helper->locations_with_subscription_product(),
|
||||
'enforce_vault' => $this->has_subscriptions(),
|
||||
|
@ -1428,9 +1456,45 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages
|
|||
* @return array
|
||||
*/
|
||||
private function attributes(): array {
|
||||
return array(
|
||||
$attributes = array(
|
||||
'data-partner-attribution-id' => $this->bn_code_for_context( $this->context() ),
|
||||
);
|
||||
|
||||
$page_type_attribute = $this->page_type_attribute();
|
||||
if ( $page_type_attribute ) {
|
||||
$attributes['data-page-type'] = $page_type_attribute;
|
||||
}
|
||||
|
||||
return $attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the value for page type attribute(data-page-type) used for the JS SDK.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function page_type_attribute(): string {
|
||||
if ( is_search() ) {
|
||||
return 'search-results';
|
||||
}
|
||||
|
||||
switch ( $this->location() ) {
|
||||
case 'product':
|
||||
return 'product-details';
|
||||
case 'shop':
|
||||
return 'product-listing';
|
||||
case 'home':
|
||||
return 'mini-cart';
|
||||
case 'cart-block':
|
||||
case 'cart':
|
||||
return 'cart';
|
||||
case 'checkout-block':
|
||||
case 'checkout':
|
||||
case 'pay-now':
|
||||
return 'checkout';
|
||||
default:
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
BIN
modules/ppcp-googlepay/assets/images/googlepay.png
Normal file
BIN
modules/ppcp-googlepay/assets/images/googlepay.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
|
@ -39,6 +39,8 @@ return array(
|
|||
$display_manager = $container->get( 'wcgateway.display-manager' );
|
||||
assert( $display_manager instanceof DisplayManager );
|
||||
|
||||
$module_url = $container->get( 'googlepay.url' );
|
||||
|
||||
// Connection tab fields.
|
||||
$fields = $insert_after(
|
||||
$fields,
|
||||
|
@ -62,10 +64,15 @@ return array(
|
|||
$connection_link = '<a href="' . $connection_url . '" style="pointer-events: auto">';
|
||||
return $insert_after(
|
||||
$fields,
|
||||
'allow_card_button_gateway',
|
||||
'digital_wallet_heading',
|
||||
array(
|
||||
'googlepay_button_enabled' => array(
|
||||
'title' => __( 'Google Pay Button', 'woocommerce-paypal-payments' ),
|
||||
'title_html' => sprintf(
|
||||
'<img src="%sassets/images/googlepay.png" alt="%s" style="max-width: 150px; max-height: 45px;" />',
|
||||
$module_url,
|
||||
__( 'Google Pay', 'woocommerce-paypal-payments' )
|
||||
),
|
||||
'type' => 'checkbox',
|
||||
'class' => array( 'ppcp-grayed-out-text' ),
|
||||
'input_class' => array( 'ppcp-disabled-checkbox' ),
|
||||
|
@ -80,7 +87,7 @@ return array(
|
|||
. '</p>',
|
||||
'default' => 'yes',
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'gateway' => 'paypal',
|
||||
'gateway' => 'dcc',
|
||||
'requirements' => array(),
|
||||
'custom_attributes' => array(
|
||||
'data-ppcp-display' => wp_json_encode(
|
||||
|
@ -93,6 +100,7 @@ return array(
|
|||
)
|
||||
),
|
||||
),
|
||||
'classes' => array( 'ppcp-valign-label-middle', 'ppcp-align-label-center' ),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
@ -101,10 +109,15 @@ return array(
|
|||
// Standard Payments tab fields.
|
||||
return $insert_after(
|
||||
$fields,
|
||||
'allow_card_button_gateway',
|
||||
'digital_wallet_heading',
|
||||
array(
|
||||
'googlepay_button_enabled' => array(
|
||||
'title' => __( 'Google Pay Button', 'woocommerce-paypal-payments' ),
|
||||
'title_html' => sprintf(
|
||||
'<img src="%sassets/images/googlepay.png" alt="%s" style="max-width: 150px; max-height: 45px;" />',
|
||||
$module_url,
|
||||
__( 'Google Pay', 'woocommerce-paypal-payments' )
|
||||
),
|
||||
'type' => 'checkbox',
|
||||
'label' => __( 'Enable Google Pay button', 'woocommerce-paypal-payments' )
|
||||
. '<p class="description">'
|
||||
|
@ -117,7 +130,7 @@ return array(
|
|||
. '</p>',
|
||||
'default' => 'yes',
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'gateway' => 'paypal',
|
||||
'gateway' => 'dcc',
|
||||
'requirements' => array(),
|
||||
'custom_attributes' => array(
|
||||
'data-ppcp-display' => wp_json_encode(
|
||||
|
@ -129,10 +142,12 @@ return array(
|
|||
->action_visible( 'googlepay_button_color' )
|
||||
->action_visible( 'googlepay_button_language' )
|
||||
->action_visible( 'googlepay_button_shipping_enabled' )
|
||||
->action_class( 'googlepay_button_enabled', 'active' )
|
||||
->to_array(),
|
||||
)
|
||||
),
|
||||
),
|
||||
'classes' => array( 'ppcp-valign-label-middle', 'ppcp-align-label-center' ),
|
||||
),
|
||||
'googlepay_button_type' => array(
|
||||
'title' => __( 'Button Label', 'woocommerce-paypal-payments' ),
|
||||
|
@ -148,7 +163,7 @@ return array(
|
|||
'default' => 'pay',
|
||||
'options' => PropertiesDictionary::button_types(),
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'gateway' => 'paypal',
|
||||
'gateway' => 'dcc',
|
||||
'requirements' => array(),
|
||||
),
|
||||
'googlepay_button_color' => array(
|
||||
|
@ -166,7 +181,7 @@ return array(
|
|||
'default' => 'black',
|
||||
'options' => PropertiesDictionary::button_colors(),
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'gateway' => 'paypal',
|
||||
'gateway' => 'dcc',
|
||||
'requirements' => array(),
|
||||
),
|
||||
'googlepay_button_language' => array(
|
||||
|
@ -183,7 +198,7 @@ return array(
|
|||
'default' => 'en',
|
||||
'options' => PropertiesDictionary::button_languages(),
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'gateway' => 'paypal',
|
||||
'gateway' => 'dcc',
|
||||
'requirements' => array(),
|
||||
),
|
||||
'googlepay_button_shipping_enabled' => array(
|
||||
|
@ -198,7 +213,7 @@ return array(
|
|||
'label' => __( 'Enable Google Pay shipping callback', 'woocommerce-paypal-payments' ),
|
||||
'default' => 'no',
|
||||
'screens' => array( State::STATE_ONBOARDED ),
|
||||
'gateway' => 'paypal',
|
||||
'gateway' => 'dcc',
|
||||
'requirements' => array(),
|
||||
),
|
||||
)
|
||||
|
|
|
@ -28,7 +28,7 @@ class GooglepayButton {
|
|||
|
||||
this.log = function() {
|
||||
if ( this.buttonConfig.is_debug ) {
|
||||
console.log('[GooglePayButton]', ...arguments);
|
||||
//console.log('[GooglePayButton]', ...arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,7 +136,10 @@ class OnboardingOptionsRenderer {
|
|||
__( 'For Standard payments, Casual sellers may connect their Personal PayPal account in eligible countries to sell on WooCommerce. For Advanced payments, a Business PayPal account is required.', 'woocommerce-paypal-payments' )
|
||||
),
|
||||
);
|
||||
$items[] = '
|
||||
|
||||
$basic_table_rows = apply_filters( 'ppcp_onboarding_basic_table_rows', $basic_table_rows );
|
||||
|
||||
$items[] = '
|
||||
<li>
|
||||
<label>
|
||||
<input type="radio" id="ppcp-onboarding-dcc-basic" name="ppcp_onboarding_dcc" value="basic" checked ' .
|
||||
|
@ -191,7 +194,10 @@ class OnboardingOptionsRenderer {
|
|||
__( 'For Standard payments, Casual sellers may connect their Personal PayPal account in eligible countries to sell on WooCommerce. For Advanced payments, a Business PayPal account is required.', 'woocommerce-paypal-payments' )
|
||||
),
|
||||
);
|
||||
$items[] = '
|
||||
|
||||
$dcc_table_rows = apply_filters( 'ppcp_onboarding_dcc_table_rows', $dcc_table_rows, $this );
|
||||
|
||||
$items[] = '
|
||||
<li>
|
||||
<label>
|
||||
<input type="radio" id="ppcp-onboarding-dcc-acdc" name="ppcp_onboarding_dcc" value="acdc" ' .
|
||||
|
@ -224,7 +230,7 @@ class OnboardingOptionsRenderer {
|
|||
* @param string $note The additional description text, such as about conditions.
|
||||
* @return string
|
||||
*/
|
||||
private function render_table_row( string $header, string $value, string $tooltip = '', string $note = '' ): string {
|
||||
public function render_table_row( string $header, string $value, string $tooltip = '', string $note = '' ): string {
|
||||
$value_html = $value;
|
||||
if ( $note ) {
|
||||
$value_html .= '<br/><span class="ppcp-muted-text">' . $note . '</span>';
|
||||
|
|
|
@ -7,40 +7,45 @@
|
|||
"description": "PayPal Pay Later messaging will be displayed for eligible customers. Customers automatically see the most relevant Pay Later offering.",
|
||||
"example": {},
|
||||
"attributes": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"layout": {
|
||||
"type": "string",
|
||||
"default": "flex"
|
||||
},
|
||||
"logo": {
|
||||
"type": "string",
|
||||
"default": "inline"
|
||||
},
|
||||
"position": {
|
||||
"type": "string",
|
||||
"default": "left"
|
||||
},
|
||||
"color": {
|
||||
"type": "string",
|
||||
"default": "black"
|
||||
},
|
||||
"flexColor": {
|
||||
"type": "string",
|
||||
"default": "white"
|
||||
},
|
||||
"flexRatio": {
|
||||
"type": "string",
|
||||
"default": "8x1"
|
||||
},
|
||||
"placement": {
|
||||
"type": "string",
|
||||
"default": "auto"
|
||||
}
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"layout": {
|
||||
"type": "string",
|
||||
"default": "flex"
|
||||
},
|
||||
"logo": {
|
||||
"type": "string",
|
||||
"default": "inline"
|
||||
},
|
||||
"position": {
|
||||
"type": "string",
|
||||
"default": "left"
|
||||
},
|
||||
"color": {
|
||||
"type": "string",
|
||||
"default": "black"
|
||||
},
|
||||
"size": {
|
||||
"type": "string",
|
||||
"default": "14"
|
||||
},
|
||||
"flexColor": {
|
||||
"type": "string",
|
||||
"default": "white"
|
||||
},
|
||||
"flexRatio": {
|
||||
"type": "string",
|
||||
"default": "8x1"
|
||||
},
|
||||
"placement": {
|
||||
"type": "string",
|
||||
"default": "auto"
|
||||
}
|
||||
},
|
||||
"supports": {
|
||||
"html": false
|
||||
"html": false,
|
||||
"multiple": false
|
||||
},
|
||||
"textdomain": "woocommerce-paypal-payments",
|
||||
"editorScript": "ppcp-paylater-block",
|
||||
|
|
156
modules/ppcp-paylater-block/composer.lock
generated
Normal file
156
modules/ppcp-paylater-block/composer.lock
generated
Normal file
|
@ -0,0 +1,156 @@
|
|||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "51e234e39d0fd6bbb67fe2186683facd",
|
||||
"packages": [
|
||||
{
|
||||
"name": "container-interop/service-provider",
|
||||
"version": "v0.4.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/container-interop/service-provider.git",
|
||||
"reference": "e04441ca21ef03e10dce70b0af29269281eec6dc"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/container-interop/service-provider/zipball/e04441ca21ef03e10dce70b0af29269281eec6dc",
|
||||
"reference": "e04441ca21ef03e10dce70b0af29269281eec6dc",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"psr/container": "^1.0 || ^2.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Interop\\Container\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "Promoting container interoperability through standard service providers",
|
||||
"homepage": "https://github.com/container-interop/service-provider",
|
||||
"support": {
|
||||
"issues": "https://github.com/container-interop/service-provider/issues",
|
||||
"source": "https://github.com/container-interop/service-provider/tree/v0.4.1"
|
||||
},
|
||||
"time": "2023-12-14T14:50:12+00:00"
|
||||
},
|
||||
{
|
||||
"name": "dhii/module-interface",
|
||||
"version": "v0.3.0-alpha2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Dhii/module-interface.git",
|
||||
"reference": "0e39f167d7ed8990c82f5d2e6084159d1a502a5b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Dhii/module-interface/zipball/0e39f167d7ed8990c82f5d2e6084159d1a502a5b",
|
||||
"reference": "0e39f167d7ed8990c82f5d2e6084159d1a502a5b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"container-interop/service-provider": "^0.4",
|
||||
"php": "^7.1 | ^8.0",
|
||||
"psr/container": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7.0 | ^8.0 | ^9.0",
|
||||
"slevomat/coding-standard": "^6.0",
|
||||
"vimeo/psalm": "^3.11.7 | ^4.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-develop": "0.3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Dhii\\Modular\\Module\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Dhii Team",
|
||||
"email": "development@dhii.co"
|
||||
}
|
||||
],
|
||||
"description": "Interfaces for modules",
|
||||
"support": {
|
||||
"issues": "https://github.com/Dhii/module-interface/issues",
|
||||
"source": "https://github.com/Dhii/module-interface/tree/v0.3.0-alpha2"
|
||||
},
|
||||
"time": "2021-08-23T08:23:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/container",
|
||||
"version": "1.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/container.git",
|
||||
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea",
|
||||
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.4.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Container\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "https://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common Container Interface (PHP FIG PSR-11)",
|
||||
"homepage": "https://github.com/php-fig/container",
|
||||
"keywords": [
|
||||
"PSR-11",
|
||||
"container",
|
||||
"container-interface",
|
||||
"container-interop",
|
||||
"psr"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-fig/container/issues",
|
||||
"source": "https://github.com/php-fig/container/tree/1.1.2"
|
||||
},
|
||||
"time": "2021-11-05T16:50:12+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "dev",
|
||||
"stability-flags": [],
|
||||
"prefer-stable": true,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
"php": "^7.2 | ^8.0"
|
||||
},
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.3.0"
|
||||
}
|
|
@ -10,13 +10,16 @@
|
|||
"Edge >= 14"
|
||||
],
|
||||
"dependencies": {
|
||||
"core-js": "^3.25.0"
|
||||
"@paypal/react-paypal-js": "^8.2.0",
|
||||
"core-js": "^3.25.0",
|
||||
"react": "^17.0.0",
|
||||
"react-dom": "^17.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.19",
|
||||
"@babel/preset-env": "^7.19",
|
||||
"@babel/preset-react": "^7.18.6",
|
||||
"@woocommerce/dependency-extraction-webpack-plugin": "^2.2.0",
|
||||
"@woocommerce/dependency-extraction-webpack-plugin": "2.2.0",
|
||||
"babel-loader": "^8.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"file-loader": "^6.2.0",
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
import { useRef, useEffect } from '@wordpress/element';
|
||||
|
||||
export default function PayPalMessages({
|
||||
amount,
|
||||
style,
|
||||
onRender,
|
||||
}) {
|
||||
const containerRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const messages = paypal.Messages({
|
||||
amount,
|
||||
style,
|
||||
onRender,
|
||||
});
|
||||
|
||||
messages.render(containerRef.current)
|
||||
.catch(err => {
|
||||
// Ignore when component destroyed.
|
||||
if (!containerRef.current || containerRef.current.children.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.error(err);
|
||||
});
|
||||
}, [amount, style, onRender]);
|
||||
|
||||
return <div ref={containerRef}/>
|
||||
}
|
|
@ -2,19 +2,16 @@ import { __ } from '@wordpress/i18n';
|
|||
import { useState, useEffect } from '@wordpress/element';
|
||||
import { InspectorControls, useBlockProps } from '@wordpress/block-editor';
|
||||
import { PanelBody, SelectControl, Spinner } from '@wordpress/components';
|
||||
import { useScriptParams } from "./hooks/script-params";
|
||||
import { loadPaypalScript } from '../../../ppcp-button/resources/js/modules/Helper/ScriptLoading'
|
||||
import PayPalMessages from "./components/PayPalMessages";
|
||||
import { PayPalScriptProvider, PayPalMessages } from '@paypal/react-paypal-js';
|
||||
import { useScriptParams } from './hooks/script-params';
|
||||
|
||||
export default function Edit( { attributes, clientId, setAttributes } ) {
|
||||
export default function Edit({ attributes, clientId, setAttributes }) {
|
||||
const { layout, logo, position, color, size, flexColor, flexRatio, placement, id } = attributes;
|
||||
const isFlex = layout === 'flex';
|
||||
|
||||
const [paypalScriptState, setPaypalScriptState] = useState(null);
|
||||
const [loaded, setLoaded] = useState(false);
|
||||
|
||||
const [rendered, setRendered] = useState(false);
|
||||
|
||||
let amount = undefined;
|
||||
let amount;
|
||||
const postContent = String(wp.data.select('core/editor')?.getEditedPostContent());
|
||||
if (postContent.includes('woocommerce/checkout') || postContent.includes('woocommerce/cart')) {
|
||||
amount = 50.0;
|
||||
|
@ -36,159 +33,171 @@ export default function Edit( { attributes, clientId, setAttributes } ) {
|
|||
|
||||
let classes = ['ppcp-paylater-block-preview', 'ppcp-overlay-parent'];
|
||||
if (PcpPayLaterBlock.vaultingEnabled || !PcpPayLaterBlock.placementEnabled) {
|
||||
classes = ['ppcp-paylater-block-preview', 'ppcp-paylater-unavailable', 'block-editor-warning'];
|
||||
classes.push('ppcp-paylater-unavailable', 'block-editor-warning');
|
||||
}
|
||||
const props = useBlockProps({className: classes});
|
||||
|
||||
const loadingElement = <div {...props}><Spinner/></div>;
|
||||
const props = useBlockProps({ className: classes.join(' ') });
|
||||
|
||||
useEffect(() => {
|
||||
if (!id) {
|
||||
setAttributes({id: 'ppcp-' + clientId});
|
||||
setAttributes({ id: `ppcp-${clientId}` });
|
||||
}
|
||||
}, []);
|
||||
}, [id, clientId]);
|
||||
|
||||
if (PcpPayLaterBlock.vaultingEnabled) {
|
||||
return <div {...props}>
|
||||
<div className={'block-editor-warning__contents'}>
|
||||
<h3>{__('PayPal Pay Later Messaging', 'woocommerce-paypal-payments')}</h3>
|
||||
<p className={'block-editor-warning__message'}>{__('Pay Later Messaging cannot be used while PayPal Vaulting is active. Disable PayPal Vaulting in the PayPal Payment settings to reactivate this block', 'woocommerce-paypal-payments')}</p>
|
||||
<div className={'class="block-editor-warning__actions"'}>
|
||||
<span className={'block-editor-warning__action'}>
|
||||
<a href={PcpPayLaterBlock.settingsUrl} className={'components-button is-primary'}>
|
||||
{__('PayPal Payments Settings', 'woocommerce-paypal-payments')}
|
||||
</a>
|
||||
</span>
|
||||
<span className={'block-editor-warning__action'}>
|
||||
<button onClick={() => wp.data.dispatch( 'core/block-editor' ).removeBlock(clientId)} type={'button'} className={'components-button is-secondary'}>
|
||||
{__('Remove Block', 'woocommerce-paypal-payments')}
|
||||
</button>
|
||||
</span>
|
||||
return (
|
||||
<div {...props}>
|
||||
<div className='block-editor-warning__contents'>
|
||||
<p className='block-editor-warning__message'>
|
||||
{__('Pay Later Messaging cannot be used while PayPal Vaulting is active. Disable PayPal Vaulting in the PayPal Payment settings to reactivate this block', 'woocommerce-paypal-payments')}
|
||||
</p>
|
||||
<div className='block-editor-warning__actions'>
|
||||
<span className='block-editor-warning__action'>
|
||||
<a href={PcpPayLaterBlock.payLaterSettingsUrl}>
|
||||
<button type='button' className='components-button is-primary'>
|
||||
{__('PayPal Payments Settings', 'woocommerce-paypal-payments')}
|
||||
</button>
|
||||
</a>
|
||||
</span>
|
||||
<span className='block-editor-warning__action'>
|
||||
<button
|
||||
onClick={() => wp.data.dispatch('core/block-editor').removeBlock(clientId)}
|
||||
type='button' className='components-button is-secondary'>
|
||||
{__('Remove Block', 'woocommerce-paypal-payments')}
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!PcpPayLaterBlock.placementEnabled) {
|
||||
return <div {...props}>
|
||||
<div className={'block-editor-warning__contents'}>
|
||||
<h3>{__('PayPal Pay Later Messaging', 'woocommerce-paypal-payments')}</h3>
|
||||
<p className={'block-editor-warning__message'}>{__('Pay Later Messaging cannot be used while the “WooCommerce Block” messaging placement is disabled. Enable the placement in the PayPal Payments Pay Later settings to reactivate this block.', 'woocommerce-paypal-payments')}</p>
|
||||
<div className={'class="block-editor-warning__actions"'}>
|
||||
<span className={'block-editor-warning__action'}>
|
||||
<a href={PcpPayLaterBlock.payLaterSettingsUrl} className={'components-button is-primary'}>
|
||||
{__('PayPal Payments Settings', 'woocommerce-paypal-payments')}
|
||||
</a>
|
||||
</span>
|
||||
<span className={'block-editor-warning__action'}>
|
||||
<button onClick={() => wp.data.dispatch( 'core/block-editor' ).removeBlock(clientId)} type={'button'} className={'components-button is-secondary'}>
|
||||
{__('Remove Block', 'woocommerce-paypal-payments')}
|
||||
</button>
|
||||
</span>
|
||||
return (
|
||||
<div {...props}>
|
||||
<div className='block-editor-warning__contents'>
|
||||
<p className='block-editor-warning__message'>
|
||||
{__('Pay Later Messaging cannot be used while the “WooCommerce Block” messaging placement is disabled. Enable the placement in the PayPal Payments Pay Later settings to reactivate this block.', 'woocommerce-paypal-payments')}
|
||||
</p>
|
||||
<div className='block-editor-warning__actions'>
|
||||
<span className='block-editor-warning__action'>
|
||||
<a href={PcpPayLaterBlock.payLaterSettingsUrl}>
|
||||
<button type='button' className='components-button is-primary'>
|
||||
{__('PayPal Payments Settings', 'woocommerce-paypal-payments')}
|
||||
</button>
|
||||
</a>
|
||||
</span>
|
||||
<span className='block-editor-warning__action'>
|
||||
<button
|
||||
onClick={() => wp.data.dispatch('core/block-editor').removeBlock(clientId)}
|
||||
type='button' className='components-button is-secondary'>
|
||||
{__('Remove Block', 'woocommerce-paypal-payments')}
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
let scriptParams = useScriptParams(PcpPayLaterBlock.ajax.cart_script_params);
|
||||
const scriptParams = useScriptParams(PcpPayLaterBlock.ajax.cart_script_params);
|
||||
|
||||
if (scriptParams === null) {
|
||||
return loadingElement;
|
||||
}
|
||||
if (scriptParams === false) {
|
||||
scriptParams = {
|
||||
url_params: {
|
||||
clientId: 'test',
|
||||
}
|
||||
}
|
||||
}
|
||||
scriptParams.url_params.components = 'messages,buttons,funding-eligibility';
|
||||
|
||||
if (!paypalScriptState) {
|
||||
loadPaypalScript(scriptParams, () => {
|
||||
setPaypalScriptState('loaded')
|
||||
}, () => {
|
||||
setPaypalScriptState('failed')
|
||||
});
|
||||
}
|
||||
if (paypalScriptState !== 'loaded') {
|
||||
return loadingElement;
|
||||
return <div {...props}><Spinner/></div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<InspectorControls>
|
||||
<PanelBody title={ __( 'Settings', 'woocommerce-paypal-payments' ) }>
|
||||
const urlParams = {
|
||||
...scriptParams.url_params,
|
||||
components: 'messages',
|
||||
dataNamespace: 'ppcp-block-editor-paylater-message',
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<InspectorControls>
|
||||
<PanelBody title={__('Settings', 'woocommerce-paypal-payments')}>
|
||||
<SelectControl
|
||||
label={ __( 'Layout', 'woocommerce-paypal-payments' ) }
|
||||
options={ [
|
||||
{ label: __( 'Text', 'woocommerce-paypal-payments' ), value: 'text' },
|
||||
{ label: __( 'Banner', 'woocommerce-paypal-payments' ), value: 'flex' },
|
||||
] }
|
||||
value={ layout }
|
||||
onChange={ ( value ) => setAttributes( { layout: value } ) }
|
||||
label={__('Layout', 'woocommerce-paypal-payments')}
|
||||
options={[
|
||||
{ label: __('Text', 'woocommerce-paypal-payments'), value: 'text' },
|
||||
{ label: __('Banner', 'woocommerce-paypal-payments'), value: 'flex' },
|
||||
]}
|
||||
value={layout}
|
||||
onChange={(value) => setAttributes({ layout: value })}
|
||||
/>
|
||||
{ !isFlex && (<SelectControl
|
||||
label={__('Logo', 'woocommerce-paypal-payments')}
|
||||
options={[
|
||||
{ label: __('Full logo', 'woocommerce-paypal-payments'), value: 'primary' },
|
||||
{ label: __('Monogram', 'woocommerce-paypal-payments'), value: 'alternative' },
|
||||
{ label: __('Inline', 'woocommerce-paypal-payments'), value: 'inline' },
|
||||
{ label: __('Message only', 'woocommerce-paypal-payments'), value: 'none' },
|
||||
]}
|
||||
value={logo}
|
||||
onChange={(value) => setAttributes({logo: value})}
|
||||
/>)}
|
||||
{ !isFlex && logo === 'primary' && (<SelectControl
|
||||
label={__('Logo Position', 'woocommerce-paypal-payments')}
|
||||
options={[
|
||||
{ label: __( 'Left', 'woocommerce-paypal-payments' ), value: 'left' },
|
||||
{ label: __( 'Right', 'woocommerce-paypal-payments' ), value: 'right' },
|
||||
{ label: __( 'Top', 'woocommerce-paypal-payments' ), value: 'top' },
|
||||
]}
|
||||
value={position}
|
||||
onChange={(value) => setAttributes({position: value})}
|
||||
/>)}
|
||||
{ !isFlex && (<SelectControl
|
||||
label={__('Text Color', 'woocommerce-paypal-payments')}
|
||||
options={[
|
||||
{ label: __( 'Black / Blue logo', 'woocommerce-paypal-payments' ), value: 'black' },
|
||||
{ label: __( 'White / White logo', 'woocommerce-paypal-payments' ), value: 'white' },
|
||||
{ label: __( 'Monochrome', 'woocommerce-paypal-payments' ), value: 'monochrome' },
|
||||
{ label: __( 'Black / Gray logo', 'woocommerce-paypal-payments' ), value: 'grayscale' },
|
||||
]}
|
||||
value={color}
|
||||
onChange={(value) => setAttributes({color: value})}
|
||||
/>)}
|
||||
{ !isFlex && (<SelectControl
|
||||
label={__('Text Size', 'woocommerce-paypal-payments')}
|
||||
options={[
|
||||
{ label: __( 'Small', 'woocommerce-paypal-payments' ), value: '12' },
|
||||
{ label: __( 'Medium', 'woocommerce-paypal-payments' ), value: '14' },
|
||||
{ label: __( 'Large', 'woocommerce-paypal-payments' ), value: '16' },
|
||||
]}
|
||||
value={size}
|
||||
onChange={(value) => setAttributes({size: value})}
|
||||
/>)}
|
||||
{ isFlex && (<SelectControl
|
||||
label={__('Color', 'woocommerce-paypal-payments')}
|
||||
options={[
|
||||
{ label: __( 'Blue', 'woocommerce-paypal-payments' ), value: 'blue' },
|
||||
{ label: __( 'Black', 'woocommerce-paypal-payments' ), value: 'black' },
|
||||
{ label: __( 'White', 'woocommerce-paypal-payments' ), value: 'white' },
|
||||
{ label: __( 'White (no border)', 'woocommerce-paypal-payments' ), value: 'white-no-border' },
|
||||
]}
|
||||
value={flexColor}
|
||||
onChange={(value) => setAttributes({flexColor: value})}
|
||||
/>)}
|
||||
{ isFlex && (<SelectControl
|
||||
label={__('Ratio', 'woocommerce-paypal-payments')}
|
||||
options={[
|
||||
{ label: __( '8x1', 'woocommerce-paypal-payments' ), value: '8x1' },
|
||||
{ label: __( '20x1', 'woocommerce-paypal-payments' ), value: '20x1' },
|
||||
]}
|
||||
value={flexRatio}
|
||||
onChange={(value) => setAttributes({flexRatio: value})}
|
||||
/>)}
|
||||
{!isFlex && (
|
||||
<SelectControl
|
||||
label={__('Logo', 'woocommerce-paypal-payments')}
|
||||
options={[
|
||||
{ label: __('Full logo', 'woocommerce-paypal-payments'), value: 'primary' },
|
||||
{ label: __('Monogram', 'woocommerce-paypal-payments'), value: 'alternative' },
|
||||
{ label: __('Inline', 'woocommerce-paypal-payments'), value: 'inline' },
|
||||
{ label: __('Message only', 'woocommerce-paypal-payments'), value: 'none' },
|
||||
]}
|
||||
value={logo}
|
||||
onChange={(value) => setAttributes({ logo: value })}
|
||||
/>
|
||||
)}
|
||||
{!isFlex && logo === 'primary' && (
|
||||
<SelectControl
|
||||
label={__('Logo Position', 'woocommerce-paypal-payments')}
|
||||
options={[
|
||||
{ label: __('Left', 'woocommerce-paypal-payments'), value: 'left' },
|
||||
{ label: __('Right', 'woocommerce-paypal-payments'), value: 'right' },
|
||||
{ label: __('Top', 'woocommerce-paypal-payments'), value: 'top' },
|
||||
]}
|
||||
value={position}
|
||||
onChange={(value) => setAttributes({ position: value })}
|
||||
/>
|
||||
)}
|
||||
{!isFlex && (
|
||||
<SelectControl
|
||||
label={__('Text Color', 'woocommerce-paypal-payments')}
|
||||
options={[
|
||||
{ label: __('Black / Blue logo', 'woocommerce-paypal-payments'), value: 'black' },
|
||||
{ label: __('White / White logo', 'woocommerce-paypal-payments'), value: 'white' },
|
||||
{ label: __('Monochrome', 'woocommerce-paypal-payments'), value: 'monochrome' },
|
||||
{ label: __('Black / Gray logo', 'woocommerce-paypal-payments'), value: 'grayscale' },
|
||||
]}
|
||||
value={color}
|
||||
onChange={(value) => setAttributes({ color: value })}
|
||||
/>
|
||||
)}
|
||||
{!isFlex && (
|
||||
<SelectControl
|
||||
label={__('Text Size', 'woocommerce-paypal-payments')}
|
||||
options={[
|
||||
{ label: __('Small', 'woocommerce-paypal-payments'), value: '12' },
|
||||
{ label: __('Medium', 'woocommerce-paypal-payments'), value: '14' },
|
||||
{ label: __('Large', 'woocommerce-paypal-payments'), value: '16' },
|
||||
]}
|
||||
value={size}
|
||||
onChange={(value) => setAttributes({ size: value })}
|
||||
/>
|
||||
)}
|
||||
{isFlex && (
|
||||
<SelectControl
|
||||
label={__('Color', 'woocommerce-paypal-payments')}
|
||||
options={[
|
||||
{ label: __('Blue', 'woocommerce-paypal-payments'), value: 'blue' },
|
||||
{ label: __('Black', 'woocommerce-paypal-payments'), value: 'black' },
|
||||
{ label: __('White', 'woocommerce-paypal-payments'), value: 'white' },
|
||||
{ label: __('White (no border)', 'woocommerce-paypal-payments'), value: 'white-no-border' },
|
||||
]}
|
||||
value={flexColor}
|
||||
onChange={(value) => setAttributes({ flexColor: value })}
|
||||
/>
|
||||
)}
|
||||
{isFlex && (
|
||||
<SelectControl
|
||||
label={__('Ratio', 'woocommerce-paypal-payments')}
|
||||
options={[
|
||||
{ label: __('8x1', 'woocommerce-paypal-payments'), value: '8x1' },
|
||||
{ label: __('20x1', 'woocommerce-paypal-payments'), value: '20x1' },
|
||||
]}
|
||||
value={flexRatio}
|
||||
onChange={(value) => setAttributes({ flexRatio: value })}
|
||||
/>
|
||||
)}
|
||||
<SelectControl
|
||||
label={ __( 'Placement page', 'woocommerce-paypal-payments' ) }
|
||||
help={ __( 'Used for the analytics dashboard in the merchant account.', 'woocommerce-paypal-payments' ) }
|
||||
|
@ -203,20 +212,23 @@ export default function Edit( { attributes, clientId, setAttributes } ) {
|
|||
value={ placement }
|
||||
onChange={ ( value ) => setAttributes( { placement: value } ) }
|
||||
/>
|
||||
</PanelBody>
|
||||
</InspectorControls>
|
||||
</PanelBody>
|
||||
</InspectorControls>
|
||||
<div {...props}>
|
||||
<div className={'ppcp-overlay-child'}>
|
||||
<PayPalMessages
|
||||
style={previewStyle}
|
||||
amount={amount}
|
||||
onRender={() => setRendered(true)}
|
||||
/>
|
||||
<div className='ppcp-overlay-child'>
|
||||
<PayPalScriptProvider options={urlParams}>
|
||||
<PayPalMessages
|
||||
style={previewStyle}
|
||||
forceReRender={[previewStyle]}
|
||||
onRender={() => setLoaded(true)}
|
||||
amount={amount}
|
||||
/>
|
||||
</PayPalScriptProvider>
|
||||
</div>
|
||||
<div className={'ppcp-overlay-child ppcp-unclicable-overlay'}> {/* make the message not clickable */}
|
||||
{!rendered && (<Spinner/>)}
|
||||
<div className='ppcp-overlay-child ppcp-unclicable-overlay'> {/* make the message not clickable */}
|
||||
{!loaded && <Spinner />}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import { registerBlockType } from '@wordpress/blocks';
|
||||
|
||||
import Edit from './edit';
|
||||
import save from './save';
|
||||
|
||||
const paypalIcon = (
|
||||
<svg width="584.798" height="720" viewBox="0 0 154.728 190.5">
|
||||
|
@ -18,7 +17,9 @@ const blockId = 'woocommerce-paypal-payments/paylater-messages';
|
|||
registerBlockType( blockId, {
|
||||
icon: paypalIcon,
|
||||
edit: Edit,
|
||||
save,
|
||||
save() {
|
||||
return null;
|
||||
},
|
||||
} );
|
||||
|
||||
document.addEventListener( 'DOMContentLoaded', () => {
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
import { useBlockProps } from '@wordpress/block-editor';
|
||||
|
||||
export default function save( { attributes } ) {
|
||||
const { layout, logo, position, color, size, flexColor, flexRatio, placement, id } = attributes;
|
||||
const paypalAttributes = layout === 'flex' ? {
|
||||
'data-pp-style-layout': 'flex',
|
||||
'data-pp-style-color': flexColor,
|
||||
'data-pp-style-ratio': flexRatio,
|
||||
} : {
|
||||
'data-pp-style-layout': 'text',
|
||||
'data-pp-style-logo-type': logo,
|
||||
'data-pp-style-logo-position': position,
|
||||
'data-pp-style-text-color': color,
|
||||
'data-pp-style-text-size': size,
|
||||
};
|
||||
if (placement && placement !== 'auto') {
|
||||
paypalAttributes['data-pp-placement'] = placement;
|
||||
}
|
||||
const props = {
|
||||
className: 'ppcp-paylater-message-block',
|
||||
id,
|
||||
...paypalAttributes,
|
||||
};
|
||||
|
||||
return <div { ...useBlockProps.save(props) }></div>;
|
||||
}
|
|
@ -9,10 +9,11 @@ declare(strict_types=1);
|
|||
|
||||
namespace WooCommerce\PayPalCommerce\PayLaterBlock;
|
||||
|
||||
use WooCommerce\PayPalCommerce\PayLaterBlock\PayLaterBlockRenderer;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
|
||||
return array(
|
||||
'paylater-block.url' => static function ( ContainerInterface $container ): string {
|
||||
'paylater-block.url' => static function ( ContainerInterface $container ): string {
|
||||
/**
|
||||
* Cannot return false for this path.
|
||||
*
|
||||
|
@ -23,4 +24,7 @@ return array(
|
|||
dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php'
|
||||
);
|
||||
},
|
||||
'paylater-block.renderer' => static function (): PayLaterBlockRenderer {
|
||||
return new PayLaterBlockRenderer();
|
||||
},
|
||||
);
|
||||
|
|
|
@ -99,7 +99,23 @@ class PayLaterBlockModule implements ModuleInterface {
|
|||
*
|
||||
* @psalm-suppress PossiblyFalseArgument
|
||||
*/
|
||||
register_block_type( dirname( realpath( __FILE__ ), 2 ) );
|
||||
register_block_type(
|
||||
dirname( realpath( __FILE__ ), 2 ),
|
||||
array(
|
||||
'render_callback' => function ( array $attributes ) use ( $c ) {
|
||||
$renderer = $c->get( 'paylater-block.renderer' );
|
||||
ob_start();
|
||||
// phpcs:ignore -- No need to escape it, the PayLaterBlockRenderer class is responsible for escaping.
|
||||
echo $renderer->render(
|
||||
// phpcs:ignore
|
||||
$attributes,
|
||||
// phpcs:ignore
|
||||
$c
|
||||
);
|
||||
return ob_get_clean();
|
||||
},
|
||||
)
|
||||
);
|
||||
},
|
||||
20
|
||||
);
|
||||
|
|
65
modules/ppcp-paylater-block/src/PayLaterBlockRenderer.php
Normal file
65
modules/ppcp-paylater-block/src/PayLaterBlockRenderer.php
Normal file
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
/**
|
||||
* Defines the PayLaterBlockRenderer class.
|
||||
*
|
||||
* This file is responsible for rendering the Pay Later Messaging block.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\PayLaterBlock
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\PayLaterBlock;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Class PayLaterBlockRenderer
|
||||
*/
|
||||
class PayLaterBlockRenderer {
|
||||
|
||||
/**
|
||||
* Renders the Pay Later Messaging block.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param ContainerInterface $c The container.
|
||||
* @return string The rendered HTML.
|
||||
*/
|
||||
public function render( array $attributes, ContainerInterface $c ): string {
|
||||
if ( PayLaterBlockModule::is_block_enabled( $c->get( 'wcgateway.settings.status' ) ) ) {
|
||||
|
||||
$html = '<div id="' . esc_attr( $attributes['id'] ?? '' ) . '" class="ppcp-messages" data-partner-attribution-id="Woo_PPCP"></div>';
|
||||
|
||||
$processor = new \WP_HTML_Tag_Processor( $html );
|
||||
|
||||
if ( $processor->next_tag( 'div' ) ) {
|
||||
$layout = $attributes['layout'] ?? 'text';
|
||||
|
||||
if ( 'flex' === $layout ) {
|
||||
$processor->set_attribute( 'data-pp-style-layout', 'flex' );
|
||||
$processor->set_attribute( 'data-pp-style-color', esc_attr( $attributes['flexColor'] ?? '' ) );
|
||||
$processor->set_attribute( 'data-pp-style-ratio', esc_attr( $attributes['flexRatio'] ?? '' ) );
|
||||
} else {
|
||||
$processor->set_attribute( 'data-pp-style-layout', 'text' );
|
||||
$processor->set_attribute( 'data-pp-style-logo-type', esc_attr( $attributes['logo'] ?? '' ) );
|
||||
$processor->set_attribute( 'data-pp-style-logo-position', esc_attr( $attributes['position'] ?? '' ) );
|
||||
$processor->set_attribute( 'data-pp-style-text-color', esc_attr( $attributes['color'] ?? '' ) );
|
||||
$processor->set_attribute( 'data-pp-style-text-size', esc_attr( $attributes['size'] ?? '' ) );
|
||||
}
|
||||
|
||||
if ( ( $attributes['placement'] ?? 'auto' ) !== 'auto' ) {
|
||||
$processor->set_attribute( 'data-pp-placement', esc_attr( $attributes['placement'] ) );
|
||||
}
|
||||
}
|
||||
|
||||
$updated_html = $processor->get_updated_html();
|
||||
|
||||
return sprintf(
|
||||
'<div id="ppcp-paylater-message-block" %1$s>%2$s</div>',
|
||||
wp_kses_data( get_block_wrapper_attributes() ),
|
||||
$updated_html
|
||||
);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
|
@ -1005,6 +1005,28 @@
|
|||
"@jridgewell/resolve-uri" "3.1.0"
|
||||
"@jridgewell/sourcemap-codec" "1.4.14"
|
||||
|
||||
"@paypal/paypal-js@^8.0.4":
|
||||
version "8.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@paypal/paypal-js/-/paypal-js-8.0.4.tgz#abe9f40f519b1d2c306adddfbe733be03eb26ce5"
|
||||
integrity sha512-91g5fhRBHGEBoikDzQT6uBn3PzlJQ75g0c3MvqVJqN0XRm5kHa9wz+6+Uaq8QQuxRzz5C2x55Zg057CW6EuwpQ==
|
||||
dependencies:
|
||||
promise-polyfill "^8.3.0"
|
||||
|
||||
"@paypal/react-paypal-js@^8.2.0":
|
||||
version "8.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@paypal/react-paypal-js/-/react-paypal-js-8.2.0.tgz#4b1a142bbb68e62dca4a92da4a6b5568f54901f0"
|
||||
integrity sha512-SworUfu0BNNcqoh0O53Ke4MFpx2m3qJRu3hayXvlluEEXJpKqGSV5aaSGFhbsZqi8hnbsx/hZR7BQbmqsggiGQ==
|
||||
dependencies:
|
||||
"@paypal/paypal-js" "^8.0.4"
|
||||
"@paypal/sdk-constants" "^1.0.122"
|
||||
|
||||
"@paypal/sdk-constants@^1.0.122":
|
||||
version "1.0.145"
|
||||
resolved "https://registry.yarnpkg.com/@paypal/sdk-constants/-/sdk-constants-1.0.145.tgz#f373cd3b7cf0409c28e121629b8f1855faf2e77b"
|
||||
integrity sha512-2tclrVX3L44YRJ09H4kkqma/UeAjRJarwH5SyPip10O5S+2ByE1HiyspAJ6hIWSjMngFVqjNyUCnrGcuQA3ldg==
|
||||
dependencies:
|
||||
hi-base32 "^0.5.0"
|
||||
|
||||
"@types/eslint-scope@^3.7.3":
|
||||
version "3.7.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16"
|
||||
|
@ -1179,7 +1201,7 @@
|
|||
resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.7.0.tgz#e1993689ac42d2b16e9194376cfb6753f6254db1"
|
||||
integrity sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==
|
||||
|
||||
"@woocommerce/dependency-extraction-webpack-plugin@^2.2.0":
|
||||
"@woocommerce/dependency-extraction-webpack-plugin@2.2.0":
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@woocommerce/dependency-extraction-webpack-plugin/-/dependency-extraction-webpack-plugin-2.2.0.tgz#230d674a67585bc32e31bc28485bec99b41dbd1f"
|
||||
integrity sha512-0wDY3EIUwWrPm0KrWvt1cf2SZDSX7CzBXvv4TyCqWOPuVPvC/ajyY8kD1HTFI80q6/RHoxWf3BYCmhuBzPbe9A==
|
||||
|
@ -1599,6 +1621,11 @@ has@^1.0.3:
|
|||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
|
||||
hi-base32@^0.5.0:
|
||||
version "0.5.1"
|
||||
resolved "https://registry.yarnpkg.com/hi-base32/-/hi-base32-0.5.1.tgz#1279f2ddae2673219ea5870c2121d2a33132857e"
|
||||
integrity sha512-EmBBpvdYh/4XxsnUybsPag6VikPYnN30td+vQk+GI3qpahVEG9+gTkG0aXVxTjBqQ5T6ijbWIu77O+C5WFWsnA==
|
||||
|
||||
immutable@^4.0.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.1.0.tgz#f795787f0db780183307b9eb2091fcac1f6fafef"
|
||||
|
@ -1674,7 +1701,7 @@ jest-worker@^27.4.5:
|
|||
merge-stream "^2.0.0"
|
||||
supports-color "^8.0.0"
|
||||
|
||||
js-tokens@^4.0.0:
|
||||
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
|
||||
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
|
||||
|
@ -1745,6 +1772,13 @@ lodash.debounce@^4.0.8:
|
|||
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
|
||||
integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==
|
||||
|
||||
loose-envify@^1.1.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
|
||||
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
|
||||
dependencies:
|
||||
js-tokens "^3.0.0 || ^4.0.0"
|
||||
|
||||
make-dir@^3.0.2, make-dir@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f"
|
||||
|
@ -1789,6 +1823,11 @@ normalize-path@^3.0.0, normalize-path@~3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
||||
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
|
||||
|
||||
object-assign@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
|
||||
|
||||
p-limit@^2.2.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
|
||||
|
@ -1840,6 +1879,11 @@ pkg-dir@^4.1.0, pkg-dir@^4.2.0:
|
|||
dependencies:
|
||||
find-up "^4.0.0"
|
||||
|
||||
promise-polyfill@^8.3.0:
|
||||
version "8.3.0"
|
||||
resolved "https://registry.yarnpkg.com/promise-polyfill/-/promise-polyfill-8.3.0.tgz#9284810268138d103807b11f4e23d5e945a4db63"
|
||||
integrity sha512-H5oELycFml5yto/atYqmjyigJoAo3+OXwolYiH7OfQuYlAqhxNvTfiNMbV9hsC6Yp83yE5r2KTVmtrG6R9i6Pg==
|
||||
|
||||
punycode@^2.1.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||
|
@ -1852,6 +1896,23 @@ randombytes@^2.1.0:
|
|||
dependencies:
|
||||
safe-buffer "^5.1.0"
|
||||
|
||||
react-dom@^17.0.0:
|
||||
version "17.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"
|
||||
integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
scheduler "^0.20.2"
|
||||
|
||||
react@^17.0.0:
|
||||
version "17.0.2"
|
||||
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
|
||||
integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
readdirp@~3.6.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
|
||||
|
@ -1957,6 +2018,14 @@ sass@^1.42.1:
|
|||
immutable "^4.0.0"
|
||||
source-map-js ">=0.6.2 <2.0.0"
|
||||
|
||||
scheduler@^0.20.2:
|
||||
version "0.20.2"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91"
|
||||
integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
object-assign "^4.1.1"
|
||||
|
||||
schema-utils@^2.6.5:
|
||||
version "2.7.1"
|
||||
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7"
|
||||
|
|
14
modules/ppcp-paylater-wc-blocks/.babelrc
Normal file
14
modules/ppcp-paylater-wc-blocks/.babelrc
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"presets": [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
"useBuiltIns": "usage",
|
||||
"corejs": "3.25.0"
|
||||
}
|
||||
],
|
||||
[
|
||||
"@babel/preset-react"
|
||||
]
|
||||
]
|
||||
}
|
3
modules/ppcp-paylater-wc-blocks/.gitignore
vendored
Normal file
3
modules/ppcp-paylater-wc-blocks/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
node_modules
|
||||
assets/js
|
||||
assets/css
|
17
modules/ppcp-paylater-wc-blocks/composer.json
Normal file
17
modules/ppcp-paylater-wc-blocks/composer.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "woocommerce/ppcp-paylater-wc-blocks",
|
||||
"type": "dhii-mod",
|
||||
"description": "Pay Later WooCommerce Blocks module for PPCP",
|
||||
"license": "GPL-2.0",
|
||||
"require": {
|
||||
"php": "^7.2 | ^8.0",
|
||||
"dhii/module-interface": "^0.3.0-alpha1"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"WooCommerce\\PayPalCommerce\\PayLaterWCBlocks\\": "src"
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true
|
||||
}
|
156
modules/ppcp-paylater-wc-blocks/composer.lock
generated
Normal file
156
modules/ppcp-paylater-wc-blocks/composer.lock
generated
Normal file
|
@ -0,0 +1,156 @@
|
|||
{
|
||||
"_readme": [
|
||||
"This file locks the dependencies of your project to a known state",
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "bbff959c846d515b5cfe39e6d175972b",
|
||||
"packages": [
|
||||
{
|
||||
"name": "container-interop/service-provider",
|
||||
"version": "v0.4.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/container-interop/service-provider.git",
|
||||
"reference": "e04441ca21ef03e10dce70b0af29269281eec6dc"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/container-interop/service-provider/zipball/e04441ca21ef03e10dce70b0af29269281eec6dc",
|
||||
"reference": "e04441ca21ef03e10dce70b0af29269281eec6dc",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"psr/container": "^1.0 || ^2.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Interop\\Container\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "Promoting container interoperability through standard service providers",
|
||||
"homepage": "https://github.com/container-interop/service-provider",
|
||||
"support": {
|
||||
"issues": "https://github.com/container-interop/service-provider/issues",
|
||||
"source": "https://github.com/container-interop/service-provider/tree/v0.4.1"
|
||||
},
|
||||
"time": "2023-12-14T14:50:12+00:00"
|
||||
},
|
||||
{
|
||||
"name": "dhii/module-interface",
|
||||
"version": "v0.3.0-alpha2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Dhii/module-interface.git",
|
||||
"reference": "0e39f167d7ed8990c82f5d2e6084159d1a502a5b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Dhii/module-interface/zipball/0e39f167d7ed8990c82f5d2e6084159d1a502a5b",
|
||||
"reference": "0e39f167d7ed8990c82f5d2e6084159d1a502a5b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"container-interop/service-provider": "^0.4",
|
||||
"php": "^7.1 | ^8.0",
|
||||
"psr/container": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7.0 | ^8.0 | ^9.0",
|
||||
"slevomat/coding-standard": "^6.0",
|
||||
"vimeo/psalm": "^3.11.7 | ^4.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-develop": "0.3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Dhii\\Modular\\Module\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Dhii Team",
|
||||
"email": "development@dhii.co"
|
||||
}
|
||||
],
|
||||
"description": "Interfaces for modules",
|
||||
"support": {
|
||||
"issues": "https://github.com/Dhii/module-interface/issues",
|
||||
"source": "https://github.com/Dhii/module-interface/tree/v0.3.0-alpha2"
|
||||
},
|
||||
"time": "2021-08-23T08:23:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/container",
|
||||
"version": "1.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/php-fig/container.git",
|
||||
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/php-fig/container/zipball/513e0666f7216c7459170d56df27dfcefe1689ea",
|
||||
"reference": "513e0666f7216c7459170d56df27dfcefe1689ea",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.4.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Psr\\Container\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "PHP-FIG",
|
||||
"homepage": "https://www.php-fig.org/"
|
||||
}
|
||||
],
|
||||
"description": "Common Container Interface (PHP FIG PSR-11)",
|
||||
"homepage": "https://github.com/php-fig/container",
|
||||
"keywords": [
|
||||
"PSR-11",
|
||||
"container",
|
||||
"container-interface",
|
||||
"container-interop",
|
||||
"psr"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/php-fig/container/issues",
|
||||
"source": "https://github.com/php-fig/container/tree/1.1.2"
|
||||
},
|
||||
"time": "2021-11-05T16:50:12+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [],
|
||||
"aliases": [],
|
||||
"minimum-stability": "dev",
|
||||
"stability-flags": [],
|
||||
"prefer-stable": true,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
"php": "^7.2 | ^8.0"
|
||||
},
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.3.0"
|
||||
}
|
12
modules/ppcp-paylater-wc-blocks/extensions.php
Normal file
12
modules/ppcp-paylater-wc-blocks/extensions.php
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
/**
|
||||
* The Pay Later WooCommerce Blocks module extensions.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\PayLaterWCBlocks
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\PayLaterWCBlocks;
|
||||
|
||||
return array();
|
16
modules/ppcp-paylater-wc-blocks/module.php
Normal file
16
modules/ppcp-paylater-wc-blocks/module.php
Normal file
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
/**
|
||||
* The Pay Later WooCommerce Blocks module.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\PayLaterWCBlocks
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\PayLaterWCBlocks;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
||||
|
||||
return static function (): ModuleInterface {
|
||||
return new PayLaterWCBlocksModule();
|
||||
};
|
36
modules/ppcp-paylater-wc-blocks/package.json
Normal file
36
modules/ppcp-paylater-wc-blocks/package.json
Normal file
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"name": "ppcp-paylater-wc-blocks",
|
||||
"version": "1.0.0",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"browserslist": [
|
||||
"> 0.5%",
|
||||
"Safari >= 8",
|
||||
"Chrome >= 41",
|
||||
"Firefox >= 43",
|
||||
"Edge >= 14"
|
||||
],
|
||||
"dependencies": {
|
||||
"@paypal/react-paypal-js": "^8.2.0",
|
||||
"core-js": "^3.25.0",
|
||||
"react": "^17.0.0",
|
||||
"react-dom": "^17.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.19",
|
||||
"@babel/preset-env": "^7.19",
|
||||
"@babel/preset-react": "^7.18.6",
|
||||
"@woocommerce/dependency-extraction-webpack-plugin": "2.2.0",
|
||||
"babel-loader": "^8.2",
|
||||
"cross-env": "^7.0.3",
|
||||
"file-loader": "^6.2.0",
|
||||
"sass": "^1.42.1",
|
||||
"sass-loader": "^12.1.0",
|
||||
"webpack": "^5.76",
|
||||
"webpack-cli": "^4.10"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "cross-env BABEL_ENV=default NODE_ENV=production webpack",
|
||||
"watch": "cross-env BABEL_ENV=default NODE_ENV=production webpack --watch",
|
||||
"dev": "cross-env BABEL_ENV=default webpack --watch"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"$schema": "https://schemas.wp.org/trunk/block.json",
|
||||
"apiVersion": 3,
|
||||
"name": "woocommerce-paypal-payments/cart-paylater-messages",
|
||||
"title": "Cart - PayPal Pay Later messaging",
|
||||
"category": "woocommerce-paypal-payments",
|
||||
"description": "PayPal Pay Later messaging will be displayed for eligible customers. Customers automatically see the most relevant Pay Later offering.",
|
||||
"example": {},
|
||||
"parent": [ "woocommerce/cart-totals-block" ],
|
||||
"attributes": {
|
||||
"blockId": {
|
||||
"type": "string",
|
||||
"default": "woocommerce-paypal-payments/cart-paylater-messages"
|
||||
},
|
||||
"ppcpId": {
|
||||
"type": "string"
|
||||
},
|
||||
"lock": {
|
||||
"type": "object",
|
||||
"default": {
|
||||
"remove": true,
|
||||
"move": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"supports": {
|
||||
"html": false,
|
||||
"inserter": false,
|
||||
"multiple": false
|
||||
},
|
||||
"textdomain": "woocommerce-paypal-payments",
|
||||
"editorScript": "ppcp-cart-paylater-block"
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
(function(wp) {
|
||||
const { createBlock } = wp.blocks;
|
||||
const { select, dispatch, subscribe } = wp.data;
|
||||
const getBlocks = () => select('core/block-editor').getBlocks() || [];
|
||||
|
||||
const { addFilter } = wp.hooks;
|
||||
const { assign } = lodash;
|
||||
|
||||
// We need to make sure the block is unlocked so that it doesn't get automatically inserted as the last block
|
||||
addFilter(
|
||||
'blocks.registerBlockType',
|
||||
'woocommerce-paypal-payments/modify-cart-paylater-messages',
|
||||
(settings, name) => {
|
||||
if (name === 'woocommerce-paypal-payments/cart-paylater-messages') {
|
||||
const newAttributes = assign({}, settings.attributes, {
|
||||
lock: assign({}, settings.attributes.lock, {
|
||||
default: assign({}, settings.attributes.lock.default, {
|
||||
remove: false
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
return assign({}, settings, {
|
||||
attributes: newAttributes
|
||||
});
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Subscribes to changes in the block editor, specifically checking for the presence of 'woocommerce/cart'.
|
||||
*/
|
||||
subscribe(() => {
|
||||
const currentBlocks = getBlocks();
|
||||
|
||||
currentBlocks.forEach(block => {
|
||||
if (block.name === 'woocommerce/cart') {
|
||||
ensurePayLaterBlockExists(block);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Ensures the 'woocommerce-paypal-payments/cart-paylater-messages' block exists inside the 'woocommerce/cart' block.
|
||||
* @param {Object} cartBlock - The cart block instance.
|
||||
*/
|
||||
function ensurePayLaterBlockExists(cartBlock) {
|
||||
const payLaterBlock = findBlockByName(cartBlock.innerBlocks, 'woocommerce-paypal-payments/cart-paylater-messages');
|
||||
if (!payLaterBlock) {
|
||||
waitForBlock('woocommerce/cart-totals-block', 'woocommerce-paypal-payments/cart-paylater-messages', 'woocommerce/cart-order-summary-block');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for a specific block to appear using async/await pattern before executing the insertBlockAfter function.
|
||||
* @param {string} targetBlockName - Name of the block to wait for.
|
||||
* @param {string} newBlockName - Name of the new block to insert after the target.
|
||||
* @param {string} anchorBlockName - Name of the anchor block to determine position.
|
||||
* @param {number} attempts - The number of attempts made to find the target block.
|
||||
*/
|
||||
async function waitForBlock(targetBlockName, newBlockName, anchorBlockName = '', attempts = 0) {
|
||||
const targetBlock = findBlockByName(getBlocks(), targetBlockName);
|
||||
if (targetBlock) {
|
||||
await delay(1000); // We need this to ensure the block is fully rendered
|
||||
insertBlockAfter(targetBlockName, newBlockName, anchorBlockName);
|
||||
} else if (attempts < 10) { // Poll up to 10 times
|
||||
await delay(1000); // Wait 1 second before retrying
|
||||
await waitForBlock(targetBlockName, newBlockName, anchorBlockName, attempts + 1);
|
||||
} else {
|
||||
console.log('Failed to find target block after several attempts.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delays execution by a given number of milliseconds.
|
||||
* @param {number} ms - Milliseconds to delay.
|
||||
* @return {Promise} A promise that resolves after the delay.
|
||||
*/
|
||||
function delay(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a block after a specified block if it doesn't already exist.
|
||||
* @param {string} targetBlockName - Name of the block to find.
|
||||
* @param {string} newBlockName - Name of the new block to insert.
|
||||
* @param {string} anchorBlockName - Name of the anchor block to determine position.
|
||||
*/
|
||||
function insertBlockAfter(targetBlockName, newBlockName, anchorBlockName = '') {
|
||||
const targetBlock = findBlockByName(getBlocks(), targetBlockName);
|
||||
if (!targetBlock) {
|
||||
// Target block not found
|
||||
return;
|
||||
}
|
||||
|
||||
const parentBlock = select('core/block-editor').getBlock(targetBlock.clientId);
|
||||
if (parentBlock.innerBlocks.some(block => block.name === newBlockName)) {
|
||||
// The block is already inserted next to the target block
|
||||
return;
|
||||
}
|
||||
|
||||
let offset = 0;
|
||||
if (anchorBlockName !== '') {
|
||||
// Find the anchor block and calculate the offset
|
||||
const anchorIndex = parentBlock.innerBlocks.findIndex(block => block.name === anchorBlockName);
|
||||
offset = parentBlock.innerBlocks.length - (anchorIndex + 1);
|
||||
}
|
||||
|
||||
const newBlock = createBlock(newBlockName);
|
||||
|
||||
// Insert the block at the correct position
|
||||
dispatch('core/block-editor').insertBlock(newBlock, parentBlock.innerBlocks.length - offset, parentBlock.clientId);
|
||||
|
||||
// Lock the block after it has been inserted
|
||||
dispatch('core/block-editor').updateBlockAttributes(newBlock.clientId, {
|
||||
lock: { remove: true }
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively searches for a block by name among all blocks.
|
||||
* @param {Array} blocks - The array of blocks to search.
|
||||
* @param {string} blockName - The name of the block to find.
|
||||
* @returns {Object|null} The found block, or null if not found.
|
||||
*/
|
||||
function findBlockByName(blocks, blockName) {
|
||||
for (const block of blocks) {
|
||||
if (block.name === blockName) {
|
||||
return block;
|
||||
}
|
||||
if (block.innerBlocks.length > 0) {
|
||||
const foundBlock = findBlockByName(block.innerBlocks, blockName);
|
||||
if (foundBlock) {
|
||||
return foundBlock;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
})(window.wp);
|
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { registerBlockType } from '@wordpress/blocks';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import Edit from './edit';
|
||||
import metadata from './block.json';
|
||||
|
||||
const paypalIcon = (
|
||||
<svg width="584.798" height="720" viewBox="0 0 154.728 190.5">
|
||||
<g transform="translate(898.192 276.071)">
|
||||
<path
|
||||
clipPath="none"
|
||||
d="M-837.663-237.968a5.49 5.49 0 0 0-5.423 4.633l-9.013 57.15-8.281 52.514-.005.044.01-.044 8.281-52.514c.421-2.669 2.719-4.633 5.42-4.633h26.404c26.573 0 49.127-19.387 53.246-45.658.314-1.996.482-3.973.52-5.924v-.003h-.003c-6.753-3.543-14.683-5.565-23.372-5.565z"
|
||||
fill="#001c64"
|
||||
/>
|
||||
<path
|
||||
clipPath="none"
|
||||
d="M-766.506-232.402c-.037 1.951-.207 3.93-.52 5.926-4.119 26.271-26.673 45.658-53.246 45.658h-26.404c-2.701 0-4.999 1.964-5.42 4.633l-8.281 52.514-5.197 32.947a4.46 4.46 0 0 0 4.405 5.153h28.66a5.49 5.49 0 0 0 5.423-4.633l7.55-47.881c.423-2.669 2.722-4.636 5.423-4.636h16.876c26.573 0 49.124-19.386 53.243-45.655 2.924-18.649-6.46-35.614-22.511-44.026z"
|
||||
fill="#0070e0"
|
||||
/>
|
||||
<path
|
||||
clipPath="none"
|
||||
d="M-870.225-276.071a5.49 5.49 0 0 0-5.423 4.636l-22.489 142.608a4.46 4.46 0 0 0 4.405 5.156h33.351l8.281-52.514 9.013-57.15a5.49 5.49 0 0 1 5.423-4.633h47.782c8.691 0 16.621 2.025 23.375 5.563.46-23.917-19.275-43.666-46.412-43.666z"
|
||||
fill="#003087"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
||||
registerBlockType(metadata, {
|
||||
icon: paypalIcon,
|
||||
edit: Edit,
|
||||
save() {
|
||||
return null;
|
||||
},
|
||||
});
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
import { useState, useEffect } from '@wordpress/element';
|
||||
import { InspectorControls, useBlockProps } from '@wordpress/block-editor';
|
||||
import { PanelBody, Spinner } from '@wordpress/components';
|
||||
import { PayPalScriptProvider, PayPalMessages } from '@paypal/react-paypal-js';
|
||||
import { useScriptParams } from '../../../../ppcp-paylater-block/resources/js/hooks/script-params';
|
||||
|
||||
export default function Edit({ attributes, clientId, setAttributes }) {
|
||||
const { ppcpId } = attributes;
|
||||
|
||||
const [loaded, setLoaded] = useState(false);
|
||||
|
||||
let amount;
|
||||
const postContent = String(wp.data.select('core/editor')?.getEditedPostContent());
|
||||
if (postContent.includes('woocommerce/checkout') || postContent.includes('woocommerce/cart')) {
|
||||
amount = 50.0;
|
||||
}
|
||||
|
||||
const cartConfig = PcpCartPayLaterBlock.config.cart;
|
||||
|
||||
// Dynamically setting previewStyle based on the layout attribute
|
||||
let previewStyle = {};
|
||||
if (cartConfig.layout === 'flex') {
|
||||
previewStyle = {
|
||||
layout: cartConfig.layout,
|
||||
color: cartConfig.color,
|
||||
ratio: cartConfig.ratio,
|
||||
};
|
||||
} else {
|
||||
previewStyle = {
|
||||
layout: cartConfig.layout,
|
||||
logo: {
|
||||
position: cartConfig['logo-position'],
|
||||
type: cartConfig['logo-type'],
|
||||
},
|
||||
text: {
|
||||
color: cartConfig['text-color'],
|
||||
size: cartConfig['text-size'],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
let classes = ['ppcp-paylater-block-preview', 'ppcp-overlay-parent'];
|
||||
if (PcpCartPayLaterBlock.vaultingEnabled || !PcpCartPayLaterBlock.placementEnabled) {
|
||||
classes = [...classes, 'ppcp-paylater-unavailable', 'block-editor-warning'];
|
||||
}
|
||||
const props = useBlockProps({ className: classes.join(' ') });
|
||||
|
||||
useEffect(() => {
|
||||
if (!ppcpId) {
|
||||
setAttributes({ ppcpId: `ppcp-${clientId}` });
|
||||
}
|
||||
}, [ppcpId, clientId]);
|
||||
|
||||
if (PcpCartPayLaterBlock.vaultingEnabled) {
|
||||
return (
|
||||
<div {...props}>
|
||||
<div className='block-editor-warning__contents'>
|
||||
<p className='block-editor-warning__message'>
|
||||
{__('Cart - Pay Later Messaging cannot be used while PayPal Vaulting is active. Disable PayPal Vaulting in the PayPal Payment settings to reactivate this block', 'woocommerce-paypal-payments')}
|
||||
</p>
|
||||
<div className='block-editor-warning__actions'>
|
||||
<span className='block-editor-warning__action'>
|
||||
<a href={PcpCartPayLaterBlock.settingsUrl}>
|
||||
<button type='button' className='components-button is-primary'>
|
||||
{__('PayPal Payments Settings', 'woocommerce-paypal-payments')}
|
||||
</button>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!PcpCartPayLaterBlock.placementEnabled) {
|
||||
return (
|
||||
<div {...props}>
|
||||
<div className='block-editor-warning__contents'>
|
||||
<p className='block-editor-warning__message'>
|
||||
{__('Cart - Pay Later Messaging cannot be used while the “Cart” messaging placement is disabled. Enable the placement in the PayPal Payments Pay Later settings to reactivate this block.', 'woocommerce-paypal-payments')}
|
||||
</p>
|
||||
<div className='block-editor-warning__actions'>
|
||||
<span className='block-editor-warning__action'>
|
||||
<a href={PcpCartPayLaterBlock.payLaterSettingsUrl}>
|
||||
<button type='button' className='components-button is-primary'>
|
||||
{__('PayPal Payments Settings', 'woocommerce-paypal-payments')}
|
||||
</button>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const scriptParams = useScriptParams(PcpCartPayLaterBlock.ajax.cart_script_params);
|
||||
if (scriptParams === null) {
|
||||
return <div {...props}><Spinner /></div>;
|
||||
}
|
||||
|
||||
const urlParams = {
|
||||
...scriptParams.url_params,
|
||||
components: 'messages',
|
||||
dataNamespace: 'ppcp-block-editor-cart-paylater-message',
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<InspectorControls>
|
||||
<PanelBody title={__('Customize your messaging', 'woocommerce-paypal-payments')}>
|
||||
<p>
|
||||
{__('Choose the layout and color of your messaging in the PayPal Payments Pay Later settings for the “Cart” messaging placement.', 'woocommerce-paypal-payments')}
|
||||
</p>
|
||||
<a href={PcpCartPayLaterBlock.payLaterSettingsUrl}>
|
||||
<button type='button' className='components-button is-primary'>
|
||||
{__('PayPal Payments Settings', 'woocommerce-paypal-payments')}
|
||||
</button>
|
||||
</a>
|
||||
</PanelBody>
|
||||
</InspectorControls>
|
||||
<div {...props}>
|
||||
<div className='ppcp-overlay-child'>
|
||||
<PayPalScriptProvider options={urlParams}>
|
||||
<PayPalMessages
|
||||
style={previewStyle}
|
||||
onRender={() => setLoaded(true)}
|
||||
amount={amount}
|
||||
/>
|
||||
</PayPalScriptProvider>
|
||||
</div>
|
||||
<div className='ppcp-overlay-child ppcp-unclicable-overlay'> {/* make the message not clickable */}
|
||||
{!loaded && <Spinner />}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"$schema": "https://schemas.wp.org/trunk/block.json",
|
||||
"apiVersion": 3,
|
||||
"name": "woocommerce-paypal-payments/checkout-paylater-messages",
|
||||
"title": "Checkout - PayPal Pay Later messaging",
|
||||
"category": "woocommerce-paypal-payments",
|
||||
"description": "PayPal Pay Later messaging will be displayed for eligible customers. Customers automatically see the most relevant Pay Later offering.",
|
||||
"example": {},
|
||||
"parent": [ "woocommerce/checkout-totals-block" ],
|
||||
"attributes": {
|
||||
"blockId": {
|
||||
"type": "string",
|
||||
"default": "woocommerce-paypal-payments/checkout-paylater-messages"
|
||||
},
|
||||
"ppcpId": {
|
||||
"type": "string"
|
||||
},
|
||||
"lock": {
|
||||
"type": "object",
|
||||
"default": {
|
||||
"remove": true,
|
||||
"move": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"supports": {
|
||||
"html": false,
|
||||
"inserter": false,
|
||||
"multiple": false
|
||||
},
|
||||
"textdomain": "woocommerce-paypal-payments",
|
||||
"editorScript": "ppcp-checkout-paylater-block"
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { registerBlockType } from '@wordpress/blocks';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import Edit from './edit';
|
||||
import metadata from './block.json';
|
||||
|
||||
const paypalIcon = (
|
||||
<svg width="584.798" height="720" viewBox="0 0 154.728 190.5">
|
||||
<g transform="translate(898.192 276.071)">
|
||||
<path
|
||||
clipPath="none"
|
||||
d="M-837.663-237.968a5.49 5.49 0 0 0-5.423 4.633l-9.013 57.15-8.281 52.514-.005.044.01-.044 8.281-52.514c.421-2.669 2.719-4.633 5.42-4.633h26.404c26.573 0 49.127-19.387 53.246-45.658.314-1.996.482-3.973.52-5.924v-.003h-.003c-6.753-3.543-14.683-5.565-23.372-5.565z"
|
||||
fill="#001c64"
|
||||
/>
|
||||
<path
|
||||
clipPath="none"
|
||||
d="M-766.506-232.402c-.037 1.951-.207 3.93-.52 5.926-4.119 26.271-26.673 45.658-53.246 45.658h-26.404c-2.701 0-4.999 1.964-5.42 4.633l-8.281 52.514-5.197 32.947a4.46 4.46 0 0 0 4.405 5.153h28.66a5.49 5.49 0 0 0 5.423-4.633l7.55-47.881c.423-2.669 2.722-4.636 5.423-4.636h16.876c26.573 0 49.124-19.386 53.243-45.655 2.924-18.649-6.46-35.614-22.511-44.026z"
|
||||
fill="#0070e0"
|
||||
/>
|
||||
<path
|
||||
clipPath="none"
|
||||
d="M-870.225-276.071a5.49 5.49 0 0 0-5.423 4.636l-22.489 142.608a4.46 4.46 0 0 0 4.405 5.156h33.351l8.281-52.514 9.013-57.15a5.49 5.49 0 0 1 5.423-4.633h47.782c8.691 0 16.621 2.025 23.375 5.563.46-23.917-19.275-43.666-46.412-43.666z"
|
||||
fill="#003087"
|
||||
/>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
|
||||
registerBlockType(metadata, {
|
||||
icon: paypalIcon,
|
||||
edit: Edit,
|
||||
save() {
|
||||
return null;
|
||||
},
|
||||
});
|
||||
|
|
@ -0,0 +1,132 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
import { useState, useEffect } from '@wordpress/element';
|
||||
import { InspectorControls, useBlockProps } from '@wordpress/block-editor';
|
||||
import { PanelBody, Spinner } from '@wordpress/components';
|
||||
import { PayPalScriptProvider, PayPalMessages } from '@paypal/react-paypal-js';
|
||||
import { useScriptParams } from '../../../../ppcp-paylater-block/resources/js/hooks/script-params';
|
||||
|
||||
export default function Edit({ attributes, clientId, setAttributes }) {
|
||||
const { ppcpId } = attributes;
|
||||
|
||||
const [loaded, setLoaded] = useState(false);
|
||||
|
||||
let amount = undefined;
|
||||
const postContent = String(wp.data.select('core/editor')?.getEditedPostContent());
|
||||
if (postContent.includes('woocommerce/checkout') || postContent.includes('woocommerce/cart')) {
|
||||
amount = 50.0;
|
||||
}
|
||||
|
||||
const checkoutConfig = PcpCheckoutPayLaterBlock.config.checkout;
|
||||
|
||||
// Dynamically setting previewStyle based on the layout attribute
|
||||
let previewStyle = {};
|
||||
if (checkoutConfig.layout === 'flex') {
|
||||
previewStyle = {
|
||||
layout: checkoutConfig.layout,
|
||||
color: checkoutConfig.color,
|
||||
ratio: checkoutConfig.ratio,
|
||||
};
|
||||
} else {
|
||||
previewStyle = {
|
||||
layout: checkoutConfig.layout,
|
||||
logo: {
|
||||
position: checkoutConfig['logo-position'],
|
||||
type: checkoutConfig['logo-type'],
|
||||
},
|
||||
text: {
|
||||
color: checkoutConfig['text-color'],
|
||||
size: checkoutConfig['text-size'],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
let classes = ['ppcp-paylater-block-preview', 'ppcp-overlay-parent'];
|
||||
if (PcpCheckoutPayLaterBlock.vaultingEnabled || !PcpCheckoutPayLaterBlock.placementEnabled) {
|
||||
classes = ['ppcp-paylater-block-preview', 'ppcp-paylater-unavailable', 'block-editor-warning'];
|
||||
}
|
||||
const props = useBlockProps({ className: classes });
|
||||
|
||||
useEffect(() => {
|
||||
if (!ppcpId) {
|
||||
setAttributes({ ppcpId: 'ppcp-' + clientId });
|
||||
}
|
||||
}, [ppcpId, clientId]);
|
||||
|
||||
if (PcpCheckoutPayLaterBlock.vaultingEnabled) {
|
||||
return (
|
||||
<div {...props}>
|
||||
<div className={'block-editor-warning__contents'}>
|
||||
<p className={'block-editor-warning__message'}>{__('Checkout - Pay Later Messaging cannot be used while PayPal Vaulting is active. Disable PayPal Vaulting in the PayPal Payment settings to reactivate this block', 'woocommerce-paypal-payments')}</p>
|
||||
<div className={'block-editor-warning__actions'}>
|
||||
<span className={'block-editor-warning__action'}>
|
||||
<a href={PcpCheckoutPayLaterBlock.settingsUrl}>
|
||||
<button type={'button'} className={'components-button is-primary'}>
|
||||
{__('PayPal Payments Settings', 'woocommerce-paypal-payments')}
|
||||
</button>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (!PcpCheckoutPayLaterBlock.placementEnabled) {
|
||||
return (
|
||||
<div {...props}>
|
||||
<div className={'block-editor-warning__contents'}>
|
||||
<p className={'block-editor-warning__message'}>{__('Checkout - Pay Later Messaging cannot be used while the “Checkout” messaging placement is disabled. Enable the placement in the PayPal Payments Pay Later settings to reactivate this block.', 'woocommerce-paypal-payments')}</p>
|
||||
<div className={'block-editor-warning__actions'}>
|
||||
<span className={'block-editor-warning__action'}>
|
||||
<a href={PcpCheckoutPayLaterBlock.payLaterSettingsUrl}>
|
||||
<button type={'button'} className={'components-button is-primary'}>
|
||||
{__('PayPal Payments Settings', 'woocommerce-paypal-payments')}
|
||||
</button>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const scriptParams = useScriptParams(PcpCheckoutPayLaterBlock.ajax.cart_script_params);
|
||||
if (scriptParams === null) {
|
||||
return <div {...props}><Spinner/></div>;
|
||||
}
|
||||
|
||||
const urlParams = {
|
||||
...scriptParams.url_params,
|
||||
components: 'messages',
|
||||
dataNamespace: 'ppcp-block-editor-checkout-paylater-message',
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<InspectorControls>
|
||||
<PanelBody title={__('Customize your messaging', 'woocommerce-paypal-payments')}>
|
||||
<p>{__('Choose the layout and color of your messaging in the PayPal Payments Pay Later settings for the “Checkout” messaging placement.', 'woocommerce-paypal-payments')}</p>
|
||||
<a href={PcpCheckoutPayLaterBlock.payLaterSettingsUrl}>
|
||||
<button type={'button'} className={'components-button is-primary'}>
|
||||
{__('PayPal Payments Settings', 'woocommerce-paypal-payments')}
|
||||
</button>
|
||||
</a>
|
||||
</PanelBody>
|
||||
</InspectorControls>
|
||||
<div {...props}>
|
||||
<div className={'ppcp-overlay-child'}>
|
||||
<PayPalScriptProvider options={urlParams}>
|
||||
<PayPalMessages
|
||||
style={previewStyle}
|
||||
onRender={() => setLoaded(true)}
|
||||
amount={amount}
|
||||
/>
|
||||
</PayPalScriptProvider>
|
||||
</div>
|
||||
<div className={'ppcp-overlay-child ppcp-unclicable-overlay'}> {/* make the message not clickable */}
|
||||
{!loaded && <Spinner/>}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
58
modules/ppcp-paylater-wc-blocks/services.php
Normal file
58
modules/ppcp-paylater-wc-blocks/services.php
Normal file
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
/**
|
||||
* The Pay Later WooCommerce Blocks module services.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\PayLaterWCBlocks
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\PayLaterWCBlocks;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
|
||||
return array(
|
||||
'paylater-wc-blocks.url' => static function ( ContainerInterface $container ): string {
|
||||
/**
|
||||
* Cannot return false for this path.
|
||||
*
|
||||
* @psalm-suppress PossiblyFalseArgument
|
||||
*/
|
||||
return plugins_url(
|
||||
'/modules/ppcp-paylater-wc-blocks/',
|
||||
dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php'
|
||||
);
|
||||
},
|
||||
|
||||
'paylater-wc-blocks.cart-renderer' => static function ( ContainerInterface $container ): PayLaterWCBlocksRenderer {
|
||||
$settings = $container->get( 'wcgateway.settings' );
|
||||
return new PayLaterWCBlocksRenderer(
|
||||
array(
|
||||
'placement' => 'cart',
|
||||
'layout' => $settings->has( 'pay_later_cart_message_layout' ) ? $settings->get( 'pay_later_cart_message_layout' ) : '',
|
||||
'position' => $settings->has( 'pay_later_cart_message_position' ) ? $settings->get( 'pay_later_cart_message_position' ) : '',
|
||||
'logo' => $settings->has( 'pay_later_cart_message_logo' ) ? $settings->get( 'pay_later_cart_message_logo' ) : '',
|
||||
'text_size' => $settings->has( 'pay_later_cart_message_text_size' ) ? $settings->get( 'pay_later_cart_message_text_size' ) : '',
|
||||
'color' => $settings->has( 'pay_later_cart_message_color' ) ? $settings->get( 'pay_later_cart_message_color' ) : '',
|
||||
'flex_color' => $settings->has( 'pay_later_cart_message_flex_color' ) ? $settings->get( 'pay_later_cart_message_flex_color' ) : '',
|
||||
'flex_ratio' => $settings->has( 'pay_later_cart_message_flex_ratio' ) ? $settings->get( 'pay_later_cart_message_flex_ratio' ) : '',
|
||||
)
|
||||
);
|
||||
},
|
||||
'paylater-wc-blocks.checkout-renderer' => static function ( ContainerInterface $container ): PayLaterWCBlocksRenderer {
|
||||
$settings = $container->get( 'wcgateway.settings' );
|
||||
return new PayLaterWCBlocksRenderer(
|
||||
array(
|
||||
'payment',
|
||||
'layout' => $settings->has( 'pay_later_checkout_message_layout' ) ? $settings->get( 'pay_later_checkout_message_layout' ) : '',
|
||||
'position' => $settings->has( 'pay_later_checkout_message_position' ) ? $settings->get( 'pay_later_checkout_message_position' ) : '',
|
||||
'logo' => $settings->has( 'pay_later_checkout_message_logo' ) ? $settings->get( 'pay_later_checkout_message_logo' ) : '',
|
||||
'text_size' => $settings->has( 'pay_later_checkout_message_text_size' ) ? $settings->get( 'pay_later_checkout_message_text_size' ) : '',
|
||||
'color' => $settings->has( 'pay_later_checkout_message_color' ) ? $settings->get( 'pay_later_checkout_message_color' ) : '',
|
||||
'flex_color' => $settings->has( 'pay_later_checkout_message_flex_color' ) ? $settings->get( 'pay_later_checkout_message_flex_color' ) : '',
|
||||
'flex_ratio' => $settings->has( 'pay_later_checkout_message_flex_ratio' ) ? $settings->get( 'pay_later_checkout_message_flex_ratio' ) : '',
|
||||
)
|
||||
);
|
||||
},
|
||||
);
|
||||
|
293
modules/ppcp-paylater-wc-blocks/src/PayLaterWCBlocksModule.php
Normal file
293
modules/ppcp-paylater-wc-blocks/src/PayLaterWCBlocksModule.php
Normal file
|
@ -0,0 +1,293 @@
|
|||
<?php
|
||||
/**
|
||||
* The Pay Later WooCommerce Blocks module.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\PayLaterWCBlocks
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\PayLaterWCBlocks;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\CartScriptParamsEndpoint;
|
||||
use WooCommerce\PayPalCommerce\PayLaterConfigurator\Factory\ConfigFactory;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
use WooCommerce\PayPalCommerce\Button\Helper\MessagesApply;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Helper\SettingsStatus;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
use WooCommerce\PayPalCommerce\PayLaterWCBlocks\PayLaterWCBlocksUtils;
|
||||
|
||||
/**
|
||||
* Class PayLaterWCBlocksModule
|
||||
*/
|
||||
class PayLaterWCBlocksModule implements ModuleInterface {
|
||||
/**
|
||||
* Returns whether the block module should be loaded.
|
||||
*
|
||||
* @return bool true if the module should be loaded, otherwise false.
|
||||
*/
|
||||
public static function is_module_loading_required(): bool {
|
||||
return apply_filters(
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
|
||||
'woocommerce.feature-flags.woocommerce_paypal_payments.paylater_wc_blocks_enabled',
|
||||
getenv( 'PCP_PAYLATER_WC_BLOCKS' ) !== '0'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the block is enabled.
|
||||
*
|
||||
* @param SettingsStatus $settings_status The Settings status helper.
|
||||
* @param string $location The location to check.
|
||||
* @return bool true if the block is enabled, otherwise false.
|
||||
*/
|
||||
public static function is_block_enabled( SettingsStatus $settings_status, string $location ): bool {
|
||||
return self::is_module_loading_required() && $settings_status->is_pay_later_messaging_enabled_for_location( $location );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the placement is enabled.
|
||||
*
|
||||
* @param SettingsStatus $settings_status The Settings status helper.
|
||||
* @param string $location The location to check.
|
||||
* @return bool true if the placement is enabled, otherwise false.
|
||||
*/
|
||||
public static function is_placement_enabled( SettingsStatus $settings_status, string $location ) : bool {
|
||||
return self::is_block_enabled( $settings_status, $location );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the under cart totals placement is enabled.
|
||||
*
|
||||
* @return bool true if the under cart totals placement is enabled, otherwise false.
|
||||
*/
|
||||
public function is_under_cart_totals_placement_enabled() : bool {
|
||||
return apply_filters(
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName.UseUnderscores
|
||||
'woocommerce.feature-flags.woocommerce_paypal_payments.paylater_wc_blocks_cart_under_totals_enabled',
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function setup(): ServiceProviderInterface {
|
||||
return new ServiceProvider(
|
||||
require __DIR__ . '/../services.php',
|
||||
require __DIR__ . '/../extensions.php'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function run( ContainerInterface $c ): void {
|
||||
$messages_apply = $c->get( 'button.helper.messages-apply' );
|
||||
assert( $messages_apply instanceof MessagesApply );
|
||||
|
||||
if ( ! $messages_apply->for_country() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$settings = $c->get( 'wcgateway.settings' );
|
||||
assert( $settings instanceof Settings );
|
||||
|
||||
add_action(
|
||||
'init',
|
||||
function () use ( $c, $settings ): void {
|
||||
$config_factory = $c->get( 'paylater-configurator.factory.config' );
|
||||
assert( $config_factory instanceof ConfigFactory );
|
||||
|
||||
$script_handle = 'ppcp-cart-paylater-block';
|
||||
|
||||
wp_register_script(
|
||||
$script_handle,
|
||||
$c->get( 'paylater-wc-blocks.url' ) . 'assets/js/cart-paylater-block.js',
|
||||
array(),
|
||||
$c->get( 'ppcp.asset-version' ),
|
||||
true
|
||||
);
|
||||
|
||||
wp_localize_script(
|
||||
$script_handle,
|
||||
'PcpCartPayLaterBlock',
|
||||
array(
|
||||
'ajax' => array(
|
||||
'cart_script_params' => array(
|
||||
'endpoint' => \WC_AJAX::get_endpoint( CartScriptParamsEndpoint::ENDPOINT ),
|
||||
),
|
||||
),
|
||||
'config' => $config_factory->from_settings( $settings ),
|
||||
'settingsUrl' => admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway' ),
|
||||
'vaultingEnabled' => $settings->has( 'vault_enabled' ) && $settings->get( 'vault_enabled' ),
|
||||
'placementEnabled' => self::is_placement_enabled( $c->get( 'wcgateway.settings.status' ), 'cart' ),
|
||||
'payLaterSettingsUrl' => admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway&ppcp-tab=ppcp-pay-later' ),
|
||||
'underTotalsPlacementEnabled' => self::is_under_cart_totals_placement_enabled(),
|
||||
)
|
||||
);
|
||||
|
||||
$script_handle = 'ppcp-checkout-paylater-block';
|
||||
|
||||
wp_register_script(
|
||||
$script_handle,
|
||||
$c->get( 'paylater-wc-blocks.url' ) . 'assets/js/checkout-paylater-block.js',
|
||||
array(),
|
||||
$c->get( 'ppcp.asset-version' ),
|
||||
true
|
||||
);
|
||||
|
||||
wp_localize_script(
|
||||
$script_handle,
|
||||
'PcpCheckoutPayLaterBlock',
|
||||
array(
|
||||
'ajax' => array(
|
||||
'cart_script_params' => array(
|
||||
'endpoint' => \WC_AJAX::get_endpoint( CartScriptParamsEndpoint::ENDPOINT ),
|
||||
),
|
||||
),
|
||||
'config' => $config_factory->from_settings( $settings ),
|
||||
'settingsUrl' => admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway' ),
|
||||
'vaultingEnabled' => $settings->has( 'vault_enabled' ) && $settings->get( 'vault_enabled' ),
|
||||
'placementEnabled' => self::is_placement_enabled( $c->get( 'wcgateway.settings.status' ), 'checkout' ),
|
||||
'payLaterSettingsUrl' => admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=ppcp-gateway&ppcp-tab=ppcp-pay-later' ),
|
||||
)
|
||||
);
|
||||
},
|
||||
20
|
||||
);
|
||||
|
||||
/**
|
||||
* Registers slugs as block categories with WordPress.
|
||||
*/
|
||||
add_action(
|
||||
'block_categories_all',
|
||||
function ( array $categories ): array {
|
||||
return array_merge(
|
||||
$categories,
|
||||
array(
|
||||
array(
|
||||
'slug' => 'woocommerce-paypal-payments',
|
||||
'title' => __( 'PayPal Blocks', 'woocommerce-paypal-payments' ),
|
||||
),
|
||||
)
|
||||
);
|
||||
},
|
||||
10,
|
||||
2
|
||||
);
|
||||
|
||||
/**
|
||||
* Cannot return false for this path.
|
||||
*
|
||||
* @psalm-suppress PossiblyFalseArgument
|
||||
*/
|
||||
if ( function_exists( 'register_block_type' ) ) {
|
||||
register_block_type(
|
||||
dirname( realpath( __FILE__ ), 2 ) . '/resources/js/CartPayLaterMessagesBlock',
|
||||
array(
|
||||
'render_callback' => function ( array $attributes ) use ( $c ) {
|
||||
return PayLaterWCBlocksUtils::render_paylater_block(
|
||||
$attributes['blockId'] ?? 'woocommerce-paypal-payments/cart-paylater-messages',
|
||||
$attributes['ppcpId'] ?? 'ppcp-cart-paylater-messages',
|
||||
'cart',
|
||||
$c
|
||||
);
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cannot return false for this path.
|
||||
*
|
||||
* @psalm-suppress PossiblyFalseArgument
|
||||
*/
|
||||
if ( function_exists( 'register_block_type' ) ) {
|
||||
register_block_type(
|
||||
dirname( realpath( __FILE__ ), 2 ) . '/resources/js/CheckoutPayLaterMessagesBlock',
|
||||
array(
|
||||
'render_callback' => function ( array $attributes ) use ( $c ) {
|
||||
return PayLaterWCBlocksUtils::render_paylater_block(
|
||||
$attributes['blockId'] ?? 'woocommerce-paypal-payments/checkout-paylater-messages',
|
||||
$attributes['ppcpId'] ?? 'ppcp-checkout-paylater-messages',
|
||||
'checkout',
|
||||
$c
|
||||
);
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// This is a fallback for the default Cart block that haven't been saved with the inserted Pay Later messaging block.
|
||||
add_filter(
|
||||
'render_block_woocommerce/cart-totals-block',
|
||||
function ( string $block_content ) use ( $c ) {
|
||||
if ( false === strpos( $block_content, 'woocommerce-paypal-payments/cart-paylater-messages' ) ) {
|
||||
return PayLaterWCBlocksUtils::render_and_insert_paylater_block(
|
||||
$block_content,
|
||||
'woocommerce-paypal-payments/cart-paylater-messages',
|
||||
'ppcp-cart-paylater-messages',
|
||||
'cart',
|
||||
$c,
|
||||
self::is_under_cart_totals_placement_enabled()
|
||||
);
|
||||
}
|
||||
return $block_content;
|
||||
},
|
||||
10,
|
||||
1
|
||||
);
|
||||
|
||||
// This is a fallback for the default Checkout block that haven't been saved with the inserted Checkout - Pay Later messaging block.
|
||||
add_filter(
|
||||
'render_block_woocommerce/checkout-totals-block',
|
||||
function ( string $block_content ) use ( $c ) {
|
||||
if ( false === strpos( $block_content, 'woocommerce-paypal-payments/checkout-paylater-messages' ) ) {
|
||||
return PayLaterWCBlocksUtils::render_and_insert_paylater_block(
|
||||
$block_content,
|
||||
'woocommerce-paypal-payments/checkout-paylater-messages',
|
||||
'ppcp-checkout-paylater-messages',
|
||||
'checkout',
|
||||
$c
|
||||
);
|
||||
}
|
||||
return $block_content;
|
||||
},
|
||||
10,
|
||||
1
|
||||
);
|
||||
|
||||
// Since there's no regular way we can place the Pay Later messaging block under the cart totals block, we need a custom script.
|
||||
if ( self::is_under_cart_totals_placement_enabled() ) {
|
||||
add_action(
|
||||
'enqueue_block_editor_assets',
|
||||
function () use ( $c, $settings ): void {
|
||||
$handle = 'ppcp-checkout-paylater-block-editor-inserter';
|
||||
$path = $c->get( 'paylater-wc-blocks.url' ) . 'assets/js/cart-paylater-block-inserter.js';
|
||||
|
||||
wp_register_script(
|
||||
$handle,
|
||||
$path,
|
||||
array( 'wp-blocks', 'wp-data', 'wp-element' ),
|
||||
$c->get( 'ppcp.asset-version' ),
|
||||
true
|
||||
);
|
||||
|
||||
wp_enqueue_script( $handle );
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key for the module.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getKey() {
|
||||
}
|
||||
}
|
131
modules/ppcp-paylater-wc-blocks/src/PayLaterWCBlocksRenderer.php
Normal file
131
modules/ppcp-paylater-wc-blocks/src/PayLaterWCBlocksRenderer.php
Normal file
|
@ -0,0 +1,131 @@
|
|||
<?php
|
||||
/**
|
||||
* The Pay Later WooCommerce Blocks Renderer.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\PayLaterWCBlocks
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\PayLaterWCBlocks;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Class PayLaterWCBlocksRenderer
|
||||
*/
|
||||
class PayLaterWCBlocksRenderer {
|
||||
/**
|
||||
* The placement.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $placement;
|
||||
/**
|
||||
* The layout.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $layout;
|
||||
/**
|
||||
* The position.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $position;
|
||||
/**
|
||||
* The logo.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $logo;
|
||||
/**
|
||||
* The text size.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $text_size;
|
||||
/**
|
||||
* The color.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $color;
|
||||
/**
|
||||
* The flex color.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $flex_color;
|
||||
/**
|
||||
* The flex ratio.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $flex_ratio;
|
||||
|
||||
/**
|
||||
* PayLaterWCBlocksRenderer constructor.
|
||||
*
|
||||
* @param array $config The configuration.
|
||||
*/
|
||||
public function __construct( array $config ) {
|
||||
$this->placement = $config['placement'] ?? '';
|
||||
$this->layout = $config['layout'] ?? 'text';
|
||||
$this->position = $config['position'] ?? '';
|
||||
$this->logo = $config['logo'] ?? '';
|
||||
$this->text_size = $config['text_size'] ?? '';
|
||||
$this->color = $config['color'] ?? '';
|
||||
$this->flex_color = $config['flex_color'] ?? '';
|
||||
$this->flex_ratio = $config['flex_ratio'] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the WC Pay Later Messaging blocks.
|
||||
*
|
||||
* @param array $attributes The block attributes.
|
||||
* @param string $location The location of the block.
|
||||
* @param ContainerInterface $c The container.
|
||||
* @return string|void
|
||||
*/
|
||||
public function render(
|
||||
array $attributes,
|
||||
string $location,
|
||||
ContainerInterface $c
|
||||
) {
|
||||
if ( PayLaterWCBlocksModule::is_placement_enabled( $c->get( 'wcgateway.settings.status' ), $location ) ) {
|
||||
|
||||
$html = '<div id="' . esc_attr( $attributes['ppcpId'] ?? '' ) . '" class="ppcp-messages" data-partner-attribution-id="Woo_PPCP"></div>';
|
||||
|
||||
$processor = new \WP_HTML_Tag_Processor( $html );
|
||||
|
||||
if ( $processor->next_tag( 'div' ) ) {
|
||||
$processor->set_attribute( 'data-block-name', esc_attr( $attributes['blockId'] ?? '' ) );
|
||||
$processor->set_attribute( 'class', 'ppcp-messages' );
|
||||
$processor->set_attribute( 'data-partner-attribution-id', 'Woo_PPCP' );
|
||||
|
||||
if ( $this->layout === 'flex' ) {
|
||||
$processor->set_attribute( 'data-pp-style-layout', 'flex' );
|
||||
$processor->set_attribute( 'data-pp-style-color', esc_attr( $this->flex_color ) );
|
||||
$processor->set_attribute( 'data-pp-style-ratio', esc_attr( $this->flex_ratio ) );
|
||||
} else {
|
||||
$processor->set_attribute( 'data-pp-style-layout', 'text' );
|
||||
$processor->set_attribute( 'data-pp-style-logo-type', esc_attr( $this->logo ) );
|
||||
$processor->set_attribute( 'data-pp-style-logo-position', esc_attr( $this->position ) );
|
||||
$processor->set_attribute( 'data-pp-style-text-color', esc_attr( $this->color ) );
|
||||
$processor->set_attribute( 'data-pp-style-text-size', esc_attr( $this->text_size ) );
|
||||
}
|
||||
|
||||
$processor->set_attribute( 'data-pp-placement', esc_attr( $this->placement ) );
|
||||
}
|
||||
|
||||
$updated_html = $processor->get_updated_html();
|
||||
|
||||
return sprintf(
|
||||
'<div %1$s>%2$s</div>',
|
||||
wp_kses_data( get_block_wrapper_attributes() ),
|
||||
$updated_html
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
104
modules/ppcp-paylater-wc-blocks/src/PayLaterWCBlocksUtils.php
Normal file
104
modules/ppcp-paylater-wc-blocks/src/PayLaterWCBlocksUtils.php
Normal file
|
@ -0,0 +1,104 @@
|
|||
<?php
|
||||
/**
|
||||
* The Pay Later WooCommerce Blocks Utils.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\PayLaterWCBlocks
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\PayLaterWCBlocks;
|
||||
|
||||
/**
|
||||
* Class PayLaterWCBlocksUtils
|
||||
*/
|
||||
class PayLaterWCBlocksUtils {
|
||||
|
||||
/**
|
||||
* Inserts content before the last div in a block.
|
||||
*
|
||||
* @param string $block_content The block content.
|
||||
* @param string $content_to_insert The content to insert.
|
||||
* @return string The block content with the content inserted.
|
||||
*/
|
||||
public static function insert_before_last_div( string $block_content, string $content_to_insert ): string {
|
||||
$last_index = strrpos( $block_content, '</div>' );
|
||||
|
||||
if ( false !== $last_index ) {
|
||||
$block_content = substr_replace( $block_content, $content_to_insert, $last_index, 0 );
|
||||
}
|
||||
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts content after the closing div tag of a specific block.
|
||||
*
|
||||
* @param string $block_content The block content.
|
||||
* @param string $content_to_insert The content to insert.
|
||||
* @param string $reference_block The block markup to insert the content after.
|
||||
* @return string The block content with the content inserted.
|
||||
*/
|
||||
public static function insert_before_opening_div( string $block_content, string $content_to_insert, string $reference_block ): string {
|
||||
$reference_block_index = strpos( $block_content, $reference_block );
|
||||
|
||||
if ( false !== $reference_block_index ) {
|
||||
return substr_replace( $block_content, $content_to_insert, $reference_block_index, 0 );
|
||||
} else {
|
||||
return self::insert_before_last_div( $block_content, $content_to_insert );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a PayLater message block and inserts it before the last closing div tag if the block id is not already present.
|
||||
*
|
||||
* @param string $block_content Current content of the block.
|
||||
* @param string $block_id ID of the block to render.
|
||||
* @param string $ppcp_id ID for the PPCP component.
|
||||
* @param string $context Rendering context (cart or checkout).
|
||||
* @param mixed $container Dependency injection container.
|
||||
* @param bool $is_under_cart_totals_placement_enabled Whether the block should be placed under the cart totals.
|
||||
* @return string Updated block content.
|
||||
*/
|
||||
public static function render_and_insert_paylater_block( string $block_content, string $block_id, string $ppcp_id, string $context, $container, bool $is_under_cart_totals_placement_enabled = false ): string {
|
||||
$paylater_message_block = self::render_paylater_block( $block_id, $ppcp_id, $context, $container );
|
||||
$cart_express_payment_block = '<div data-block-name="woocommerce/cart-express-payment-block" class="wp-block-woocommerce-cart-express-payment-block"></div>';
|
||||
|
||||
if ( false !== $paylater_message_block ) {
|
||||
if ( $is_under_cart_totals_placement_enabled && $context === 'cart' ) {
|
||||
return self::insert_before_opening_div( $block_content, $paylater_message_block, $cart_express_payment_block );
|
||||
} else {
|
||||
return self::insert_before_last_div( $block_content, $paylater_message_block );
|
||||
}
|
||||
}
|
||||
return $block_content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the PayLater block based on the provided parameters.
|
||||
*
|
||||
* @param string $block_id ID of the block to render.
|
||||
* @param string $ppcp_id ID for the PPCP component.
|
||||
* @param string $context Rendering context (cart or checkout).
|
||||
* @param mixed $container Dependency injection container.
|
||||
* @return false|string Rendered content.
|
||||
*/
|
||||
public static function render_paylater_block( string $block_id, string $ppcp_id, string $context, $container ) {
|
||||
$renderer = $container->get( 'paylater-wc-blocks.' . $context . '-renderer' );
|
||||
ob_start();
|
||||
// phpcs:ignore -- No need to escape it, the PayLaterWCBlocksRenderer class is responsible for escaping.
|
||||
echo $renderer->render(
|
||||
array(
|
||||
// phpcs:ignore
|
||||
'blockId' => $block_id,
|
||||
// phpcs:ignore
|
||||
'ppcpId' => $ppcp_id,
|
||||
),
|
||||
// phpcs:ignore
|
||||
$context,
|
||||
// phpcs:ignore
|
||||
$container
|
||||
);
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
63
modules/ppcp-paylater-wc-blocks/webpack.config.js
Normal file
63
modules/ppcp-paylater-wc-blocks/webpack.config.js
Normal file
|
@ -0,0 +1,63 @@
|
|||
const path = require("path");
|
||||
const isProduction = process.env.NODE_ENV === "production";
|
||||
|
||||
const DependencyExtractionWebpackPlugin = require("@woocommerce/dependency-extraction-webpack-plugin");
|
||||
|
||||
module.exports = {
|
||||
devtool: isProduction ? "source-map" : "eval-source-map",
|
||||
mode: isProduction ? "production" : "development",
|
||||
target: "web",
|
||||
plugins: [new DependencyExtractionWebpackPlugin()],
|
||||
entry: {
|
||||
"cart-paylater-block": path.resolve(
|
||||
process.cwd(),
|
||||
"resources",
|
||||
"js",
|
||||
"CartPayLaterMessagesBlock",
|
||||
"cart-paylater-block.js"
|
||||
),
|
||||
"cart-paylater-block-inserter": path.resolve(
|
||||
process.cwd(),
|
||||
"resources",
|
||||
"js",
|
||||
"CartPayLaterMessagesBlock",
|
||||
"cart-paylater-block-inserter.js"
|
||||
),
|
||||
"checkout-paylater-block": path.resolve(
|
||||
process.cwd(),
|
||||
"resources",
|
||||
"js",
|
||||
"CheckoutPayLaterMessagesBlock",
|
||||
"checkout-paylater-block.js"
|
||||
),
|
||||
},
|
||||
output: {
|
||||
path: path.resolve(__dirname, "assets/"),
|
||||
filename: "js/[name].js",
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js?$/,
|
||||
exclude: /node_modules/,
|
||||
loader: "babel-loader",
|
||||
options: {
|
||||
presets: ["@babel/preset-env", "@babel/preset-react"],
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
exclude: /node_modules/,
|
||||
use: [
|
||||
{
|
||||
loader: "file-loader",
|
||||
options: {
|
||||
name: "css/[name].css",
|
||||
},
|
||||
},
|
||||
{ loader: "sass-loader" },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
2319
modules/ppcp-paylater-wc-blocks/yarn.lock
Normal file
2319
modules/ppcp-paylater-wc-blocks/yarn.lock
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,8 @@
|
|||
@use "../../../ppcp-button/resources/css/mixins/apm-button" as apm-button;
|
||||
|
||||
$border-color: #c3c3c3;
|
||||
$background-ident-color: #fbfbfb;
|
||||
|
||||
.ppcp-field-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
@ -11,9 +14,10 @@
|
|||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.ppcp-field-indent {
|
||||
th {
|
||||
padding-left: 20px;
|
||||
.ppcp-active-spacer {
|
||||
th, td {
|
||||
padding: 0;
|
||||
height: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,3 +43,57 @@
|
|||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.ppcp-align-label-center {
|
||||
th {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.ppcp-valign-label-middle {
|
||||
th {
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
// Box indented fields.
|
||||
@media screen and (min-width: 800px) {
|
||||
.ppcp-settings-field {
|
||||
border-left: 1px solid transparent;
|
||||
border-right: 1px solid transparent;
|
||||
|
||||
&.active {
|
||||
background-color: $background-ident-color;
|
||||
border: 1px solid $border-color;
|
||||
|
||||
th {
|
||||
padding-left: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
&.ppcp-field-indent {
|
||||
background-color: $background-ident-color;
|
||||
border: 1px solid $border-color;
|
||||
|
||||
th, &.ppcp-settings-field-heading td {
|
||||
padding-left: 40px;
|
||||
}
|
||||
|
||||
th, td {
|
||||
border-top: 1px solid $border-color;
|
||||
}
|
||||
|
||||
& + .ppcp-field-indent {
|
||||
th, td {
|
||||
border-top: 1px solid $background-ident-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ppcp-settings-field-select {
|
||||
p.description {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
import ElementAction from "./action/ElementAction";
|
||||
import VisibilityAction from "./action/VisibilityAction";
|
||||
import AttributeAction from "./action/AttributeAction";
|
||||
|
||||
class ActionFactory {
|
||||
static make(actionConfig) {
|
||||
switch (actionConfig.type) {
|
||||
case 'element':
|
||||
return new ElementAction(actionConfig);
|
||||
case 'visibility':
|
||||
return new VisibilityAction(actionConfig);
|
||||
case 'attribute':
|
||||
return new AttributeAction(actionConfig);
|
||||
}
|
||||
|
||||
throw new Error('[ActionFactory] Unknown action: ' + actionConfig.type);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import ElementCondition from "./condition/ElementCondition";
|
||||
import BoolCondition from "./condition/BoolCondition";
|
||||
import JsVariableCondition from "./condition/JsVariableCondition";
|
||||
|
||||
class ConditionFactory {
|
||||
static make(conditionConfig, triggerUpdate) {
|
||||
|
@ -8,6 +9,8 @@ class ConditionFactory {
|
|||
return new ElementCondition(conditionConfig, triggerUpdate);
|
||||
case 'bool':
|
||||
return new BoolCondition(conditionConfig, triggerUpdate);
|
||||
case 'js_variable':
|
||||
return new JsVariableCondition(conditionConfig, triggerUpdate);
|
||||
}
|
||||
|
||||
throw new Error('[ConditionFactory] Unknown condition: ' + conditionConfig.type);
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
import BaseAction from "./BaseAction";
|
||||
|
||||
class AttributeAction extends BaseAction {
|
||||
|
||||
run(status) {
|
||||
|
||||
if (status) {
|
||||
jQuery(this.config.selector).addClass(this.config.html_class);
|
||||
} else {
|
||||
jQuery(this.config.selector).removeClass(this.config.html_class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default AttributeAction;
|
|
@ -1,6 +1,6 @@
|
|||
import BaseAction from "./BaseAction";
|
||||
|
||||
class ElementAction extends BaseAction {
|
||||
class VisibilityAction extends BaseAction {
|
||||
|
||||
run(status) {
|
||||
|
||||
|
@ -32,4 +32,4 @@ class ElementAction extends BaseAction {
|
|||
|
||||
}
|
||||
|
||||
export default ElementAction;
|
||||
export default VisibilityAction;
|
|
@ -0,0 +1,24 @@
|
|||
import BaseCondition from "./BaseCondition";
|
||||
|
||||
class JsVariableCondition extends BaseCondition {
|
||||
|
||||
register() {
|
||||
jQuery(document).on('ppcp-display-change', () => {
|
||||
const status = this.check();
|
||||
if (status !== this.status) {
|
||||
this.status = status;
|
||||
this.triggerUpdate();
|
||||
}
|
||||
});
|
||||
|
||||
this.status = this.check();
|
||||
}
|
||||
|
||||
check() {
|
||||
let value = document[this.config.variable];
|
||||
return this.config.value === value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default JsVariableCondition;
|
|
@ -17,6 +17,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\ApplicationContext;
|
|||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
|
||||
use WooCommerce\PayPalCommerce\Axo\Gateway\AxoGateway;
|
||||
use WooCommerce\PayPalCommerce\Button\Helper\MessagesDisclaimers;
|
||||
use WooCommerce\PayPalCommerce\Common\Pattern\SingletonDecorator;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||
|
@ -194,6 +195,7 @@ return array(
|
|||
CardButtonGateway::ID,
|
||||
OXXOGateway::ID,
|
||||
Settings::PAY_LATER_TAB_ID,
|
||||
AxoGateway::ID,
|
||||
),
|
||||
true
|
||||
);
|
||||
|
@ -801,6 +803,14 @@ return array(
|
|||
'elo' => _x( 'Elo', 'Name of credit card', 'woocommerce-paypal-payments' ),
|
||||
'hiper' => _x( 'Hiper', 'Name of credit card', 'woocommerce-paypal-payments' ),
|
||||
),
|
||||
'options_axo' => array(
|
||||
'dinersclub-light' => _x( 'Diners Club (light)', 'Name of credit card', 'woocommerce-paypal-payments' ),
|
||||
'discover-light' => _x( 'Discover (light)', 'Name of credit card', 'woocommerce-paypal-payments' ),
|
||||
'jcb-light' => _x( 'JCB (light)', 'Name of credit card', 'woocommerce-paypal-payments' ),
|
||||
'mastercard-light' => _x( 'Mastercard (light)', 'Name of credit card', 'woocommerce-paypal-payments' ),
|
||||
'unionpay-light' => _x( 'UnionPay (light)', 'Name of credit card', 'woocommerce-paypal-payments' ),
|
||||
'visa-light' => _x( 'Visa (light)', 'Name of credit card', 'woocommerce-paypal-payments' ),
|
||||
),
|
||||
'screens' => array(
|
||||
State::STATE_ONBOARDED,
|
||||
),
|
||||
|
@ -809,25 +819,6 @@ return array(
|
|||
),
|
||||
'gateway' => 'dcc',
|
||||
),
|
||||
'vault_enabled_dcc' => array(
|
||||
'title' => __( 'Vaulting', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'checkbox',
|
||||
'desc_tip' => true,
|
||||
'label' => sprintf(
|
||||
// translators: %1$s and %2$s are the opening and closing of HTML <a> tag.
|
||||
__( 'Securely store your customers’ credit cards for a seamless checkout experience and subscription features. Payment methods are saved in the secure %1$sPayPal Vault%2$s.', 'woocommerce-paypal-payments' ),
|
||||
'<a href="https://woocommerce.com/document/woocommerce-paypal-payments/#vaulting-saving-a-payment-method" target="_blank">',
|
||||
'</a>'
|
||||
),
|
||||
'description' => __( 'Allow registered buyers to save Credit Card payments.', 'woocommerce-paypal-payments' ),
|
||||
'default' => false,
|
||||
'screens' => array(
|
||||
State::STATE_ONBOARDED,
|
||||
),
|
||||
'requirements' => array(),
|
||||
'gateway' => 'dcc',
|
||||
'input_class' => $container->get( 'wcgateway.helper.vaulting-scope' ) ? array() : array( 'ppcp-disabled-checkbox' ),
|
||||
),
|
||||
'3d_secure_heading' => array(
|
||||
'heading' => __( '3D Secure', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'ppcp-heading',
|
||||
|
@ -884,6 +875,52 @@ return array(
|
|||
),
|
||||
'gateway' => 'dcc',
|
||||
),
|
||||
'saved_payments_heading' => array(
|
||||
'heading' => __( 'Saved Payments', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'ppcp-heading',
|
||||
'description' => wp_kses_post(
|
||||
sprintf(
|
||||
// translators: %1$s and %2$s is a link tag.
|
||||
__(
|
||||
'PayPal can securely store your customers’ payment methods for
|
||||
%1$sfuture payments and subscriptions%2$s, simplifying the checkout
|
||||
process and enabling recurring transactions on your website.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'<a
|
||||
rel="noreferrer noopener"
|
||||
href="https://woo.com/document/woocommerce-paypal-payments/#vaulting-a-card"
|
||||
>',
|
||||
'</a>'
|
||||
)
|
||||
),
|
||||
'screens' => array(
|
||||
State::STATE_ONBOARDED,
|
||||
),
|
||||
'requirements' => array(
|
||||
'dcc',
|
||||
),
|
||||
'gateway' => 'dcc',
|
||||
),
|
||||
'vault_enabled_dcc' => array(
|
||||
'title' => __( 'Vaulting', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'checkbox',
|
||||
'desc_tip' => true,
|
||||
'label' => sprintf(
|
||||
// translators: %1$s and %2$s are the opening and closing of HTML <a> tag.
|
||||
__( 'Securely store your customers’ credit cards for a seamless checkout experience and subscription features. Payment methods are saved in the secure %1$sPayPal Vault%2$s.', 'woocommerce-paypal-payments' ),
|
||||
'<a href="https://woocommerce.com/document/woocommerce-paypal-payments/#vaulting-saving-a-payment-method" target="_blank">',
|
||||
'</a>'
|
||||
),
|
||||
'description' => __( 'Allow registered buyers to save Credit Card payments.', 'woocommerce-paypal-payments' ),
|
||||
'default' => false,
|
||||
'screens' => array(
|
||||
State::STATE_ONBOARDED,
|
||||
),
|
||||
'requirements' => array(),
|
||||
'gateway' => 'dcc',
|
||||
'input_class' => $container->get( 'wcgateway.helper.vaulting-scope' ) ? array() : array( 'ppcp-disabled-checkbox' ),
|
||||
),
|
||||
'paypal_saved_payments' => array(
|
||||
'heading' => __( 'Saved payments', 'woocommerce-paypal-payments' ),
|
||||
'description' => sprintf(
|
||||
|
@ -922,6 +959,32 @@ return array(
|
|||
'gateway' => 'paypal',
|
||||
'input_class' => $container->get( 'wcgateway.helper.vaulting-scope' ) ? array() : array( 'ppcp-disabled-checkbox' ),
|
||||
),
|
||||
'digital_wallet_heading' => array(
|
||||
'heading' => __( 'Digital Wallet Services', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'ppcp-heading',
|
||||
'description' => wp_kses_post(
|
||||
sprintf(
|
||||
// translators: %1$s and %2$s is a link tag.
|
||||
__(
|
||||
'PayPal supports digital wallet services like Apple Pay or Google Pay
|
||||
to give your buyers more options to pay without a PayPal account.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'<a
|
||||
rel="noreferrer noopener"
|
||||
href="https://woo.com/document/woocommerce-paypal-payments/#vaulting-a-card"
|
||||
>',
|
||||
'</a>'
|
||||
)
|
||||
),
|
||||
'screens' => array(
|
||||
State::STATE_ONBOARDED,
|
||||
),
|
||||
'requirements' => array(
|
||||
'dcc',
|
||||
),
|
||||
'gateway' => 'dcc',
|
||||
),
|
||||
);
|
||||
|
||||
if ( ! $subscription_helper->plugin_is_active() ) {
|
||||
|
@ -1509,6 +1572,7 @@ return array(
|
|||
PayUponInvoiceGateway::ID,
|
||||
CardButtonGateway::ID,
|
||||
OXXOGateway::ID,
|
||||
AxoGateway::ID,
|
||||
);
|
||||
},
|
||||
'wcgateway.gateway-repository' => static function ( ContainerInterface $container ): GatewayRepository {
|
||||
|
|
|
@ -298,6 +298,8 @@ class PayPalGateway extends \WC_Payment_Gateway {
|
|||
'subscription_payment_method_change_admin',
|
||||
'multiple_subscriptions'
|
||||
);
|
||||
} elseif ( $this->config->has( 'subscriptions_mode' ) && $this->config->get( 'subscriptions_mode' ) === 'subscriptions_api' ) {
|
||||
$this->supports[] = 'gateway_scheduled_payments';
|
||||
} elseif ( $this->config->has( 'vault_enabled_dcc' ) && $this->config->get( 'vault_enabled_dcc' ) ) {
|
||||
$this->supports[] = 'tokenization';
|
||||
}
|
||||
|
|
|
@ -16,8 +16,9 @@ use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
|||
*/
|
||||
class DisplayRule {
|
||||
|
||||
const CONDITION_TYPE_ELEMENT = 'element';
|
||||
const CONDITION_TYPE_BOOL = 'bool';
|
||||
const CONDITION_TYPE_ELEMENT = 'element';
|
||||
const CONDITION_TYPE_BOOL = 'bool';
|
||||
const CONDITION_TYPE_JS_VARIABLE = 'js_variable';
|
||||
|
||||
const CONDITION_OPERATION_EQUALS = 'equals';
|
||||
const CONDITION_OPERATION_NOT_EQUALS = 'not_equals';
|
||||
|
@ -26,10 +27,12 @@ class DisplayRule {
|
|||
const CONDITION_OPERATION_EMPTY = 'empty';
|
||||
const CONDITION_OPERATION_NOT_EMPTY = 'not_empty';
|
||||
|
||||
const ACTION_TYPE_ELEMENT = 'element';
|
||||
const ACTION_TYPE_VISIBILITY = 'visibility';
|
||||
const ACTION_TYPE_ATTRIBUTE = 'attribute';
|
||||
|
||||
const ACTION_VISIBLE = 'visible';
|
||||
const ACTION_ENABLE = 'enable';
|
||||
const ACTION_CLASS = 'class';
|
||||
|
||||
/**
|
||||
* The element selector.
|
||||
|
@ -132,6 +135,24 @@ class DisplayRule {
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a condition related to js variable check.
|
||||
*
|
||||
* @param string $variable_name The javascript variable name.
|
||||
* @param mixed $value The value to enable / disable the condition.
|
||||
* @return self
|
||||
*/
|
||||
public function condition_js_variable( string $variable_name, $value ): self {
|
||||
$this->add_condition(
|
||||
array(
|
||||
'type' => self::CONDITION_TYPE_JS_VARIABLE,
|
||||
'variable' => $variable_name,
|
||||
'value' => $value,
|
||||
)
|
||||
);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a condition to show/hide the element.
|
||||
*
|
||||
|
@ -140,7 +161,7 @@ class DisplayRule {
|
|||
public function action_visible( string $selector ): self {
|
||||
$this->add_action(
|
||||
array(
|
||||
'type' => self::ACTION_TYPE_ELEMENT,
|
||||
'type' => self::ACTION_TYPE_VISIBILITY,
|
||||
'selector' => $selector,
|
||||
'action' => self::ACTION_VISIBLE,
|
||||
)
|
||||
|
@ -148,6 +169,24 @@ class DisplayRule {
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a condition to add/remove a html class.
|
||||
*
|
||||
* @param string $selector The condition selector.
|
||||
* @param string $class The class.
|
||||
*/
|
||||
public function action_class( string $selector, string $class ): self {
|
||||
$this->add_action(
|
||||
array(
|
||||
'type' => self::ACTION_TYPE_ATTRIBUTE,
|
||||
'selector' => $selector,
|
||||
'html_class' => $class,
|
||||
'action' => self::ACTION_CLASS,
|
||||
)
|
||||
);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a condition to enable/disable the element.
|
||||
*
|
||||
|
@ -156,7 +195,7 @@ class DisplayRule {
|
|||
public function action_enable( string $selector ): self {
|
||||
$this->add_action(
|
||||
array(
|
||||
'type' => self::ACTION_TYPE_ELEMENT,
|
||||
'type' => self::ACTION_TYPE_VISIBILITY,
|
||||
'selector' => $selector,
|
||||
'action' => self::ACTION_ENABLE,
|
||||
)
|
||||
|
|
|
@ -270,6 +270,40 @@ class OrderProcessor {
|
|||
do_action( 'woocommerce_paypal_payments_after_order_processor', $wc_order, $order );
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a given WooCommerce order and captured/authorizes the connected PayPal orders.
|
||||
*
|
||||
* @param WC_Order $wc_order The WooCommerce order.
|
||||
* @param Order $order The PayPal order.
|
||||
*
|
||||
* @throws Exception If processing fails.
|
||||
*/
|
||||
public function process_captured_and_authorized( WC_Order $wc_order, Order $order ): void {
|
||||
$this->add_paypal_meta( $wc_order, $order, $this->environment );
|
||||
|
||||
if ( $order->intent() === 'AUTHORIZE' ) {
|
||||
$wc_order->update_meta_data( AuthorizedPaymentsProcessor::CAPTURED_META_KEY, 'false' );
|
||||
|
||||
if ( $this->subscription_helper->has_subscription( $wc_order->get_id() ) ) {
|
||||
$wc_order->update_meta_data( '_ppcp_captured_vault_webhook', 'false' );
|
||||
}
|
||||
}
|
||||
|
||||
$transaction_id = $this->get_paypal_order_transaction_id( $order );
|
||||
|
||||
if ( $transaction_id ) {
|
||||
$this->update_transaction_id( $transaction_id, $wc_order );
|
||||
}
|
||||
|
||||
$this->handle_new_order_status( $order, $wc_order );
|
||||
|
||||
if ( $this->capture_authorized_downloads( $order ) ) {
|
||||
$this->authorized_payments_processor->capture_authorized_payment( $wc_order );
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_paypal_payments_after_order_processor', $wc_order, $order );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a PayPal order for the given WC order.
|
||||
*
|
||||
|
|
|
@ -436,7 +436,7 @@ return function ( ContainerInterface $container, array $fields ): array {
|
|||
'desc_tip' => true,
|
||||
'label' => $container->get( 'wcgateway.settings.fraudnet-label' ),
|
||||
'description' => __( 'FraudNet is a JavaScript library developed by PayPal and embedded into a merchant’s web page to collect browser-based data to help reduce fraud.', 'woocommerce-paypal-payments' ),
|
||||
'default' => false,
|
||||
'default' => true,
|
||||
'screens' => array(
|
||||
State::STATE_ONBOARDED,
|
||||
),
|
||||
|
@ -522,8 +522,8 @@ return function ( ContainerInterface $container, array $fields ): array {
|
|||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'options' => array(
|
||||
PurchaseUnitSanitizer::MODE_DITCH => __( 'Do not send line items to PayPal', 'woocommerce-paypal-payments' ),
|
||||
PurchaseUnitSanitizer::MODE_EXTRA_LINE => __( 'Add another line item', 'woocommerce-paypal-payments' ),
|
||||
PurchaseUnitSanitizer::MODE_DITCH => __( 'Do not send line items to PayPal', 'woocommerce-paypal-payments' ),
|
||||
),
|
||||
'screens' => array(
|
||||
State::STATE_START,
|
||||
|
@ -538,6 +538,7 @@ return function ( ContainerInterface $container, array $fields ): array {
|
|||
->rule()
|
||||
->condition_element( 'subtotal_mismatch_behavior', PurchaseUnitSanitizer::MODE_EXTRA_LINE )
|
||||
->action_visible( 'subtotal_mismatch_line_name' )
|
||||
->action_class( 'subtotal_mismatch_behavior', 'active' )
|
||||
->to_array(),
|
||||
)
|
||||
),
|
||||
|
@ -548,6 +549,7 @@ return function ( ContainerInterface $container, array $fields ): array {
|
|||
'type' => 'text',
|
||||
'desc_tip' => true,
|
||||
'description' => __( 'The name of the extra line that will be sent to PayPal to correct the subtotal mismatch.', 'woocommerce-paypal-payments' ),
|
||||
'classes' => array( 'ppcp-field-indent' ),
|
||||
'maxlength' => 22,
|
||||
'default' => '',
|
||||
'screens' => array(
|
||||
|
|
|
@ -91,7 +91,7 @@ return function ( ContainerInterface $container, array $fields ): array {
|
|||
'title' => __( 'Customize Smart Buttons Per Location', 'woocommerce-paypal-payments' ),
|
||||
'type' => 'checkbox',
|
||||
'label' => __( 'Customize smart button style per location', 'woocommerce-paypal-payments' ),
|
||||
'default' => true,
|
||||
'default' => false,
|
||||
'screens' => array( State::STATE_START, State::STATE_ONBOARDED ),
|
||||
'requirements' => array(),
|
||||
'gateway' => 'paypal',
|
||||
|
@ -126,7 +126,7 @@ return function ( ContainerInterface $container, array $fields ): array {
|
|||
'label' => __( 'Enable tagline', 'woocommerce-paypal-payments' ),
|
||||
'desc_tip' => true,
|
||||
'description' => __(
|
||||
'Add the tagline. This line will only show up, if you select a horizontal layout.',
|
||||
'Enable to show the tagline below the payment button. Requires button width of 300px minimum to appear.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'screens' => array(
|
||||
|
@ -272,7 +272,7 @@ return function ( ContainerInterface $container, array $fields ): array {
|
|||
'label' => __( 'Enable tagline', 'woocommerce-paypal-payments' ),
|
||||
'desc_tip' => true,
|
||||
'description' => __(
|
||||
'Add the tagline. This line will only show up, if you select a horizontal layout.',
|
||||
'Enable to show the tagline below the payment button. Requires button width of 300px minimum to appear.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'screens' => array(
|
||||
|
@ -412,7 +412,7 @@ return function ( ContainerInterface $container, array $fields ): array {
|
|||
'default' => false,
|
||||
'desc_tip' => true,
|
||||
'description' => __(
|
||||
'Add the tagline. This line will only show up, if you select a horizontal layout.',
|
||||
'Enable to show the tagline below the payment button. Requires button width of 300px minimum to appear.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'screens' => array(
|
||||
|
@ -552,7 +552,7 @@ return function ( ContainerInterface $container, array $fields ): array {
|
|||
'default' => false,
|
||||
'desc_tip' => true,
|
||||
'description' => __(
|
||||
'Add the tagline. This line will only show up, if you select a horizontal layout.',
|
||||
'Enable to show the tagline below the payment button. Requires button width of 300px minimum to appear.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'screens' => array(
|
||||
|
@ -692,7 +692,7 @@ return function ( ContainerInterface $container, array $fields ): array {
|
|||
'default' => false,
|
||||
'desc_tip' => true,
|
||||
'description' => __(
|
||||
'Add the tagline. This line will only show up, if you select a horizontal layout.',
|
||||
'Enable to show the tagline below the payment button. Requires button width of 300px minimum to appear.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'screens' => array(
|
||||
|
|
|
@ -9,6 +9,7 @@ declare(strict_types=1);
|
|||
|
||||
namespace WooCommerce\PayPalCommerce\WcGateway\Settings;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Axo\Gateway\AxoGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
|
@ -37,6 +38,7 @@ trait PageMatcherTrait {
|
|||
Settings::PAY_LATER_TAB_ID => Settings::PAY_LATER_TAB_ID,
|
||||
CreditCardGateway::ID => 'dcc', // TODO: consider using just the gateway ID for PayPal and DCC too.
|
||||
CardButtonGateway::ID => CardButtonGateway::ID,
|
||||
AxoGateway::ID => 'axo',
|
||||
);
|
||||
return array_key_exists( $current_page_id, $gateway_page_id_map )
|
||||
&& in_array( $gateway_page_id_map[ $current_page_id ], $allowed_gateways, true );
|
||||
|
|
|
@ -142,7 +142,7 @@ class Settings implements ContainerInterface {
|
|||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'smart_button_locations' => $this->default_button_locations,
|
||||
'smart_button_enable_styling_per_location' => true,
|
||||
'smart_button_enable_styling_per_location' => false,
|
||||
'pay_later_messaging_enabled' => true,
|
||||
'pay_later_button_enabled' => true,
|
||||
'pay_later_button_locations' => $this->default_pay_later_button_locations,
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue