New onboarding options, buttons

This commit is contained in:
Alex P 2022-01-14 14:02:33 +02:00
parent 3b488fbf8e
commit ff8c6fdf01
7 changed files with 348 additions and 191 deletions

View file

@ -35,8 +35,7 @@
display: unset;
}
#field-production_toggle_manual_input button,
#field-sandbox_toggle_manual_input button {
#field-toggle_manual_input button {
color: #0073aa;
transition-property: border, background, color;
transition-duration: .05s;
@ -49,8 +48,7 @@
padding: 0;
}
#field-sandbox_toggle_manual_input.onboarded,
#field-production_toggle_manual_input.onboarded {
#field-toggle_manual_input.onboarded {
display: none;
}
@ -92,3 +90,15 @@
.input-text[pattern]:invalid {
border: red solid 2px;
}
ul.ppcp-onboarding-options, ul.ppcp-onboarding-options-sublist {
list-style: none;
}
ul.ppcp-onboarding-options-sublist {
margin-left: 15px;
}
.ppcp-muted-text {
opacity: 0.6;
}

View file

@ -15,7 +15,7 @@ const ppcp_onboarding = {
return;
}
// Add event listeners to buttons.
// Add event listeners to buttons preventing link clicking if PayPal init failed.
buttons.forEach(
(element) => {
if (element.hasAttribute('data-ppcp-button-initialized')) {
@ -137,8 +137,6 @@ const credentialToggle = (forProduction) => {
const toggleSandboxProduction = (showProduction) => {
const productionDisplaySelectors = [
'#field-credentials_production_heading',
'#field-production_toggle_manual_input',
'#field-ppcp_onboarding_production',
];
const productionClassSelectors = [
@ -150,8 +148,6 @@ const toggleSandboxProduction = (showProduction) => {
];
const sandboxDisplaySelectors = [
'#field-credentials_sandbox_heading',
'#field-sandbox_toggle_manual_input',
'#field-ppcp_onboarding_sandbox',
];
const sandboxClassSelectors = [
'#field-ppcp_disconnect_sandbox',
@ -197,6 +193,34 @@ const toggleSandboxProduction = (showProduction) => {
)
};
const updateOptionsState = () => {
const cardsChk = document.querySelector('#ppcp-onboarding-accept-cards');
document.querySelectorAll('#ppcp-onboarding-dcc-options input').forEach(input => {
input.disabled = !cardsChk.checked;
});
const basicRb = document.querySelector('#ppcp-onboarding-dcc-basic');
const isExpress = !cardsChk.checked || basicRb.checked;
const expressButtonSelectors = [
'#field-ppcp_onboarding_production_express',
'#field-ppcp_onboarding_sandbox_express',
];
const ppcpButtonSelectors = [
'#field-ppcp_onboarding_production_ppcp',
'#field-ppcp_onboarding_sandbox_ppcp',
];
document.querySelectorAll(expressButtonSelectors.join()).forEach(
element => element.style.display = isExpress ? '' : 'none'
);
document.querySelectorAll(ppcpButtonSelectors.join()).forEach(
element => element.style.display = !isExpress ? '' : 'none'
);
};
const disconnect = (event) => {
event.preventDefault();
const fields = event.target.classList.contains('production') ? [
@ -234,7 +258,6 @@ const disconnect = (event) => {
}
);
// Prevent a possibly dirty form arising from this particular checkbox.
if (sandboxSwitchElement) {
sandboxSwitchElement.addEventListener(
'click',
@ -243,6 +266,7 @@ const disconnect = (event) => {
toggleSandboxProduction( ! value );
// Prevent a possibly dirty form arising from this particular checkbox.
event.preventDefault();
event.stopPropagation();
setTimeout( () => {
@ -253,13 +277,23 @@ const disconnect = (event) => {
);
}
document.querySelectorAll('#field-sandbox_toggle_manual_input button, #field-production_toggle_manual_input button').forEach(
document.querySelectorAll('.ppcp-onboarding-options input').forEach(
(element) => {
element.addEventListener('click', updateOptionsState);
}
);
updateOptionsState();
document.querySelectorAll('#field-toggle_manual_input button').forEach(
(button) => {
button.addEventListener(
'click',
(event) => {
event.preventDefault();
const isProduction = event.target.classList.contains('production-toggle');
const isProduction = ! sandboxSwitchElement.checked;
toggleSandboxProduction(isProduction);
credentialToggle(isProduction);
}
)

View file

@ -18,6 +18,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnerReferrals;
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
use WooCommerce\PayPalCommerce\Onboarding\Assets\OnboardingAssets;
use WooCommerce\PayPalCommerce\Onboarding\Endpoint\LoginSellerEndpoint;
use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingOptionsRenderer;
use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingRenderer;
use WooCommerce\PayPalCommerce\Onboarding\OnboardingRESTController;
@ -212,6 +213,9 @@ return array(
$partner_referrals_data
);
},
'onboarding.render-options' => static function ( ContainerInterface $container ) : OnboardingOptionsRenderer {
return new OnboardingOptionsRenderer();
},
'onboarding.rest' => static function( $container ) : OnboardingRESTController {
return new OnboardingRESTController( $container );
},

View file

@ -0,0 +1,68 @@
<?php
/**
* Renders the onboarding options.
*
* @package WooCommerce\PayPalCommerce\Onboarding\Render
*/
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\Onboarding\Render;
/**
* Class OnboardingRenderer
*/
class OnboardingOptionsRenderer {
/**
* Renders the onboarding options.
*
* @param bool $is_shop_supports_dcc Whether the shop can use DCC (country, currency).
*/
public function render( bool $is_shop_supports_dcc ): string {
return '
<ul class="ppcp-onboarding-options">
<li>
<label><input type="checkbox" disabled checked> ' .
__( 'Accept PayPal, Venmo, Pay Later and local payment methods', 'woocommerce-paypal-payments' ) . '
</label>
</li>
<li>
<label><input type="checkbox" id="ppcp-onboarding-accept-cards" checked> ' .
__( 'Securely accept all major credit & debit cards on the strength of the PayPal network', 'woocommerce-paypal-payments' ) . '
</label>
</li>
<li>' . $this->render_dcc( $is_shop_supports_dcc ) . '</li>
</ul>';
}
/**
* Renders the onboarding DCC options.
*
* @param bool $is_shop_supports_dcc Whether the shop can use DCC (country, currency).
*/
private function render_dcc( bool $is_shop_supports_dcc ): string {
$items = array();
if ( $is_shop_supports_dcc ) {
$items[] = '
<li>
<label><input type="radio" id="ppcp-onboarding-dcc-acdc" name="ppcp_onboarding_dcc" value="acdc" checked> ' .
__( 'Advanced credit and debit card processing', 'woocommerce-paypal-payments' ) . '*<br/> ' .
__( '(With advanced fraud protection and fully customizable card fields)', 'woocommerce-paypal-payments' ) . '
<span class="ppcp-muted-text">*' . __( 'Additional onboarding steps required', 'woocommerce-paypal-payments' ) . '</span>
</label>
</li>';
}
$items[] = '
<li>
<label><input type="radio" id="ppcp-onboarding-dcc-basic" name="ppcp_onboarding_dcc" value="basic" ' . ( ! $is_shop_supports_dcc ? 'checked' : '' ) . '> ' .
__( 'Basic credit and debit card processing', 'woocommerce-paypal-payments' ) . '
</label>
</li>';
return '<ul id="ppcp-onboarding-dcc-options" class="ppcp-onboarding-options-sublist">' .
implode( '', $items ) .
'</ul>';
}
}

View file

@ -97,9 +97,11 @@ class OnboardingRenderer {
*/
public function render( bool $is_production, array $products ) {
try {
$id = 'connect-to' . ( $is_production ? 'production' : 'sandbox' ) . strtolower( implode( '-', $products ) );
$this->render_button(
$this->get_signup_link( $is_production, $products ),
$is_production ? 'connect-to-production' : 'connect-to-sandbox',
$id,
$is_production ? __( 'Connect PayPal', 'woocommerce-paypal-payments' ) : __( 'Test Payments', 'woocommerce-paypal-payments' ),
$is_production ? 'primary' : 'secondary',
$is_production ? 'production' : 'sandbox'

View file

@ -17,6 +17,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
use WooCommerce\PayPalCommerce\Button\Helper\MessagesDisclaimers;
use WooCommerce\PayPalCommerce\Onboarding\Environment;
use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingOptionsRenderer;
use WooCommerce\PayPalCommerce\Onboarding\State;
use WooCommerce\PayPalCommerce\WcGateway\Admin\OrderTablePaymentStatusColumn;
use WooCommerce\PayPalCommerce\WcGateway\Admin\PaymentStatusOrderDetail;
@ -257,22 +258,15 @@ return array(
$state = $container->get( 'onboarding.state' );
$messages_disclaimers = $container->get( 'button.helper.messages-disclaimers' );
$fields = array(
'sandbox_on' => array(
'title' => __( 'Sandbox', 'woocommerce-paypal-payments' ),
'type' => 'checkbox',
'label' => __( 'To test your WooCommerce installation, you can use the sandbox mode.', 'woocommerce-paypal-payments' ),
'default' => 0,
'screens' => array(
State::STATE_START,
State::STATE_PROGRESSIVE,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => 'paypal',
),
$dcc_applies = $container->get( 'api.helpers.dccapplies' );
assert( $dcc_applies instanceof DccApplies );
// Production credentials.
$is_shop_supports_dcc = $dcc_applies->for_country_currency();
$onboarding_options_renderer = $container->get( 'onboarding.render-options' );
assert( $onboarding_options_renderer instanceof OnboardingOptionsRenderer );
$fields = array(
'credentials_production_heading' => array(
'heading' => __( 'API Credentials', 'woocommerce-paypal-payments' ),
'type' => 'ppcp-heading',
@ -283,8 +277,34 @@ return array(
'requirements' => array(),
'gateway' => 'paypal',
),
'ppcp_onboarding_production' => array(
'title' => __( 'Connect to PayPal', 'woocommerce-paypal-payments' ),
'credentials_sandbox_heading' => array(
'heading' => __( 'Sandbox API Credentials', 'woocommerce-paypal-payments' ),
'type' => 'ppcp-heading',
'screens' => array(
State::STATE_PROGRESSIVE,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => 'paypal',
'description' => __( 'Your account setting is set to sandbox, no real charging takes place. To accept live payments, switch your environment to live and connect your PayPal account.', 'woocommerce-paypal-payments' ),
),
'ppcp_onboarading_options' => array(
'type' => 'ppcp-text',
'text' => $onboarding_options_renderer->render( $is_shop_supports_dcc ),
'raw' => true,
'screens' => array(
State::STATE_START,
State::STATE_PROGRESSIVE,
),
'requirements' => array(),
'gateway' => 'paypal',
),
// We need to have a button for each option (ppcp, express)
// because currently the only documented way to use the PayPal onboarding JS library
// is to have the buttons before loading the script.
'ppcp_onboarding_production_ppcp' => array(
'type' => 'ppcp_onboarding',
'screens' => array(
State::STATE_START,
@ -292,10 +312,49 @@ return array(
State::STATE_ONBOARDED,
),
'env' => 'production',
'products' => array( 'PPCP' ),
'requirements' => array(),
'gateway' => 'paypal',
'description' => __( 'Setup or link an existing PayPal account.', 'woocommerce-paypal-payments' ),
),
'ppcp_onboarding_production_express' => array(
'type' => 'ppcp_onboarding',
'screens' => array(
State::STATE_START,
State::STATE_PROGRESSIVE,
State::STATE_ONBOARDED,
),
'env' => 'production',
'products' => array( 'EXPRESS_CHECKOUT' ),
'requirements' => array(),
'gateway' => 'paypal',
),
'ppcp_onboarding_sandbox_ppcp' => array(
'type' => 'ppcp_onboarding',
'screens' => array(
State::STATE_START,
State::STATE_PROGRESSIVE,
State::STATE_ONBOARDED,
),
'env' => 'sandbox',
'products' => array( 'PPCP' ),
'requirements' => array(),
'gateway' => 'paypal',
'description' => __( 'Prior to accepting live payments, you can test payments on your WooCommerce platform in a safe PayPal sandbox environment.', 'woocommerce-paypal-payments' ),
),
'ppcp_onboarding_sandbox_express' => array(
'type' => 'ppcp_onboarding',
'screens' => array(
State::STATE_START,
State::STATE_PROGRESSIVE,
State::STATE_ONBOARDED,
),
'env' => 'sandbox',
'products' => array( 'EXPRESS_CHECKOUT' ),
'requirements' => array(),
'gateway' => 'paypal',
'description' => __( 'Prior to accepting live payments, you can test payments on your WooCommerce platform in a safe PayPal sandbox environment.', 'woocommerce-paypal-payments' ),
),
'ppcp_disconnect_production' => array(
'title' => __( 'Disconnect from PayPal', 'woocommerce-paypal-payments' ),
'type' => 'ppcp-text',
@ -311,11 +370,38 @@ return array(
'gateway' => 'paypal',
'description' => __( 'Click to reset current credentials and use another account.', 'woocommerce-paypal-payments' ),
),
'production_toggle_manual_input' => array(
'ppcp_disconnect_sandbox' => array(
'title' => __( 'Disconnect from PayPal Sandbox', 'woocommerce-paypal-payments' ),
'type' => 'ppcp-text',
'classes' => array( State::STATE_ONBOARDED === $state->sandbox_state() ? 'onboarded' : '' ),
'text' => '<button type="button" class="button ppcp-disconnect sandbox">' . esc_html__( 'Disconnect', 'woocommerce-paypal-payments' ) . '</button>',
'screens' => array(
State::STATE_START,
State::STATE_PROGRESSIVE,
State::STATE_ONBOARDED,
),
'env' => 'production',
'requirements' => array(),
'gateway' => 'paypal',
'description' => __( 'Click to reset current credentials and use another account.', 'woocommerce-paypal-payments' ),
),
'toggle_manual_input' => array(
'type' => 'ppcp-text',
'title' => __( 'Manual mode', 'woocommerce-paypal-payments' ),
'classes' => array( State::STATE_ONBOARDED === $state->production_state() ? 'onboarded' : '' ),
'text' => '<button type="button" id="ppcp[production_toggle_manual_input]" class="production-toggle">' . __( 'Toggle to manual credential input', 'woocommerce-paypal-payments' ) . '</button>',
'text' => '<button type="button" id="ppcp[toggle_manual_input]">' . __( 'Toggle to manual credential input', 'woocommerce-paypal-payments' ) . '</button>',
'screens' => array(
State::STATE_START,
State::STATE_PROGRESSIVE,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => 'paypal',
),
'sandbox_on' => array(
'title' => __( 'Sandbox', 'woocommerce-paypal-payments' ),
'type' => 'checkbox',
'label' => __( 'To test your WooCommerce installation, you can use the sandbox mode.', 'woocommerce-paypal-payments' ),
'default' => 0,
'screens' => array(
State::STATE_START,
State::STATE_PROGRESSIVE,
@ -386,60 +472,6 @@ return array(
'gateway' => 'paypal',
),
// Sandbox credentials.
'credentials_sandbox_heading' => array(
'heading' => __( 'Sandbox API Credentials', 'woocommerce-paypal-payments' ),
'type' => 'ppcp-heading',
'screens' => array(
State::STATE_PROGRESSIVE,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => 'paypal',
'description' => __( 'Your account setting is set to sandbox, no real charging takes place. To accept live payments, switch your environment to live and connect your PayPal account.', 'woocommerce-paypal-payments' ),
),
'ppcp_onboarding_sandbox' => array(
'title' => __( 'Connect to PayPal', 'woocommerce-paypal-payments' ),
'type' => 'ppcp_onboarding',
'screens' => array(
State::STATE_START,
State::STATE_PROGRESSIVE,
State::STATE_ONBOARDED,
),
'env' => 'sandbox',
'requirements' => array(),
'gateway' => 'paypal',
'description' => __( 'Setup or link an existing PayPal Sandbox account.', 'woocommerce-paypal-payments' ),
),
'ppcp_disconnect_sandbox' => array(
'title' => __( 'Disconnect from PayPal Sandbox', 'woocommerce-paypal-payments' ),
'type' => 'ppcp-text',
'classes' => array( State::STATE_ONBOARDED === $state->sandbox_state() ? 'onboarded' : '' ),
'text' => '<button type="button" class="button ppcp-disconnect sandbox">' . esc_html__( 'Disconnect', 'woocommerce-paypal-payments' ) . '</button>',
'screens' => array(
State::STATE_START,
State::STATE_PROGRESSIVE,
State::STATE_ONBOARDED,
),
'env' => 'production',
'requirements' => array(),
'gateway' => 'paypal',
'description' => __( 'Click to reset current credentials and use another account.', 'woocommerce-paypal-payments' ),
),
'sandbox_toggle_manual_input' => array(
'type' => 'ppcp-text',
'title' => __( 'Manual mode', 'woocommerce-paypal-payments' ),
'classes' => array( State::STATE_ONBOARDED === $state->sandbox_state() ? 'onboarded' : '' ),
'text' => '<button type="button" id="ppcp[sandbox_toggle_manual_input]" class="sandbox-toggle">' . __( 'Toggle to manual credential input', 'woocommerce-paypal-payments' ) . '</button>',
'screens' => array(
State::STATE_START,
State::STATE_PROGRESSIVE,
State::STATE_ONBOARDED,
),
'requirements' => array(),
'gateway' => 'paypal',
),
'merchant_email_sandbox' => array(
'title' => __( 'Sandbox Email address', 'woocommerce-paypal-payments' ),
'classes' => array( State::STATE_ONBOARDED === $state->sandbox_state() ? 'onboarded' : '' ),
@ -1935,26 +1967,26 @@ return array(
unset( $fields['vault_enabled'] );
}
if ( State::STATE_ONBOARDED === $state->production_state() ) {
unset( $fields['ppcp_onboarding_production'] );
} else {
unset( $fields['ppcp_disconnect_production'] );
if ( State::STATE_ONBOARDED === $state->production_state() || State::STATE_ONBOARDED === $state->sandbox_state() ) {
unset( $fields['ppcp_onboarading_options'] );
unset( $fields['ppcp_onboarding_sandbox_ppcp'] );
unset( $fields['ppcp_onboarding_sandbox_express'] );
unset( $fields['ppcp_onboarding_production_ppcp'] );
unset( $fields['ppcp_onboarding_production_express'] );
}
if ( State::STATE_ONBOARDED === $state->sandbox_state() ) {
unset( $fields['ppcp_onboarding_sandbox'] );
if ( State::STATE_ONBOARDED === $state->production_state() ) {
unset( $fields['ppcp_disconnect_sandbox'] );
} elseif ( State::STATE_ONBOARDED === $state->sandbox_state() ) {
unset( $fields['ppcp_disconnect_production'] );
} else {
unset( $fields['ppcp_disconnect_sandbox'] );
unset( $fields['ppcp_disconnect_production'] );
}
/**
* Depending on your store location, some credit cards can't be used.
* Here, we filter them out.
*
* The DCC Applies object.
*
* @var DccApplies $dcc_applies
*/
$dcc_applies = $container->get( 'api.helpers.dccapplies' );
$card_options = $fields['disable_cards']['options'];
foreach ( $card_options as $card => $label ) {
if ( $dcc_applies->can_process_card( $card ) ) {

View file

@ -475,7 +475,14 @@ $data_rows_html
* @param array $config The configuration array.
*/
private function render_text( array $config ) {
$raw = $config['raw'] ?? false;
if ( $raw ) {
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo $config['text'];
} else {
echo wp_kses_post( $config['text'] );
}
if ( isset( $config['hidden'] ) ) {
$value = $this->settings->has( $config['hidden'] ) ?
(string) $this->settings->get( $config['hidden'] )