Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Onboarding UI improvements #508

Merged
merged 11 commits into from
Feb 22, 2022
51 changes: 47 additions & 4 deletions modules/ppcp-onboarding/assets/css/onboarding.css
Original file line number Diff line number Diff line change
Expand Up @@ -59,29 +59,72 @@ ul.ppcp-onboarding-options-sublist {

.ppcp-muted-text {
opacity: 0.6;
font-size: 85%;
}

.ppcp-onboarding-header {
#field-ppcp_onboarading_header > td, #field-ppcp_onboarading_options > td {
padding: 0;
}

.ppcp-onboarding-header, .ppcp-onboarding-cards-options {
display: flex;
width: 1000px;
width: 1200px;
}

.ppcp-onboarding-header-left, .ppcp-onboarding-header-right {
flex: 50%;
}

.ppcp-onboarding-header-right {
text-align: right;
}

.ppcp-onboarding-header h2 {
margin-top: 0;
}

.ppcp-onboarding-header-left img {
height: 60px;
}

.ppcp-onboarding-header-cards img, .ppcp-onboarding-header-paypal-logos img {
margin: 5px;
}

.ppcp-onboarding-header-cards img {
height: 40px;
height: 37px;
}

.ppcp-onboarding-header-paypal-logos img {
height: 45px;
height: 32px;
}

.ppcp-onboarding-cards-options table {
margin-left: 35px;
margin-right: 15px;
}

.ppcp-onboarding-cards-options table td {
padding-top: 2px;
}

.ppcp-onboarding-cards-options table td:first-child {
vertical-align: top;
}

.ppcp-onboarding-cards-options table tr:not(:last-child) td {
padding-bottom: 0;
}

.ppcp-onboarding-cards-options table tr td:first-child {
width: 350px;
}

.ppcp-onboarding-cards-screen {
flex: 1;
align-self: center;
}

.ppcp-onboarding-cards-screen img {
width: 100%;
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 11 additions & 1 deletion modules/ppcp-onboarding/assets/js/onboarding.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,8 @@ const ppcp_onboarding = {
authCode: authCode,
sharedId: sharedId,
nonce: PayPalCommerceGatewayOnboarding.nonce,
env: env
env: env,
acceptCards: document.querySelector('#ppcp-onboarding-accept-cards').checked,
}
)
}
Expand Down Expand Up @@ -144,6 +145,15 @@ function ppcp_onboarding_productionCallback(...args) {
document.querySelectorAll(ppcpButtonSelectors.join()).forEach(
element => element.style.display = !isExpress ? '' : 'none'
);

const screemImg = document.querySelector('#ppcp-onboarding-cards-screen-img');
if (screemImg) {
const currentRb = Array.from(document.querySelectorAll('#ppcp-onboarding-dcc-options input[type="radio"]'))
.filter(rb => rb.checked)[0] ?? null;

const imgUrl = currentRb.getAttribute('data-screen-url');
screemImg.src = imgUrl;
}
};

const updateManualInputControls = (shown, isSandbox, isAnyEnvOnboarded) => {
Expand Down
4 changes: 3 additions & 1 deletion modules/ppcp-onboarding/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,9 @@
);
},
'onboarding.render-options' => static function ( ContainerInterface $container ) : OnboardingOptionsRenderer {
return new OnboardingOptionsRenderer();
return new OnboardingOptionsRenderer(
$container->get( 'onboarding.url' )
);
},
'onboarding.rest' => static function( $container ) : OnboardingRESTController {
return new OnboardingRESTController( $container );
Expand Down
2 changes: 1 addition & 1 deletion modules/ppcp-onboarding/src/Assets/OnboardingAssets.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ public function get_script_data() {
'current_state' => State::get_state_name( $this->state->current_state() ),
'current_env' => $this->environment->current_environment(),
'error_messages' => array(
'no_credentials' => __( 'Enter the credentials.', 'woocommerce-paypal-payments' ),
'no_credentials' => __( 'API credentials must be entered to save the settings.', 'woocommerce-paypal-payments' ),
),
);
}
Expand Down
21 changes: 21 additions & 0 deletions modules/ppcp-onboarding/src/Endpoint/LoginSellerEndpoint.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ public function handle_request(): bool {
$this->settings->set( 'sandbox_on', $is_sandbox );
$this->settings->set( 'products_dcc_enabled', null );
$this->settings->persist();

$endpoint = $is_sandbox ? $this->login_seller_sandbox : $this->login_seller_production;
$credentials = $endpoint->credentials_for(
$data['sharedId'],
Expand All @@ -143,10 +144,30 @@ public function handle_request(): bool {
}
$this->settings->set( 'client_secret', $credentials->client_secret );
$this->settings->set( 'client_id', $credentials->client_id );

$accept_cards = (bool) ( $data['acceptCards'] ?? true );
$funding_sources = array();
if ( $this->settings->get( 'disable_funding' ) ) {
$funding_sources = $this->settings->get( 'disable_funding' );
if ( ! is_array( $funding_sources ) ) {
$funding_sources = array();
}
}
if ( $accept_cards ) {
$funding_sources = array_diff( $funding_sources, array( 'card' ) );
} else {
if ( ! in_array( 'card', $funding_sources, true ) ) {
$funding_sources[] = 'card';
}
}
$this->settings->set( 'disable_funding', $funding_sources );

$this->settings->persist();

if ( $this->cache->has( PayPalBearer::CACHE_KEY ) ) {
$this->cache->delete( PayPalBearer::CACHE_KEY );
}

wp_schedule_single_event(
time() + 5,
WebhookRegistrar::EVENT_HOOK
Expand Down
155 changes: 143 additions & 12 deletions modules/ppcp-onboarding/src/Render/OnboardingOptionsRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,22 @@
* Class OnboardingRenderer
*/
class OnboardingOptionsRenderer {
/**
* The module url.
*
* @var string
*/
private $module_url;

/**
* OnboardingOptionsRenderer constructor.
*
* @param string $module_url The module url (for assets).
*/
public function __construct( string $module_url ) {
$this->module_url = $module_url;
}

/**
* Renders the onboarding options.
*
Expand All @@ -23,7 +39,7 @@ public function render( bool $is_shop_supports_dcc ): string {
<ul class="ppcp-onboarding-options">
<li>
<label><input type="checkbox" disabled checked> ' .
__( 'Accept PayPal, Venmo, Pay Later and local payment methods', 'woocommerce-paypal-payments' ) . '
__( 'Enable PayPal Payments — includes PayPal, Venmo, Pay Later — with fraud protection', 'woocommerce-paypal-payments' ) . '
</label>
</li>
<li>
Expand All @@ -44,25 +60,140 @@ private function render_dcc( bool $is_shop_supports_dcc ): string {
$items = array();

if ( $is_shop_supports_dcc ) {
$items[] = '
$dcc_table_rows = array(
$this->render_table_row(
__( 'Credit & Debit Card form fields', 'woocommerce-paypal-payments' ),
__( 'Customizable user experience', 'woocommerce-paypal-payments' )
),
$this->render_table_row(
__( 'Credit & Debit Card pricing', 'woocommerce-paypal-payments' ),
__( '2.59% + $0.49', 'woocommerce-paypal-payments' )
),
$this->render_table_row(
__( 'Seller Protection', 'woocommerce-paypal-payments' ),
__( 'Yes', 'woocommerce-paypal-payments' ),
__( 'No matter what you sell, Seller Protection can help you avoid chargebacks, reversals, and fees on eligible PayPal payment transactions — even when a customer has filed a dispute.', 'woocommerce-paypal-payments' ),
__( 'On eligible PayPal transactions', 'woocommerce-paypal-payments' )
),
$this->render_table_row(
__( 'Advanced Fraud Protection', 'woocommerce-paypal-payments' ),
__( 'Yes', 'woocommerce-paypal-payments' ),
__( 'Included with Advanced Checkout at no extra cost, Fraud Protection gives you the insight and control you need to better balance chargebacks and declines.', 'woocommerce-paypal-payments' )
),
$this->render_table_row(
__( 'Chargeback Protection', 'woocommerce-paypal-payments' ),
__( 'Yes', 'woocommerce-paypal-payments' ),
__( 'If you choose this optional, fee-based alternative to Fraud Protection, PayPal will manage chargebacks for eligible credit and debit card transactions — so you won’t have to worry about unexpected costs.', 'woocommerce-paypal-payments' ),
__( 'Extra 0.4% per transaction', 'woocommerce-paypal-payments' )
),
$this->render_table_row(
__( 'Additional Vetting and Underwriting Required', 'woocommerce-paypal-payments' ),
__( 'Yes', 'woocommerce-paypal-payments' ),
__( 'Business Ownership and other business information will be required during the application for Advanced Card Processing.', 'woocommerce-paypal-payments' )
),
$this->render_table_row(
__( 'Seller Account Type', 'woocommerce-paypal-payments' ),
__( 'Business', 'woocommerce-paypal-payments' )
),
);
$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' .
' title="' . __( 'PayPal acts as the payment processor for card transactions. You can add optional features like Chargeback Protection for more security.', 'woocommerce-paypal-payments' ) . '"'
. '>
<input type="radio" id="ppcp-onboarding-dcc-acdc" name="ppcp_onboarding_dcc" value="acdc" checked ' .
'data-screen-url="' . $this->get_screen_url( 'acdc' ) . '"> ' .
__( 'Advanced Card Processing', 'woocommerce-paypal-payments' ) . '
</label>
<table>
' . implode( '', $dcc_table_rows ) . '
</table>
</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' ) . '
$basic_table_rows = array(
$this->render_table_row(
__( 'Credit & Debit Card form fields', 'woocommerce-paypal-payments' ),
__( 'Prebuilt user experience', 'woocommerce-paypal-payments' )
),
$this->render_table_row(
__( 'Credit & Debit Card pricing', 'woocommerce-paypal-payments' ),
__( '3.49% + $0.49', 'woocommerce-paypal-payments' )
),
$this->render_table_row(
__( 'Seller Protection', 'woocommerce-paypal-payments' ),
__( 'Yes', 'woocommerce-paypal-payments' ),
__( 'No matter what you sell, Seller Protection can help you avoid chargebacks, reversals, and fees on eligible PayPal payment transactions — even when a customer has filed a dispute.', 'woocommerce-paypal-payments' ),
__( 'On eligible PayPal transactions', 'woocommerce-paypal-payments' )
),
$this->render_table_row(
__( 'Seller Account Type', 'woocommerce-paypal-payments' ),
__( 'Business or Personal', 'woocommerce-paypal-payments' ),
__( '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[] = '
<li ' . ( ! $is_shop_supports_dcc ? 'style="display: none;"' : '' ) . '>
<label ' .
' title="' . __( 'Card transactions are managed by PayPal, which simplifies compliance requirements for you.', 'woocommerce-paypal-payments' ) . '"'
. '>
<input type="radio" id="ppcp-onboarding-dcc-basic" name="ppcp_onboarding_dcc" value="basic" ' .
( ! $is_shop_supports_dcc ? 'checked' : '' ) .
' data-screen-url="' . $this->get_screen_url( 'basic' ) . '"' .
'> ' .
__( 'Standard Card Processing', 'woocommerce-paypal-payments' ) . '
</label>
<table>
' . implode( $basic_table_rows ) . '
</table>
</li>';

return '<ul id="ppcp-onboarding-dcc-options" class="ppcp-onboarding-options-sublist">' .
return '
<div class="ppcp-onboarding-cards-options">
<ul id="ppcp-onboarding-dcc-options" class="ppcp-onboarding-options-sublist">' .
implode( '', $items ) .
'</ul>';
'
</ul>
<div class="ppcp-onboarding-cards-screen">' .
( $is_shop_supports_dcc ? '<img id="ppcp-onboarding-cards-screen-img" />' : '' ) . '
</div>
</div>';
}

/**
* Returns HTML of a row for the cards options tables.
*
* @param string $header The text in the first cell.
* @param string $value The text in the second cell.
* @param string $tooltip The text shown on hover.
* @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 {
$value_html = $value;
if ( $note ) {
$value_html .= '<br/><span class="ppcp-muted-text">' . $note . '</span>';
}

$row_attributes_html = '';
if ( $tooltip ) {
$row_attributes_html .= 'title="' . $tooltip . '"';
}

return "
<tr $row_attributes_html>
<td>$header</td>
<td>$value_html</td>
</tr>";
}

/**
* Returns the screen image URL.
*
* @param string $key The image suffix, 'acdc' or 'basic'.
* @return string
*/
private function get_screen_url( string $key ): string {
return untrailingslashit( $this->module_url ) . "/assets/images/cards-screen-$key.png";
}
}
2 changes: 1 addition & 1 deletion modules/ppcp-onboarding/src/Render/OnboardingRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public function render( bool $is_production, array $products ) {
$this->render_button(
$this->get_signup_link( $is_production, $products ),
$id,
$is_production ? __( 'Connect with PayPal', 'woocommerce-paypal-payments' ) : __( 'Test payments with PayPal sandbox', 'woocommerce-paypal-payments' ),
$is_production ? __( 'Activate PayPal', 'woocommerce-paypal-payments' ) : __( 'Test payments with PayPal sandbox', 'woocommerce-paypal-payments' ),
$is_production ? 'primary' : 'secondary',
$is_production ? 'production' : 'sandbox'
);
Expand Down
21 changes: 15 additions & 6 deletions modules/ppcp-wc-gateway/assets/images/amex.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading