Merge pull request #3111 from woocommerce/PCP-4192-new-ux-defaults-testing

Pcp 4192 new ux defaults testing
This commit is contained in:
Emili Castells 2025-02-14 14:47:19 +01:00 committed by GitHub
commit be6cbd465f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 1240 additions and 727 deletions

View file

@ -0,0 +1,94 @@
# Applying Default Configuration After Onboarding
The `OnboardingProfile` has a property named `setup_done`, which indicated whether the default
configuration was set up.
### `OnboardingProfile::is_setup_done()`
This flag indicated, whether the default plugin configuration was applied or not.
It's set to true after the merchant's authentication attempt was successful, and settings were
adjusted.
The only way to reset this flag, is to enable the "**Start Over**" toggle and disconnecting the
merchant:
https://example.com/wp-admin/admin.php?page=wc-settings&tab=checkout&section=ppcp-gateway&panel=settings#disconnect-merchant
### `class SettingsDataManager`
The `SettingsDataManager` service is responsible for applying all defaults options at the end of the
onboarding process.
### `SettingsDataManager::set_defaults_for_new_merchant()`
This method expects a DTO argument (`ConfigurationFlagsDTO`) that provides relevant details about
the merchant and onboarding choices.
It verifies, if default settings were already applied (by checking the
`OnboardingProfile::is_setup_done()` state). If not done yet, the DTO object is inspected to
initialize the plugin's configuration, before marking the `setup_done` flag as completed.
## Default Settings Matrix
### Decision Flags
- **Country**: The merchant country.
- According to PayPal settings, not the WooCommerce country
- Test case: Set Woo country to Germany and sign in with a US merchant account; this should
trigger the "Country: US" branches below.
- **Seller Type**: Business or Casual.
- According to PayPal, not the onboarding choice
- Test case: Choose "Personal" during onboarding but log in with a business account; this should
trigger the "Account: Business" branches below.
- **Subscriptions**: An onboarding choice on the "Products" screen.
- **Cards**: An onboarding choice, on the "Checkout Options" screen.
- Refers to the first option on the checkout options screen ("Custom Card Fields", etc.)
### Payment Methods
By default, all payment methods are turned off after onboarding, unless the conditions specified in
the following table are met.
| Payment Method | Country | Seller Type | Subscriptions | Cards | Notes |
|----------------|---------|-------------|---------------|-------|-------------------------------|
| Venmo | US | *any* | *any* | *any* | Always |
| Pay Later | US | *any* | *any* | *any* | Always |
| ACDC | US | Business | *any* | ✅ | Greyed out for Casual Sellers |
| BCDC | US | *any* | *any* | ✅ | |
| Apple Pay | US | Business | *any* | ✅ | Based on feature eligibility |
| Google Pay | US | Business | *any* | ✅ | Based on feature eligibility |
| All APMs | US | Business | *any* | ✅ | Based on feature eligibility |
### Settings
| Feature | Country | Seller-Type | Subscriptions | Cards | Notes |
|-----------------------------|---------|-------------|---------------|-------|----------------------------|
| Pay Now Experience | US | _any_ | _any_ | _any_ | |
| Save PayPal and Venmo | US | Business | ✅ | _any_ | |
| Save Credit and Debit Cards | US | Business | ✅ | ✅ | Requires ACDC eligibility* |
- `*` If merchant has no ACDC eligibility, the setting should be disabled (not toggleable).
### Styling
All US merchants use the same settings, regardless of onboarding choices.
| Button Location | Enabled | Displayed Payment Methods |
|------------------|---------|-------------------------------------------------|
| Cart | ✅ | PayPal, Venmo, Pay Later, Google Pay, Apple Pay |
| Classic Checkout | ✅ | PayPal, Venmo, Pay Later, Google Pay, Apple Pay |
| Express Checkout | ✅ | PayPal, Venmo, Pay Later, Google Pay, Apple Pay |
| Mini Cart | ✅ | PayPal, Venmo, Pay Later, Google Pay, Apple Pay |
| Product Page | ✅ | PayPal, Venmo, Pay Later |
### Pay Later Messaging
All US merchants use the same settings, regardless of onboarding choices.
| Location | Enabled |
|-------------------|---------|
| Product | ✅ |
| Cart | ✅ |
| Checkout | ✅ |
| Home | ❌ |
| Shop | ❌ |
| WooCommerce Block | ❌ |

View file

@ -2,12 +2,18 @@
* Modal for disconnecting the merchant from the current PayPal account.
*/
.ppcp--modal-disconnect {
.ppcp--toggle-danger {
--wp-components-color-accent: #cc1818
.ppcp--toggle-danger .components-form-toggle {
&.is-checked {
--wp-components-color-accent: #cc1818;
}
}
.ppcp--action-buttons {
text-align: right;
margin-top: 32px;
.components-button {
transition: background 0.3s;
}
}
}

View file

@ -2,7 +2,7 @@ import { Icon } from '@wordpress/components';
import { chevronDown, chevronUp } from '@wordpress/icons';
import classNames from 'classnames';
import { useAccordionState } from '../../hooks/useAccordionState';
import { useToggleState } from '../../hooks/useToggleState';
import {
Content,
Description,
@ -21,7 +21,7 @@ const Accordion = ( {
children = null,
className = '',
} ) => {
const { isOpen, toggleOpen } = useAccordionState( { id, initiallyOpen } );
const { isOpen, toggleOpen } = useToggleState( id, initiallyOpen );
const wrapperClasses = classNames( 'ppcp-r-accordion', className, {
'ppcp--is-open': isOpen,
} );

View file

@ -3,10 +3,11 @@ import { Button, Modal, ToggleControl } from '@wordpress/components';
import { useCallback, useState } from '@wordpress/element';
import { CommonHooks } from '../../../../../../data';
import { useToggleState } from '../../../../../../hooks/useToggleState';
import { HStack } from '../../../../../ReusableComponents/Stack';
const DisconnectButton = () => {
const [ isOpen, setIsOpen ] = useState( false );
const { isOpen, setIsOpen } = useToggleState( 'disconnect-merchant' );
const [ resetFlag, setResetFlag ] = useState( false );
const { disconnectMerchant } = CommonHooks.useDisconnectMerchant();
@ -78,7 +79,7 @@ const DisconnectButton = () => {
</Button>
<Button
variant="primary"
isDestructive={ true }
isDestructive={ resetFlag }
onClick={ handleConfirm }
>
{ __(

View file

@ -2,22 +2,21 @@ import { __ } from '@wordpress/i18n';
import { PaymentHooks, StylingHooks } from '../../../../../../data';
import { CheckboxStylingSection } from '../Layout';
import { useMemo } from '@wordpress/element';
const SectionPaymentMethods = ( { location } ) => {
const { paymentMethods, setPaymentMethods, choices } =
StylingHooks.usePaymentMethodProps( location );
const { all: allMethods } = PaymentHooks.usePaymentMethods();
const methods = PaymentHooks.usePaymentMethods();
const methodIds = [];
methods.all.forEach( ( method ) => {
if ( method.enabled === true ) {
methodIds.push( method.id );
}
} );
const filteredChoices = choices.filter( ( choice ) => {
return methodIds.includes( choice.paymentMethod );
} );
const filteredChoices = useMemo( () => {
return choices.filter( ( choice ) => {
const methodConfig = allMethods.find(
( i ) => i.id === choice.value
);
return methodConfig?.enabled;
} );
}, [ choices, allMethods ] );
return (
<CheckboxStylingSection

View file

@ -104,33 +104,28 @@ export const STYLING_SHAPES = {
};
export const STYLING_PAYMENT_METHODS = {
paypal: {
value: '',
'ppcp-gateway': {
value: 'ppcp-gateway',
label: __( 'PayPal', 'woocommerce-paypal-payments' ),
checked: true,
disabled: true,
paymentMethod: 'ppcp-gateway',
},
venmo: {
value: 'venmo',
label: __( 'Venmo', 'woocommerce-paypal-payments' ),
isFunding: true,
paymentMethod: 'venmo',
},
paylater: {
value: 'paylater',
'pay-later': {
value: 'pay-later',
label: __( 'Pay Later', 'woocommerce-paypal-payments' ),
isFunding: true,
paymentMethod: 'pay-later',
},
googlepay: {
value: 'googlepay',
'ppcp-googlepay': {
value: 'ppcp-googlepay',
label: __( 'Google Pay', 'woocommerce-paypal-payments' ),
paymentMethod: 'ppcp-googlepay',
},
applepay: {
value: 'applepay',
'ppcp-applepay': {
value: 'ppcp-applepay',
label: __( 'Apple Pay', 'woocommerce-paypal-payments' ),
paymentMethod: 'ppcp-applepay',
},
};

View file

@ -1,39 +0,0 @@
import { useEffect, useState } from '@wordpress/element';
const checkIfCurrentTab = ( id ) => {
return id && window.location.hash === `#${ id }`;
};
const determineInitialState = ( id, initiallyOpen ) => {
if ( initiallyOpen !== null ) {
return initiallyOpen;
}
return checkIfCurrentTab( id );
};
export function useAccordionState( { id = '', initiallyOpen = null } ) {
const [ isOpen, setIsOpen ] = useState(
determineInitialState( id, initiallyOpen )
);
useEffect( () => {
const handleHashChange = () => {
if ( checkIfCurrentTab( id ) ) {
setIsOpen( true );
}
};
window.addEventListener( 'hashchange', handleHashChange );
return () => {
window.removeEventListener( 'hashchange', handleHashChange );
};
}, [ id ] );
const toggleOpen = ( ev ) => {
setIsOpen( ! isOpen );
ev?.preventDefault();
return false;
};
return { isOpen, toggleOpen };
}

View file

@ -0,0 +1,50 @@
import { useCallback, useEffect, useState } from '@wordpress/element';
const checkIfCurrentTab = ( id ) => {
return id && window.location.hash === `#${ id }`;
};
const determineInitialState = ( id, initiallyOpen ) => {
if ( initiallyOpen !== null ) {
return initiallyOpen;
}
return checkIfCurrentTab( id );
};
/**
* Allows managing a toggle-able component, such as an accordion or a modal dialog.
*
* @param {string} [id=''] - If provided, the toggle can be opened via the URL.
* @param {null|boolean} [initiallyOpen=null] - If provided, it defines the initial open state.
* If omitted, the initial open state is determined by using the "id" logic (inspecting the URL).
* @return {{isOpen: unknown, toggleOpen: (function(*): boolean)}} Hook object.
*/
export function useToggleState( id = '', initiallyOpen = null ) {
const [ isOpen, setIsOpen ] = useState(
determineInitialState( id, initiallyOpen )
);
useEffect( () => {
const handleHashChange = () => {
if ( checkIfCurrentTab( id ) ) {
setIsOpen( true );
}
};
window.addEventListener( 'hashchange', handleHashChange );
return () => {
window.removeEventListener( 'hashchange', handleHashChange );
};
}, [ id ] );
const toggleOpen = useCallback(
( ev ) => {
setIsOpen( ! isOpen );
ev?.preventDefault();
return false;
},
[ isOpen ]
);
return { isOpen, setIsOpen, toggleOpen };
}

View file

@ -39,6 +39,10 @@ use WooCommerce\PayPalCommerce\Settings\Service\TodosEligibilityService;
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
use WooCommerce\PayPalCommerce\Settings\Service\DataSanitizer;
use WooCommerce\PayPalCommerce\Settings\Service\SettingsDataManager;
use WooCommerce\PayPalCommerce\Settings\Data\Definition\PaymentMethodsDefinition;
use WooCommerce\PayPalCommerce\PayLaterConfigurator\Factory\ConfigFactory;
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
use WooCommerce\PayPalCommerce\PayLaterConfigurator\Endpoint\SaveConfig;
return array(
'settings.url' => static function ( ContainerInterface $container ) : string {
@ -92,6 +96,25 @@ return array(
$container->get( 'settings.service.sanitizer' )
);
},
'settings.data.paylater-messaging' => static function ( ContainerInterface $container ) : array {
// TODO: Create an AbstractDataModel wrapper for this configuration!
$config_factors = $container->get( 'paylater-configurator.factory.config' );
assert( $config_factors instanceof ConfigFactory );
$save_config = $container->get( 'paylater-configurator.endpoint.save-config' );
assert( $save_config instanceof SaveConfig );
$settings = $container->get( 'wcgateway.settings' );
assert( $settings instanceof Settings );
$pay_later_config = $config_factors->from_settings( $settings );
return array(
'read' => $pay_later_config,
'save' => $save_config,
);
},
/**
* Checks if valid merchant connection details are stored in the DB.
*/
@ -108,7 +131,10 @@ return array(
return new CommonRestEndpoint( $container->get( 'settings.data.general' ) );
},
'settings.rest.payment' => static function ( ContainerInterface $container ) : PaymentRestEndpoint {
return new PaymentRestEndpoint( $container->get( 'settings.data.payment' ) );
return new PaymentRestEndpoint(
$container->get( 'settings.data.payment' ),
$container->get( 'settings.data.definition.methods' )
);
},
'settings.rest.styling' => static function ( ContainerInterface $container ) : StylingRestEndpoint {
return new StylingRestEndpoint(
@ -249,17 +275,16 @@ return array(
return new DataSanitizer();
},
'settings.service.data-manager' => static function ( ContainerInterface $container ) : SettingsDataManager {
$models = array(
return new SettingsDataManager(
$container->get( 'settings.data.definition.methods' ),
$container->get( 'settings.data.onboarding' ),
$container->get( 'settings.data.general' ),
$container->get( 'settings.data.settings' ),
$container->get( 'settings.data.styling' ),
$container->get( 'settings.data.payment' ),
$container->get( 'settings.data.settings' ),
$container->get( 'settings.data.paylater-messaging' ),
$container->get( 'settings.data.todos' ),
$container->get( 'settings.data.definition.todos' ),
);
return new SettingsDataManager( $models );
},
'settings.ajax.switch_ui' => static function ( ContainerInterface $container ) : SwitchSettingsUiEndpoint {
return new SwitchSettingsUiEndpoint(
@ -285,6 +310,11 @@ return array(
$container->get( 'settings.data.general' )
);
},
'settings.data.definition.methods' => static function ( ContainerInterface $container ) : PaymentMethodsDefinition {
return new PaymentMethodsDefinition(
$container->get( 'settings.data.payment' ),
);
},
'settings.service.todos_eligibilities' => static function ( ContainerInterface $container ) : TodosEligibilityService {
$features = apply_filters(
'woocommerce_paypal_payments_rest_common_merchant_features',

View file

@ -0,0 +1,47 @@
<?php
/**
* Data transfer object. Stores flags that are relevant for the default plugin
* configuration at the end of the onboarding process.
*
* @package WooCommerce\PayPalCommerce\Settings\DTO;
*/
declare( strict_types = 1 );
namespace WooCommerce\PayPalCommerce\Settings\DTO;
/**
* DTO that represents a plugin configuration.
*
* Intentionally has no internal logic, sanitation or validation.
*/
class ConfigurationFlagsDTO {
/**
* The merchant's country, which indicates availability of certain features.
*
* @var string
*/
public string $country_code = '';
/**
* Whether we configure a business account.
* If false, a personal (casual seller) account is set up.
*
* @var bool
*/
public bool $is_business_seller = false;
/**
* Whether credit card payments should be handled by our plugin.
*
* @var bool
*/
public bool $use_card_payments = false;
/**
* If the shop needs to process subscription payments.
*
* @var bool
*/
public bool $use_subscriptions = false;
}

View file

@ -0,0 +1,386 @@
<?php
/**
* PayPal Commerce Todos Definitions
*
* @package WooCommerce\PayPalCommerce\Settings\Data\Definition
*/
declare( strict_types = 1 );
namespace WooCommerce\PayPalCommerce\Settings\Data\Definition;
use WooCommerce\PayPalCommerce\Applepay\ApplePayGateway;
use WooCommerce\PayPalCommerce\Axo\Gateway\AxoGateway;
use WooCommerce\PayPalCommerce\Googlepay\GooglePayGateway;
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\BancontactGateway;
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\BlikGateway;
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\EPSGateway;
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\IDealGateway;
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\MultibancoGateway;
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\MyBankGateway;
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\P24Gateway;
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\TrustlyGateway;
use WooCommerce\PayPalCommerce\Settings\Data\PaymentSettings;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\OXXO\OXXO;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayUponInvoice\PayUponInvoiceGateway;
/**
* Class PaymentMethodsDefinition
*
* Provides a list of all payment methods that are available in the settings UI.
*/
class PaymentMethodsDefinition {
/**
* Data model that manages the payment method configuration.
*
* @var PaymentSettings
*/
private PaymentSettings $settings;
/**
* List of WooCommerce payment gateways.
*
* @var array|null
*/
private ?array $wc_gateways = null;
/**
* Constructor.
*
* @param PaymentSettings $settings Payment methods data model.
*/
public function __construct( PaymentSettings $settings ) {
$this->settings = $settings;
}
/**
* Returns the payment method definitions.
*
* @return array
*/
public function get_definitions() : array {
// Refresh the WooCommerce gateway details before we build the definitions.
$this->wc_gateways = WC()->payment_gateways()->payment_gateways();
$all_methods = array_merge(
$this->group_paypal_methods(),
$this->group_card_methods(),
$this->group_apms(),
);
$result = array();
foreach ( $all_methods as $method ) {
$result[ $method['id'] ] = $this->build_method_definition(
$method['id'],
$method['title'],
$method['description'],
$method['icon'],
$method['fields'] ?? array()
);
}
return $result;
}
/**
* Returns a new payment method configuration array that contains all
* common attributes which must be present in every method definition.
*
* @param string $gateway_id The payment method ID.
* @param string $title Admin-side payment method title.
* @param string $description Admin-side info about the payment method.
* @param string $icon Admin-side icon of the payment method.
* @param array|false $fields Optional. Additional fields to display in the edit modal.
* Setting this to false omits all fields.
* @return array Payment method definition.
*/
private function build_method_definition(
string $gateway_id,
string $title,
string $description,
string $icon,
$fields = array()
) : array {
$gateway = $this->wc_gateways[ $gateway_id ] ?? null;
$gateway_title = $gateway ? $gateway->get_title() : $title;
$gateway_description = $gateway ? $gateway->get_description() : $description;
$config = array(
'id' => $gateway_id,
'enabled' => $this->settings->is_method_enabled( $gateway_id ),
'title' => str_replace( '&amp;', '&', $gateway_title ),
'description' => $gateway_description,
'icon' => $icon,
'itemTitle' => $title,
'itemDescription' => $description,
);
if ( is_array( $fields ) ) {
$config['fields'] = array_merge(
array(
'checkoutPageTitle' => array(
'type' => 'text',
'default' => $gateway_title,
'label' => __( 'Checkout page title', 'woocommerce-paypal-payments' ),
),
'checkoutPageDescription' => array(
'type' => 'text',
'default' => $gateway ? $gateway->get_description() : '',
'label' => __( 'Checkout page description', 'woocommerce-paypal-payments' ),
),
),
$fields
);
}
return $config;
}
// Payment method groups.
/**
* Define PayPal related payment methods.
*
* @return array
*/
public function group_paypal_methods() : array {
$group = array(
array(
'id' => PayPalGateway::ID,
'title' => __( 'PayPal', 'woocommerce-paypal-payments' ),
'description' => __( 'Our all-in-one checkout solution lets you offer PayPal, Venmo, Pay Later options, and more to help maximize conversion.', 'woocommerce-paypal-payments' ),
'icon' => 'payment-method-paypal',
'fields' => array(
'paypalShowLogo' => array(
'type' => 'toggle',
'default' => $this->settings->get_paypal_show_logo(),
'label' => __( 'Show logo', 'woocommerce-paypal-payments' ),
),
),
),
array(
'id' => 'venmo',
'title' => __( 'Venmo', 'woocommerce-paypal-payments' ),
'description' => __(
'Offer Venmo at checkout to millions of active users.',
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-venmo',
'fields' => false,
),
array(
'id' => 'pay-later',
'title' => __( 'Pay Later', 'woocommerce-paypal-payments' ),
'description' => __(
'Get paid in full at checkout while giving your customers the flexibility to pay in installments over time with no late fees.',
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-paypal',
'fields' => false,
),
array(
'id' => CardButtonGateway::ID,
'title' => __( 'Credit and debit card payments', 'woocommerce-paypal-payments' ),
'description' => __( "Accept all major credit and debit cards - even if your customer doesn't have a PayPal account . ", 'woocommerce-paypal-payments' ),
'icon' => 'payment-method-cards',
),
);
return apply_filters( 'woocommerce_paypal_payments_gateway_group_paypal', $group );
}
/**
* Define card related payment methods.
*
* @return array
*/
public function group_card_methods() : array {
$group = array(
array(
'id' => CreditCardGateway::ID,
'title' => __( 'Advanced Credit and Debit Card Payments', 'woocommerce-paypal-payments' ),
'description' => __( "Present custom credit and debit card fields to your payers so they can pay with credit and debit cards using your site's branding.", 'woocommerce-paypal-payments' ),
'icon' => 'payment-method-advanced-cards',
'fields' => array(
'threeDSecure' => array(
'type' => 'radio',
'default' => $this->settings->get_three_d_secure(),
'label' => __( '3D Secure', 'woocommerce-paypal-payments' ),
'description' => __(
'Authenticate cardholders through their card issuers to reduce fraud and improve transaction security. Successful 3D Secure authentication can shift liability for fraudulent chargebacks to the card issuer.',
'woocommerce-paypal-payments'
),
'options' => array(
array(
'label' => __(
'No 3D Secure',
'woocommerce-paypal-payments'
),
'value' => 'no-3d-secure',
),
array(
'label' => __(
'Only when required',
'woocommerce-paypal-payments'
),
'value' => 'only-required-3d-secure',
),
array(
'label' => __(
'Always require 3D Secure',
'woocommerce-paypal-payments'
),
'value' => 'always-3d-secure',
),
),
),
),
),
array(
'id' => AxoGateway::ID,
'title' => __( 'Fastlane by PayPal', 'woocommerce-paypal-payments' ),
'description' => __( "Tap into the scale and trust of PayPal's customer network to recognize shoppers and make guest checkout more seamless than ever.", 'woocommerce-paypal-payments' ),
'icon' => 'payment-method-fastlane',
'fields' => array(
'fastlaneCardholderName' => array(
'type' => 'toggle',
'default' => $this->settings->get_fastlane_cardholder_name(),
'label' => __(
'Display cardholder name',
'woocommerce-paypal-payments'
),
),
'fastlaneDisplayWatermark' => array(
'type' => 'toggle',
'default' => $this->settings->get_fastlane_display_watermark(),
'label' => __(
'Display Fastlane Watermark',
'woocommerce-paypal-payments'
),
),
),
),
array(
'id' => ApplePayGateway::ID,
'title' => __( 'Apple Pay', 'woocommerce-paypal-payments' ),
'description' => __( 'Allow customers to pay via their Apple Pay digital wallet.', 'woocommerce-paypal-payments' ),
'icon' => 'payment-method-apple-pay',
),
array(
'id' => GooglePayGateway::ID,
'title' => __( 'Google Pay', 'woocommerce-paypal-payments' ),
'description' => __( 'Allow customers to pay via their Google Pay digital wallet.', 'woocommerce-paypal-payments' ),
'icon' => 'payment-method-google-pay',
),
);
return apply_filters( 'woocommerce_paypal_payments_gateway_group_cards', $group );
}
/**
* Builds an array of payment method definitions, which includes details
* of all APM gateways.
*
* @return array List of payment method definitions.
*/
public function group_apms() : array {
$group = array(
array(
'id' => BancontactGateway::ID,
'title' => __( 'Bancontact', 'woocommerce-paypal-payments' ),
'description' => __(
'Bancontact is the most widely used, accepted and trusted electronic payment method in Belgium. Bancontact makes it possible to pay directly through the online payment systems of all major Belgian banks.',
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-bancontact',
),
array(
'id' => BlikGateway::ID,
'title' => __( 'BLIK', 'woocommerce-paypal-payments' ),
'description' => __(
'A widely used mobile payment method in Poland, allowing Polish customers to pay directly via their banking apps. Transactions are processed in PLN.',
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-blik',
),
array(
'id' => EPSGateway::ID,
'title' => __( 'eps', 'woocommerce-paypal-payments' ),
'description' => __(
'An online payment method in Austria, enabling Austrian buyers to make secure payments directly through their bank accounts. Transactions are processed in EUR.',
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-eps',
),
array(
'id' => IDealGateway::ID,
'title' => __( 'iDEAL', 'woocommerce-paypal-payments' ),
'description' => __(
'iDEAL is a payment method in the Netherlands that allows buyers to select their issuing bank from a list of options.',
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-ideal',
),
array(
'id' => MyBankGateway::ID,
'title' => __( 'MyBank', 'woocommerce-paypal-payments' ),
'description' => __(
'A European online banking payment solution primarily used in Italy, enabling customers to make secure bank transfers during checkout. Transactions are processed in EUR.',
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-mybank',
),
array(
'id' => P24Gateway::ID,
'title' => __( 'Przelewy24', 'woocommerce-paypal-payments' ),
'description' => __(
'A popular online payment gateway in Poland, offering various payment options for Polish customers. Transactions can be processed in PLN or EUR.',
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-przelewy24',
),
array(
'id' => TrustlyGateway::ID,
'title' => __( 'Trustly', 'woocommerce-paypal-payments' ),
'description' => __(
'A European payment method that allows buyers to make payments directly from their bank accounts, suitable for customers across multiple European countries. Supported currencies include EUR, DKK, SEK, GBP, and NOK.',
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-trustly',
),
array(
'id' => MultibancoGateway::ID,
'title' => __( 'Multibanco', 'woocommerce-paypal-payments' ),
'description' => __(
'An online payment method in Portugal, enabling Portuguese buyers to make secure payments directly through their bank accounts. Transactions are processed in EUR.',
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-multibanco',
),
array(
'id' => PayUponInvoiceGateway::ID,
'title' => __( 'Pay upon Invoice', 'woocommerce-paypal-payments' ),
'description' => __(
'Pay upon Invoice is an invoice payment method in Germany. It is a local buy now, pay later payment method that allows the buyer to place an order, receive the goods, try them, verify they are in good order, and then pay the invoice within 30 days.',
'woocommerce-paypal-payments'
),
'icon' => '',
),
array(
'id' => OXXO::ID,
'title' => __( 'OXXO', 'woocommerce-paypal-payments' ),
'description' => __(
'OXXO is a Mexican chain of convenience stores. *Get PayPal account permission to use OXXO payment functionality by contacting us at (+52) 8009250304',
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-oxxo',
),
);
return apply_filters( 'woocommerce_paypal_payments_gateway_group_apm', $group );
}
}

View file

@ -67,11 +67,12 @@ class OnboardingProfile extends AbstractDataModel {
*/
protected function get_defaults() : array {
return array(
'completed' => false,
'step' => 0,
'is_casual_seller' => null,
'are_optional_payment_methods_enabled' => null,
'products' => array(),
'completed' => false,
'step' => 0,
'is_casual_seller' => null,
'accept_card_payments' => null,
'products' => array(),
'setup_done' => false,
);
}
@ -89,10 +90,10 @@ class OnboardingProfile extends AbstractDataModel {
/**
* Sets the 'completed' flag.
*
* @param bool $step Whether the onboarding process has been completed.
* @param bool $state Whether the onboarding process has been completed.
*/
public function set_completed( bool $step ) : void {
$this->data['completed'] = $step;
public function set_completed( bool $state ) : void {
$this->data['completed'] = $state;
}
/**
@ -132,12 +133,21 @@ class OnboardingProfile extends AbstractDataModel {
}
/**
* Sets the optional payment methods flag.
* Whether the merchant wants to accept card payments via the PayPal plugin.
*
* @param bool|null $are_optional_payment_methods_enabled Whether the PayPal optional payment methods are enabled.
* @return bool
*/
public function set_are_optional_payment_methods_enabled( ?bool $are_optional_payment_methods_enabled ) : void {
$this->data['are_optional_payment_methods_enabled'] = $are_optional_payment_methods_enabled;
public function get_accept_card_payments() : bool {
return (bool) $this->data['accept_card_payments'];
}
/**
* Sets the "accept card payments" flag.
*
* @param bool|null $accept_cards Whether to accept card payments via the PayPal plugin.
*/
public function set_accept_card_payments( ?bool $accept_cards ) : void {
$this->data['accept_card_payments'] = $accept_cards;
}
/**
@ -166,4 +176,22 @@ class OnboardingProfile extends AbstractDataModel {
public function get_flags() : array {
return $this->flags;
}
/**
* Gets the 'setup_done' flag.
*
* @return bool
*/
public function is_setup_done() : bool {
return (bool) $this->data['setup_done'];
}
/**
* Sets the 'setup_done' flag.
*
* @param bool $done Whether the onboarding process has been setup_done.
*/
public function set_setup_done( bool $done ) : void {
$this->data['setup_done'] = $done;
}
}

View file

@ -9,6 +9,8 @@ declare( strict_types = 1 );
namespace WooCommerce\PayPalCommerce\Settings\Data;
use WC_Payment_Gateway;
/**
* Class PaymentSettings
*/
@ -21,12 +23,19 @@ class PaymentSettings extends AbstractDataModel {
*/
protected const OPTION_KEY = 'woocommerce-ppcp-data-payment';
/**
* List of WC_Payment_Gateway instances that need to be saved.
*
* @var WC_Payment_Gateway[]
*/
private array $unsaved_gateways = array();
/**
* Get default values for the model.
*
* @return array
*/
protected function get_defaults(): array {
protected function get_defaults() : array {
return array(
'paypal_show_logo' => false,
'three_d_secure' => 'no-3d-secure',
@ -37,12 +46,115 @@ class PaymentSettings extends AbstractDataModel {
);
}
/**
* Saves the model data to WordPress options.
*/
public function save() : void {
parent::save();
foreach ( $this->unsaved_gateways as $gateway ) {
$gateway->settings['enabled'] = $gateway->enabled;
$gateway->settings['title'] = $gateway->title;
$gateway->settings['description'] = $gateway->description;
update_option( $gateway->get_option_key(), $gateway->settings );
}
$this->unsaved_gateways = array();
}
/**
* Enables or disables the defined payment method, if it exists.
*
* @param string $method_id ID of the payment method.
* @param bool $is_enabled Whether to enable the method.
*/
public function toggle_method_state( string $method_id, bool $is_enabled ) : void {
switch ( $method_id ) {
case 'venmo':
$this->set_venmo_enabled( $is_enabled );
break;
case 'pay-later':
$this->set_paylater_enabled( $is_enabled );
break;
default:
$gateway = $this->get_gateway( $method_id );
if ( $gateway ) {
$gateway->enabled = wc_bool_to_string( $is_enabled );
$this->modified_gateway( $gateway );
}
}
}
/**
* Checks, if the provided payment method is enabled.
*
* @param string $method_id ID of the payment method.
* @return bool True, if the method is enabled. False if it's disabled or not existing.
*/
public function is_method_enabled( string $method_id ) : bool {
switch ( $method_id ) {
case 'venmo':
return $this->get_venmo_enabled();
case 'pay-later':
return $this->get_paylater_enabled();
default:
$gateway = $this->get_gateway( $method_id );
if ( $gateway ) {
return wc_string_to_bool( $gateway->enabled );
}
return false;
}
}
/**
* Updates the payment method title.
*
* @param string $method_id ID of the payment method.
* @param string $title The new title.
* @return void
*/
public function set_method_title( string $method_id, string $title ) : void {
$gateway = $this->get_gateway( $method_id );
if ( $gateway ) {
$gateway->title = $title;
$this->modified_gateway( $gateway );
}
}
/**
* Updates the payment method description.
*
* @param string $method_id ID of the payment method.
* @param string $description The new description.
* @return void
*/
public function set_method_description( string $method_id, string $description ) : void {
$gateway = $this->get_gateway( $method_id );
if ( $gateway ) {
$gateway->description = $description;
$this->modified_gateway( $gateway );
}
}
/**
* Get PayPal show logo.
*
* @return bool
*/
public function get_paypal_show_logo(): bool {
public function get_paypal_show_logo() : bool {
return (bool) $this->data['paypal_show_logo'];
}
@ -51,7 +163,7 @@ class PaymentSettings extends AbstractDataModel {
*
* @return string
*/
public function get_three_d_secure(): string {
public function get_three_d_secure() : string {
return $this->data['three_d_secure'];
}
@ -60,7 +172,7 @@ class PaymentSettings extends AbstractDataModel {
*
* @return bool
*/
public function get_fastlane_cardholder_name(): bool {
public function get_fastlane_cardholder_name() : bool {
return (bool) $this->data['fastlane_cardholder_name'];
}
@ -69,7 +181,7 @@ class PaymentSettings extends AbstractDataModel {
*
* @return bool
*/
public function get_fastlane_display_watermark(): bool {
public function get_fastlane_display_watermark() : bool {
return (bool) $this->data['fastlane_display_watermark'];
}
@ -78,7 +190,7 @@ class PaymentSettings extends AbstractDataModel {
*
* @return bool
*/
public function get_venmo_enabled(): bool {
public function get_venmo_enabled() : bool {
return (bool) $this->data['venmo_enabled'];
}
@ -87,7 +199,7 @@ class PaymentSettings extends AbstractDataModel {
*
* @return bool
*/
public function get_paylater_enabled(): bool {
public function get_paylater_enabled() : bool {
return (bool) $this->data['paylater_enabled'];
}
@ -97,7 +209,7 @@ class PaymentSettings extends AbstractDataModel {
* @param bool $value The value.
* @return void
*/
public function set_paypal_show_logo( bool $value ): void {
public function set_paypal_show_logo( bool $value ) : void {
$this->data['paypal_show_logo'] = $value;
}
@ -107,7 +219,7 @@ class PaymentSettings extends AbstractDataModel {
* @param string $value The value.
* @return void
*/
public function set_three_d_secure( string $value ): void {
public function set_three_d_secure( string $value ) : void {
$this->data['three_d_secure'] = $value;
}
@ -117,7 +229,7 @@ class PaymentSettings extends AbstractDataModel {
* @param bool $value The value.
* @return void
*/
public function set_fastlane_cardholder_name( bool $value ): void {
public function set_fastlane_cardholder_name( bool $value ) : void {
$this->data['fastlane_cardholder_name'] = $value;
}
@ -127,7 +239,7 @@ class PaymentSettings extends AbstractDataModel {
* @param bool $value The value.
* @return void
*/
public function set_fastlane_display_watermark( bool $value ): void {
public function set_fastlane_display_watermark( bool $value ) : void {
$this->data['fastlane_display_watermark'] = $value;
}
@ -137,7 +249,7 @@ class PaymentSettings extends AbstractDataModel {
* @param bool $value The value.
* @return void
*/
public function set_venmo_enabled( bool $value ): void {
public function set_venmo_enabled( bool $value ) : void {
$this->data['venmo_enabled'] = $value;
}
@ -147,7 +259,40 @@ class PaymentSettings extends AbstractDataModel {
* @param bool $value The value.
* @return void
*/
public function set_paylater_enabled( bool $value ): void {
public function set_paylater_enabled( bool $value ) : void {
$this->data['paylater_enabled'] = $value;
}
/**
* Get the gateway object for the given method ID.
*
* @param string $method_id ID of the payment method.
* @return WC_Payment_Gateway|null
*/
private function get_gateway( string $method_id ) : ?WC_Payment_Gateway {
if ( isset( $this->unsaved_gateways[ $method_id ] ) ) {
return $this->unsaved_gateways[ $method_id ];
}
$gateways = WC()->payment_gateways()->payment_gateways();
if ( ! isset( $gateways[ $method_id ] ) ) {
return null;
}
$gateway = $gateways[ $method_id ];
$gateway->init_form_fields();
return $gateway;
}
/**
* Store the gateway object for later saving.
*
* @param WC_Payment_Gateway $gateway The gateway object.
* @return void
*/
private function modified_gateway( WC_Payment_Gateway $gateway ) : void {
$this->unsaved_gateways[ $gateway->id ] = $gateway;
}
}

View file

@ -41,23 +41,23 @@ class OnboardingRestEndpoint extends RestEndpoint {
* @var array
*/
private array $field_map = array(
'completed' => array(
'completed' => array(
'js_name' => 'completed',
'sanitize' => 'to_boolean',
),
'step' => array(
'step' => array(
'js_name' => 'step',
'sanitize' => 'to_number',
),
'is_casual_seller' => array(
'is_casual_seller' => array(
'js_name' => 'isCasualSeller',
'sanitize' => 'to_boolean',
),
'are_optional_payment_methods_enabled' => array(
'accept_card_payments' => array(
'js_name' => 'areOptionalPaymentMethodsEnabled',
'sanitize' => 'to_boolean',
),
'products' => array(
'products' => array(
'js_name' => 'products',
),
);

View file

@ -29,6 +29,7 @@ use WP_REST_Response;
use WP_REST_Request;
use WooCommerce\PayPalCommerce\Applepay\ApplePayGateway;
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\EPSGateway;
use WooCommerce\PayPalCommerce\Settings\Data\Definition\PaymentMethodsDefinition;
/**
* REST controller for the "Payment Methods" settings tab.
@ -51,6 +52,13 @@ class PaymentRestEndpoint extends RestEndpoint {
*/
protected PaymentSettings $settings;
/**
* The payment method details.
*
* @var PaymentMethodsDefinition
*/
protected PaymentMethodsDefinition $methods_definition;
/**
* Field mapping for request to profile transformation.
*
@ -78,10 +86,12 @@ class PaymentRestEndpoint extends RestEndpoint {
/**
* Constructor.
*
* @param PaymentSettings $settings The settings instance.
* @param PaymentSettings $settings The settings instance.
* @param PaymentMethodsDefinition $methods_definition Payment Method details.
*/
public function __construct( PaymentSettings $settings ) {
$this->settings = $settings;
public function __construct( PaymentSettings $settings, PaymentMethodsDefinition $methods_definition ) {
$this->settings = $settings;
$this->methods_definition = $methods_definition;
}
/**
@ -89,515 +99,8 @@ class PaymentRestEndpoint extends RestEndpoint {
*
* @return array[]
*/
protected function gateways():array {
return array(
// PayPal checkout.
PayPalGateway::ID => array(
'id' => PayPalGateway::ID,
'title' => __( 'PayPal', 'woocommerce-paypal-payments' ),
'description' => __(
'Our all-in-one checkout solution lets you offer PayPal, Venmo, Pay Later options, and more to help maximize conversion.',
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-paypal',
'itemTitle' => __( 'PayPal', 'woocommerce-paypal-payments' ),
'itemDescription' => __(
'Our all-in-one checkout solution lets you offer PayPal, Venmo, Pay Later options, and more to help maximize conversion.',
'woocommerce-paypal-payments'
),
'fields' => array(
'checkoutPageTitle' => array(
'type' => 'text',
'default' => $this->getPaymentTitle( PayPalGateway::ID ) ?? '',
'label' => __( 'Checkout page title', 'woocommerce-paypal-payments' ),
),
'checkoutPageDescription' => array(
'type' => 'text',
'default' => $this->getPaymentDescription( PayPalGateway::ID ) ?? '',
'label' => __( 'Checkout page description', 'woocommerce-paypal-payments' ),
),
'paypalShowLogo' => array(
'type' => 'toggle',
'default' => $this->settings->get_paypal_show_logo(),
'label' => __( 'Show logo', 'woocommerce-paypal-payments' ),
),
),
),
'venmo' => array(
'id' => 'venmo',
'itemTitle' => __( 'Venmo', 'woocommerce-paypal-payments' ),
'itemDescription' => __(
'Offer Venmo at checkout to millions of active users.',
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-venmo',
'enabled' => $this->settings->get_venmo_enabled(),
),
'pay-later' => array(
'id' => 'pay-later',
'itemTitle' => __( 'Pay Later', 'woocommerce-paypal-payments' ),
'itemDescription' => __(
'Get paid in full at checkout while giving your customers the flexibility to pay in installments over time with no late fees.',
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-paypal',
'enabled' => $this->settings->get_paylater_enabled(),
),
CardButtonGateway::ID => array(
'id' => CardButtonGateway::ID,
'title' => __(
'Credit and debit card payments',
'woocommerce-paypal-payments'
),
'description' => __(
"Accept all major credit and debit cards - even if your customer doesn't have a PayPal account.",
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-cards',
'itemTitle' => __(
'Credit and debit card payments',
'woocommerce-paypal-payments'
),
'itemDescription' => __(
"Accept all major credit and debit cards - even if your customer doesn't have a PayPal account.",
'woocommerce-paypal-payments'
),
'fields' => array(
'checkoutPageTitle' => array(
'type' => 'text',
'default' => $this->getPaymentTitle( CardButtonGateway::ID ) ?? '',
'label' => __( 'Checkout page title', 'woocommerce-paypal-payments' ),
),
'checkoutPageDescription' => array(
'type' => 'text',
'default' => $this->getPaymentDescription( CardButtonGateway::ID ) ?? '',
'label' => __( 'Checkout page description', 'woocommerce-paypal-payments' ),
),
),
),
// Online card Payments.
CreditCardGateway::ID => array(
'id' => CreditCardGateway::ID,
'title' => __(
'Advanced Credit and Debit Card Payments',
'woocommerce-paypal-payments'
),
'description' => __(
"Present custom credit and debit card fields to your payers so they can pay with credit and debit cards using your site's branding.",
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-advanced-cards',
'itemTitle' => __(
'Advanced Credit and Debit Card Payments',
'woocommerce-paypal-payments'
),
'itemDescription' => __(
"Present custom credit and debit card fields to your payers so they can pay with credit and debit cards using your site's branding.",
'woocommerce-paypal-payments'
),
'fields' => array(
'checkoutPageTitle' => array(
'type' => 'text',
'default' => $this->getPaymentTitle( CreditCardGateway::ID ) ?? '',
'label' => __( 'Checkout page title', 'woocommerce-paypal-payments' ),
),
'checkoutPageDescription' => array(
'type' => 'text',
'default' => $this->getPaymentDescription( CreditCardGateway::ID ) ?? '',
'label' => __( 'Checkout page description', 'woocommerce-paypal-payments' ),
),
'threeDSecure' => array(
'type' => 'radio',
'default' => $this->settings->get_three_d_secure(),
'label' => __( '3D Secure', 'woocommerce-paypal-payments' ),
'description' => __(
'Authenticate cardholders through their card issuers to reduce fraud and improve transaction security. Successful 3D Secure authentication can shift liability for fraudulent chargebacks to the card issuer.',
'woocommerce-paypal-payments'
),
'options' => array(
array(
'label' => __(
'No 3D Secure',
'woocommerce-paypal-payments'
),
'value' => 'no-3d-secure',
),
array(
'label' => __(
'Only when required',
'woocommerce-paypal-payments'
),
'value' => 'only-required-3d-secure',
),
array(
'label' => __(
'Always require 3D Secure',
'woocommerce-paypal-payments'
),
'value' => 'always-3d-secure',
),
),
),
),
),
AxoGateway::ID => array(
'id' => AxoGateway::ID,
'title' => __( 'Fastlane by PayPal', 'woocommerce-paypal-payments' ),
'description' => __(
"Tap into the scale and trust of PayPal's customer network to recognize shoppers and make guest checkout more seamless than ever.",
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-fastlane',
'itemTitle' => __( 'Fastlane by PayPal', 'woocommerce-paypal-payments' ),
'itemDescription' => __(
"Tap into the scale and trust of PayPal's customer network to recognize shoppers and make guest checkout more seamless than ever.",
'woocommerce-paypal-payments'
),
'fields' => array(
'checkoutPageTitle' => array(
'type' => 'text',
'default' => $this->getPaymentTitle( AxoGateway::ID ) ?? '',
'label' => __( 'Checkout page title', 'woocommerce-paypal-payments' ),
),
'checkoutPageDescription' => array(
'type' => 'text',
'default' => $this->getPaymentDescription( AxoGateway::ID ) ?? '',
'label' => __( 'Checkout page description', 'woocommerce-paypal-payments' ),
),
'fastlaneCardholderName' => array(
'type' => 'toggle',
'default' => $this->settings->get_fastlane_cardholder_name(),
'label' => __(
'Display cardholder name',
'woocommerce-paypal-payments'
),
),
'fastlaneDisplayWatermark' => array(
'type' => 'toggle',
'default' => $this->settings->get_fastlane_display_watermark(),
'label' => __(
'Display Fastlane Watermark',
'woocommerce-paypal-payments'
),
),
),
),
ApplePayGateway::ID => array(
'id' => ApplePayGateway::ID,
'title' => __( 'Apple Pay', 'woocommerce-paypal-payments' ),
'description' => __(
'Allow customers to pay via their Apple Pay digital wallet.',
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-apple-pay',
'itemTitle' => __( 'Apple Pay', 'woocommerce-paypal-payments' ),
'itemDescription' => __(
'Allow customers to pay via their Apple Pay digital wallet.',
'woocommerce-paypal-payments'
),
'fields' => array(
'checkoutPageTitle' => array(
'type' => 'text',
'default' => $this->getPaymentTitle( ApplePayGateway::ID ) ?? '',
'label' => __( 'Checkout page title', 'woocommerce-paypal-payments' ),
),
'checkoutPageDescription' => array(
'type' => 'text',
'default' => $this->getPaymentDescription( ApplePayGateway::ID ) ?? '',
'label' => __( 'Checkout page description', 'woocommerce-paypal-payments' ),
),
),
),
GooglePayGateway::ID => array(
'id' => GooglePayGateway::ID,
'title' => __( 'Google Pay', 'woocommerce-paypal-payments' ),
'description' => __(
'Allow customers to pay via their Google Pay digital wallet.',
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-google-pay',
'itemTitle' => __( 'Google Pay', 'woocommerce-paypal-payments' ),
'itemDescription' => __(
'Allow customers to pay via their Google Pay digital wallet.',
'woocommerce-paypal-payments'
),
'fields' => array(
'checkoutPageTitle' => array(
'type' => 'text',
'default' => $this->getPaymentTitle( GooglePayGateway::ID ) ?? '',
'label' => __( 'Checkout page title', 'woocommerce-paypal-payments' ),
),
'checkoutPageDescription' => array(
'type' => 'text',
'default' => $this->getPaymentDescription( GooglePayGateway::ID ) ?? '',
'label' => __( 'Checkout page description', 'woocommerce-paypal-payments' ),
),
),
),
// Alternative payment methods.
BancontactGateway::ID => array(
'id' => BancontactGateway::ID,
'title' => __( 'Bancontact', 'woocommerce-paypal-payments' ),
'description' => __(
'Bancontact is the most widely used, accepted and trusted electronic payment method in Belgium. Bancontact makes it possible to pay directly through the online payment systems of all major Belgian banks.',
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-bancontact',
'itemTitle' => __( 'Bancontact', 'woocommerce-paypal-payments' ),
'itemDescription' => __(
'Bancontact is the most widely used, accepted and trusted electronic payment method in Belgium. Bancontact makes it possible to pay directly through the online payment systems of all major Belgian banks.',
'woocommerce-paypal-payments'
),
'fields' => array(
'checkoutPageTitle' => array(
'type' => 'text',
'default' => $this->getPaymentTitle( BancontactGateway::ID ) ?? '',
'label' => __( 'Checkout page title', 'woocommerce-paypal-payments' ),
),
'checkoutPageDescription' => array(
'type' => 'text',
'default' => $this->getPaymentDescription( BancontactGateway::ID ) ?? '',
'label' => __( 'Checkout page description', 'woocommerce-paypal-payments' ),
),
),
),
BlikGateway::ID => array(
'id' => BlikGateway::ID,
'title' => __( 'BLIK', 'woocommerce-paypal-payments' ),
'description' => __(
'A widely used mobile payment method in Poland, allowing Polish customers to pay directly via their banking apps. Transactions are processed in PLN.',
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-blik',
'itemTitle' => __( 'BLIK', 'woocommerce-paypal-payments' ),
'itemDescription' => __(
'A widely used mobile payment method in Poland, allowing Polish customers to pay directly via their banking apps. Transactions are processed in PLN.',
'woocommerce-paypal-payments'
),
'fields' => array(
'checkoutPageTitle' => array(
'type' => 'text',
'default' => $this->getPaymentTitle( BlikGateway::ID ) ?? '',
'label' => __( 'Checkout page title', 'woocommerce-paypal-payments' ),
),
'checkoutPageDescription' => array(
'type' => 'text',
'default' => $this->getPaymentDescription( BlikGateway::ID ) ?? '',
'label' => __( 'Checkout page description', 'woocommerce-paypal-payments' ),
),
),
),
EPSGateway::ID => array(
'id' => EPSGateway::ID,
'title' => __( 'eps', 'woocommerce-paypal-payments' ),
'description' => __(
'An online payment method in Austria, enabling Austrian buyers to make secure payments directly through their bank accounts. Transactions are processed in EUR.',
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-eps',
'itemTitle' => __( 'eps', 'woocommerce-paypal-payments' ),
'itemDescription' => __(
'An online payment method in Austria, enabling Austrian buyers to make secure payments directly through their bank accounts. Transactions are processed in EUR.',
'woocommerce-paypal-payments'
),
'fields' => array(
'checkoutPageTitle' => array(
'type' => 'text',
'default' => $this->getPaymentTitle( EPSGateway::ID ) ?? '',
'label' => __( 'Checkout page title', 'woocommerce-paypal-payments' ),
),
'checkoutPageDescription' => array(
'type' => 'text',
'default' => $this->getPaymentDescription( EPSGateway::ID ) ?? '',
'label' => __( 'Checkout page description', 'woocommerce-paypal-payments' ),
),
),
),
IDealGateway::ID => array(
'id' => IDealGateway::ID,
'title' => __( 'iDEAL', 'woocommerce-paypal-payments' ),
'description' => __(
'iDEAL is a payment method in the Netherlands that allows buyers to select their issuing bank from a list of options.',
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-ideal',
'itemTitle' => __( 'iDEAL', 'woocommerce-paypal-payments' ),
'itemDescription' => __(
'iDEAL is a payment method in the Netherlands that allows buyers to select their issuing bank from a list of options.',
'woocommerce-paypal-payments'
),
'fields' => array(
'checkoutPageTitle' => array(
'type' => 'text',
'default' => $this->getPaymentTitle( IDealGateway::ID ) ?? '',
'label' => __( 'Checkout page title', 'woocommerce-paypal-payments' ),
),
'checkoutPageDescription' => array(
'type' => 'text',
'default' => $this->getPaymentDescription( IDealGateway::ID ) ?? '',
'label' => __( 'Checkout page description', 'woocommerce-paypal-payments' ),
),
),
),
MyBankGateway::ID => array(
'id' => MyBankGateway::ID,
'title' => __( 'MyBank', 'woocommerce-paypal-payments' ),
'description' => __(
'A European online banking payment solution primarily used in Italy, enabling customers to make secure bank transfers during checkout. Transactions are processed in EUR.',
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-mybank',
'itemTitle' => __( 'MyBank', 'woocommerce-paypal-payments' ),
'itemDescription' => __(
'A European online banking payment solution primarily used in Italy, enabling customers to make secure bank transfers during checkout. Transactions are processed in EUR.',
'woocommerce-paypal-payments'
),
'fields' => array(
'checkoutPageTitle' => array(
'type' => 'text',
'default' => $this->getPaymentTitle( MyBankGateway::ID ) ?? '',
'label' => __( 'Checkout page title', 'woocommerce-paypal-payments' ),
),
'checkoutPageDescription' => array(
'type' => 'text',
'default' => $this->getPaymentDescription( MyBankGateway::ID ) ?? '',
'label' => __( 'Checkout page description', 'woocommerce-paypal-payments' ),
),
),
),
P24Gateway::ID => array(
'id' => P24Gateway::ID,
'title' => __( 'Przelewy24', 'woocommerce-paypal-payments' ),
'description' => __(
'A popular online payment gateway in Poland, offering various payment options for Polish customers. Transactions can be processed in PLN or EUR.',
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-przelewy24',
'itemTitle' => __( 'Przelewy24', 'woocommerce-paypal-payments' ),
'itemDescription' => __(
'A popular online payment gateway in Poland, offering various payment options for Polish customers. Transactions can be processed in PLN or EUR.',
'woocommerce-paypal-payments'
),
'fields' => array(
'checkoutPageTitle' => array(
'type' => 'text',
'default' => $this->getPaymentTitle( P24Gateway::ID ) ?? '',
'label' => __( 'Checkout page title', 'woocommerce-paypal-payments' ),
),
'checkoutPageDescription' => array(
'type' => 'text',
'default' => $this->getPaymentDescription( P24Gateway::ID ) ?? '',
'label' => __( 'Checkout page description', 'woocommerce-paypal-payments' ),
),
),
),
TrustlyGateway::ID => array(
'id' => TrustlyGateway::ID,
'title' => __( 'Trustly', 'woocommerce-paypal-payments' ),
'description' => __(
'A European payment method that allows buyers to make payments directly from their bank accounts, suitable for customers across multiple European countries. Supported currencies include EUR, DKK, SEK, GBP, and NOK.',
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-trustly',
'itemTitle' => __( 'Trustly', 'woocommerce-paypal-payments' ),
'itemDescription' => __(
'A European payment method that allows buyers to make payments directly from their bank accounts, suitable for customers across multiple European countries. Supported currencies include EUR, DKK, SEK, GBP, and NOK.',
'woocommerce-paypal-payments'
),
'fields' => array(
'checkoutPageTitle' => array(
'type' => 'text',
'default' => $this->getPaymentTitle( TrustlyGateway::ID ) ?? '',
'label' => __( 'Checkout page title', 'woocommerce-paypal-payments' ),
),
'checkoutPageDescription' => array(
'type' => 'text',
'default' => $this->getPaymentDescription( TrustlyGateway::ID ) ?? '',
'label' => __( 'Checkout page description', 'woocommerce-paypal-payments' ),
),
),
),
MultibancoGateway::ID => array(
'id' => MultibancoGateway::ID,
'title' => __( 'Multibanco', 'woocommerce-paypal-payments' ),
'description' => __(
'An online payment method in Portugal, enabling Portuguese buyers to make secure payments directly through their bank accounts. Transactions are processed in EUR.',
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-multibanco',
'itemTitle' => __( 'Multibanco', 'woocommerce-paypal-payments' ),
'itemDescription' => __(
'An online payment method in Portugal, enabling Portuguese buyers to make secure payments directly through their bank accounts. Transactions are processed in EUR.',
'woocommerce-paypal-payments'
),
'fields' => array(
'checkoutPageTitle' => array(
'type' => 'text',
'default' => $this->getPaymentTitle( MultibancoGateway::ID ) ?? '',
'label' => __( 'Checkout page title', 'woocommerce-paypal-payments' ),
),
'checkoutPageDescription' => array(
'type' => 'text',
'default' => $this->getPaymentDescription( MultibancoGateway::ID ) ?? '',
'label' => __( 'Checkout page description', 'woocommerce-paypal-payments' ),
),
),
),
PayUponInvoiceGateway::ID => array(
'id' => PayUponInvoiceGateway::ID,
'title' => __( 'Pay upon Invoice', 'woocommerce-paypal-payments' ),
'description' => __(
'Pay upon Invoice is an invoice payment method in Germany. It is a local buy now, pay later payment method that allows the buyer to place an order, receive the goods, try them, verify they are in good order, and then pay the invoice within 30 days.',
'woocommerce-paypal-payments'
),
'icon' => '',
'itemTitle' => __( 'Pay upon Invoice', 'woocommerce-paypal-payments' ),
'itemDescription' => __(
'Pay upon Invoice is an invoice payment method in Germany. It is a local buy now, pay later payment method that allows the buyer to place an order, receive the goods, try them, verify they are in good order, and then pay the invoice within 30 days.',
'woocommerce-paypal-payments'
),
'fields' => array(
'checkoutPageTitle' => array(
'type' => 'text',
'default' => $this->getPaymentTitle( PayUponInvoiceGateway::ID ) ?? '',
'label' => __( 'Checkout page title', 'woocommerce-paypal-payments' ),
),
'checkoutPageDescription' => array(
'type' => 'text',
'default' => $this->getPaymentDescription( PayUponInvoiceGateway::ID ) ?? '',
'label' => __( 'Checkout page description', 'woocommerce-paypal-payments' ),
),
),
),
OXXO::ID => array(
'id' => OXXO::ID,
'title' => __( 'OXXO', 'woocommerce-paypal-payments' ),
'description' => __(
'OXXO is a Mexican chain of convenience stores. *Get PayPal account permission to use OXXO payment functionality by contacting us at (+52) 8009250304',
'woocommerce-paypal-payments'
),
'icon' => 'payment-method-oxxo',
'itemTitle' => __( 'OXXO', 'woocommerce-paypal-payments' ),
'itemDescription' => __(
'OXXO is a Mexican chain of convenience stores. *Get PayPal account permission to use OXXO payment functionality by contacting us at (+52) 8009250304',
'woocommerce-paypal-payments'
),
'fields' => array(
'checkoutPageTitle' => array(
'type' => 'text',
'default' => $this->getPaymentTitle( OXXO::ID ) ?? '',
'label' => __( 'Checkout page title', 'woocommerce-paypal-payments' ),
),
'checkoutPageDescription' => array(
'type' => 'text',
'default' => $this->getPaymentDescription( OXXO::ID ) ?? '',
'label' => __( 'Checkout page description', 'woocommerce-paypal-payments' ),
),
),
),
);
protected function gateways() : array {
return $this->methods_definition->get_definitions();
}
/**
@ -644,44 +147,22 @@ class PaymentRestEndpoint extends RestEndpoint {
* @return WP_REST_Response The current payment methods details.
*/
public function get_details() : WP_REST_Response {
$all_gateways = WC()->payment_gateways->payment_gateways();
$gateway_settings = array();
$all_methods = $this->gateways();
foreach ( $this->gateways() as $key => $value ) {
// Here we handle the payment methods that are listed on the page but not registered as WooCommerce Payment gateways.
if ( ! isset( $all_gateways[ $key ] ) ) {
$gateway_settings[ $key ] = array(
'id' => $this->gateways()[ $key ]['id'] ?? '',
'title' => $this->gateways()[ $key ]['title'] ?? '',
'description' => $this->gateways()[ $key ]['description'] ?? '',
'enabled' => $this->gateways()[ $key ]['enabled'] ?? false,
'icon' => $this->gateways()[ $key ]['icon'] ?? '',
'itemTitle' => $this->gateways()[ $key ]['itemTitle'] ?? '',
'itemDescription' => $this->gateways()[ $key ]['itemDescription'] ?? '',
);
if ( isset( $this->gateways()[ $key ]['fields'] ) ) {
$gateway_settings[ $key ]['fields'] = $this->gateways()[ $key ]['fields'];
}
continue;
}
$gateway = $all_gateways[ $key ];
foreach ( $all_methods as $key => $method ) {
$gateway_settings[ $key ] = array(
'enabled' => 'yes' === $gateway->enabled,
'title' => str_replace( '&amp;', '&', $gateway->get_title() ),
'description' => $gateway->get_description(),
'id' => $this->gateways()[ $key ]['id'] ?? $key,
'icon' => $this->gateways()[ $key ]['icon'] ?? '',
'itemTitle' => $this->gateways()[ $key ]['itemTitle'] ?? '',
'itemDescription' => $this->gateways()[ $key ]['itemDescription'] ?? '',
'id' => $method['id'],
'title' => $method['title'],
'description' => $method['description'],
'enabled' => $method['enabled'],
'icon' => $method['icon'],
'itemTitle' => $method['itemTitle'],
'itemDescription' => $method['itemDescription'],
);
if ( isset( $this->gateways()[ $key ]['fields'] ) ) {
$gateway_settings[ $key ]['fields'] = $this->gateways()[ $key ]['fields'];
if ( isset( $method['fields'] ) ) {
$gateway_settings[ $key ]['fields'] = $method['fields'];
}
}
@ -701,52 +182,26 @@ class PaymentRestEndpoint extends RestEndpoint {
* @return WP_REST_Response The updated payment methods details.
*/
public function update_details( WP_REST_Request $request ) : WP_REST_Response {
$all_gateways = WC()->payment_gateways->payment_gateways();
$request_data = $request->get_params();
$all_methods = $this->gateways();
foreach ( $this->gateways() as $key => $value ) {
// Here we handle the payment methods that are listed on the page but not registered as WooCommerce Payment gateways.
if ( ! isset( $all_gateways[ $key ] ) && isset( $request_data[ $key ] ) ) {
switch ( $key ) {
case 'venmo':
$this->settings->set_venmo_enabled( $request_data[ $key ]['enabled'] ?? false );
break;
case 'pay-later':
$this->settings->set_paylater_enabled( $request_data[ $key ]['enabled'] ?? false );
break;
}
continue;
}
// Check if the REST body contains details for this gateway.
if ( ! isset( $request_data[ $key ] ) || ! isset( $all_gateways[ $key ] ) ) {
continue;
}
$gateway = $all_gateways[ $key ];
foreach ( $all_methods as $key => $value ) {
$new_data = $request_data[ $key ];
$gateway->init_form_fields();
$settings = $gateway->settings;
if ( ! $new_data ) {
continue;
}
if ( isset( $new_data['enabled'] ) ) {
$settings['enabled'] = wc_bool_to_string( $new_data['enabled'] );
$gateway->enabled = $settings['enabled'];
$this->settings->toggle_method_state( $key, $new_data['enabled'] );
}
if ( isset( $new_data['title'] ) ) {
$settings['title'] = sanitize_text_field( $new_data['title'] );
$gateway->title = $settings['title'];
$this->settings->set_method_title( $key, sanitize_text_field( $new_data['title'] ) );
}
if ( isset( $new_data['description'] ) ) {
$settings['description'] = wp_kses_post( $new_data['description'] );
$gateway->description = $settings['description'];
$this->settings->set_method_description( $key, wp_kses_post( $new_data['description'] ) );
}
$gateway->settings = $settings;
update_option( $gateway->get_option_key(), $settings );
}
$wp_data = $this->sanitize_for_wordpress(
@ -759,32 +214,4 @@ class PaymentRestEndpoint extends RestEndpoint {
return $this->get_details();
}
/**
* Returns title for the given gateway.
*
* @param string $id Gateway ID.
* @return string
*/
private function getPaymentTitle( string $id ): string {
if ( ! isset( WC()->payment_gateways()->payment_gateways()[ $id ] ) ) {
return '';
}
return WC()->payment_gateways()->payment_gateways()[ $id ]->get_title() ?? '';
}
/**
* Returns title for the given gateway.
*
* @param string $id Gateway ID.
* @return string
*/
private function getPaymentDescription( string $id ): string {
if ( ! isset( WC()->payment_gateways()->payment_gateways()[ $id ] ) ) {
return '';
}
return WC()->payment_gateways()->payment_gateways()[ $id ]->get_description() ?? '';
}
}

View file

@ -0,0 +1,56 @@
<?php
/**
* Defines valid "product" options that can be chosen during onboarding.
*
* @package WooCommerce\PayPalCommerce\Settings\Enum
*/
declare( strict_types = 1 );
namespace WooCommerce\PayPalCommerce\Settings\Enum;
/**
* Enum for the "product" list choice.
*/
class ProductChoicesEnum {
/**
* Virtual products that don't require shipping
* Sample: downloads, courses, events
*/
public const VIRTUAL = 'virtual';
/**
* Physical products that require shipping
* Sample: books, clothing, electronics
*/
public const PHYSICAL = 'physical';
/**
* Subscription products that require automatic payments
* Sample: memberships, subscriptions
*/
public const SUBSCRIPTIONS = 'subscriptions';
/**
* Get all valid seller types.
*
* @return array List of all valid seller_types.
*/
public static function get_valid_values() : array {
return array(
self::VIRTUAL,
self::PHYSICAL,
self::SUBSCRIPTIONS,
);
}
/**
* Check if a given type is valid.
*
* @param string $type The value to validate.
* @return bool True, if the value is a valid seller_type.
*/
public static function is_valid( string $type ) : bool {
return in_array( $type, self::get_valid_values(), true );
}
}

View file

@ -10,6 +10,19 @@ declare( strict_types = 1 );
namespace WooCommerce\PayPalCommerce\Settings\Service;
use WooCommerce\PayPalCommerce\Settings\Data\AbstractDataModel;
use WooCommerce\PayPalCommerce\Settings\Data\OnboardingProfile;
use WooCommerce\PayPalCommerce\Settings\DTO\ConfigurationFlagsDTO;
use WooCommerce\PayPalCommerce\Settings\DTO\LocationStylingDTO;
use WooCommerce\PayPalCommerce\Googlepay\GooglePayGateway;
use WooCommerce\PayPalCommerce\Applepay\ApplePayGateway;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
use WooCommerce\PayPalCommerce\Settings\Data\StylingSettings;
use WooCommerce\PayPalCommerce\Settings\Data\GeneralSettings;
use WooCommerce\PayPalCommerce\Settings\Data\SettingsModel;
use WooCommerce\PayPalCommerce\Settings\Data\PaymentSettings;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway;
use WooCommerce\PayPalCommerce\Settings\Data\Definition\PaymentMethodsDefinition;
/**
* Class SettingsDataManager
@ -19,25 +32,104 @@ use WooCommerce\PayPalCommerce\Settings\Data\AbstractDataModel;
*/
class SettingsDataManager {
/**
* The payment methods definition, provides a list of all available payment methods.
*
* @var PaymentMethodsDefinition
*/
private PaymentMethodsDefinition $methods_definition;
/**
* The onboarding profile data model.
*
* @var OnboardingProfile
*/
private OnboardingProfile $onboarding_profile;
/**
* Payment settings model.
*
* @var SettingsModel
*/
private SettingsModel $payment_settings;
/**
* Data model that handles button styling on the front end.
*
* @var StylingSettings
*/
private StylingSettings $styling_settings;
/**
* Model for handling payment methods.
*
* @var PaymentSettings
*/
private PaymentSettings $payment_methods;
/**
* Data accessors for pay later messaging settings.
*
* @var array
* @todo This should be a proper class!
*/
private array $paylater_messaging;
/**
* Stores a list of all AbstractDataModel instances that are managed by
* this service.
*
* @var AbstractDataModel[]
*/
private array $models = array();
private array $models_to_reset = array();
/**
* Constructor.
*
* @param array $data_models List of AbstractDataModel instances.
* @param PaymentMethodsDefinition $methods_definition Access list of all payment methods.
* @param OnboardingProfile $onboarding_profile The onboarding profile model.
* @param GeneralSettings $general_settings The general settings model.
* @param SettingsModel $payment_settings The settings model.
* @param StylingSettings $styling_settings The styling settings model.
* @param PaymentSettings $payment_methods The payment settings model.
* @param array $paylater_messaging Paylater Messaging accessor.
* @param array ...$data_models List of additional data models to reset.
*/
public function __construct( array $data_models ) {
public function __construct(
PaymentMethodsDefinition $methods_definition,
OnboardingProfile $onboarding_profile,
GeneralSettings $general_settings,
SettingsModel $payment_settings,
StylingSettings $styling_settings,
PaymentSettings $payment_methods,
array $paylater_messaging, // TODO should be migrated to an AbstractDataModel.
...$data_models
) {
foreach ( $data_models as $data_model ) {
/**
* An instance extracted from the spread operator. We only process
* AbstractDataModel instances.
*
* @var mixed|AbstractDataModel $data_model
*/
if ( $data_model instanceof AbstractDataModel ) {
$this->models[] = $data_model;
$this->models_to_reset[] = $data_model;
}
}
$this->models_to_reset[] = $onboarding_profile;
$this->models_to_reset[] = $general_settings;
$this->models_to_reset[] = $payment_settings;
$this->models_to_reset[] = $styling_settings;
$this->models_to_reset[] = $payment_methods;
$this->methods_definition = $methods_definition;
$this->onboarding_profile = $onboarding_profile;
$this->payment_settings = $payment_settings;
$this->styling_settings = $styling_settings;
$this->payment_methods = $payment_methods;
$this->paylater_messaging = $paylater_messaging;
}
/**
@ -52,11 +144,186 @@ class SettingsDataManager {
*/
do_action( 'woocommerce_paypal_payments_reset_settings' );
foreach ( $this->models as $model ) {
foreach ( $this->models_to_reset as $model ) {
$model->purge();
}
// Clear any caches.
wp_cache_flush();
}
/**
* Applies a default configuration to the plugin for a new merchant.
*
* This method checks the onboarding "setup_done" flag to determine if
* the defaults should be applied. At the end of this method, the
* "setup_done" flag is set, so future calls to the method have no effect.
*
* @param ConfigurationFlagsDTO $flags The configuration flags.
* @return void
*/
public function set_defaults_for_new_merchant( ConfigurationFlagsDTO $flags ) : void {
if ( $this->onboarding_profile->is_setup_done() ) {
return;
}
$this->apply_configuration( $flags );
$this->onboarding_profile->set_setup_done( true );
$this->onboarding_profile->save();
}
/**
* Applies a default configuration to the plugin, without any condition.
*
* @param ConfigurationFlagsDTO $flags The configuration flags.
* @return void
*/
protected function apply_configuration( ConfigurationFlagsDTO $flags ) : void {
// Apply defaults for the "Payment Methods" tab.
$this->toggle_payment_gateways( $flags );
// Apply defaults for the "Settings" tab.
$this->apply_payment_settings( $flags );
// Assign defaults for the "Styling" tab.
$this->apply_location_styles( $flags );
// Assign defaults for the "Pay Later Messaging" tab.
$this->apply_pay_later_messaging( $flags );
}
/**
* Enables or disables payment gateways depending on the provided
* configuration flags.
*
* @param ConfigurationFlagsDTO $flags Shop configuration flags.
* @return void
*/
protected function toggle_payment_gateways( ConfigurationFlagsDTO $flags ) : void {
// First, disable all payment methods.
$methods_paypal = $this->methods_definition->group_paypal_methods();
$methods_cards = $this->methods_definition->group_card_methods();
$methods_apm = $this->methods_definition->group_apms();
$all_methods = array_merge( $methods_paypal, $methods_cards, $methods_apm );
foreach ( $all_methods as $method ) {
$this->payment_methods->toggle_method_state( $method['id'], false );
}
// Always enable Venmo and Pay Later.
$this->payment_methods->toggle_method_state( 'venmo', true );
$this->payment_methods->toggle_method_state( 'pay-later', true );
if ( $flags->is_business_seller && $flags->use_card_payments ) {
// Use BCDC for casual sellers.
$this->payment_methods->toggle_method_state( CardButtonGateway::ID, true );
}
if ( $flags->is_business_seller ) {
if ( $flags->use_card_payments ) {
// Enable ACDC for business sellers.
$this->payment_methods->toggle_method_state( CreditCardGateway::ID, true );
}
$this->payment_methods->toggle_method_state( ApplePayGateway::ID, true );
$this->payment_methods->toggle_method_state( GooglePayGateway::ID, true );
// Enable all APM methods.
foreach ( $methods_apm as $method ) {
$this->payment_methods->toggle_method_state( $method['id'], true );
}
}
$this->payment_methods->save();
}
/**
* Applies the default payment settings that are relevant for the provided
* configuration flags.
*
* @param ConfigurationFlagsDTO $flags Shop configuration flags.
* @return void
*/
protected function apply_payment_settings( ConfigurationFlagsDTO $flags ) : void {
// Enable Pay-Now experience for all merchants.
$this->payment_settings->set_enable_pay_now( true );
if ( $flags->is_business_seller && $flags->use_subscriptions ) {
$this->payment_settings->set_save_paypal_and_venmo( true );
if ( $flags->use_card_payments ) {
$this->payment_settings->set_save_card_details( true );
} else {
$this->payment_settings->set_save_card_details( false );
}
}
$this->payment_settings->save();
}
/**
* Applies the default styling details for the shop.
*
* @param ConfigurationFlagsDTO $flags Shop configuration flags.
* @return void
*/
protected function apply_location_styles( ConfigurationFlagsDTO $flags ) : void {
$methods_full = array(
PayPalGateway::ID,
'venmo',
'pay-later',
ApplePayGateway::ID,
GooglePayGateway::ID,
);
$methods_own = array(
PayPalGateway::ID,
'venmo',
'pay-later',
);
/**
* Initialize the styling options using the defaults.
*
* - Cart: Enabled, display PayPal, Venmo, Pay Later, Google Pay, Apple Pay.
* - Classic Checkout: Display PayPal, Venmo, Pay Later, Google Pay, Apple Pay.
* - Express Checkout: Display PayPal, Venmo, Pay Later, Google Pay, Apple Pay.
* - Mini Cart: Display PayPal, Venmo, Pay Later, Google Pay, Apple Pay.
* - Product Page: Display PayPal, Venmo, Pay Later.
*/
$location_styles = array(
'cart' => new LocationStylingDTO( 'cart', true, $methods_full ),
'classic_checkout' => new LocationStylingDTO( 'classic_checkout', true, $methods_full ),
'express_checkout' => new LocationStylingDTO( 'express_checkout', true, $methods_full ),
'mini_cart' => new LocationStylingDTO( 'mini_cart', true, $methods_full ),
'product' => new LocationStylingDTO( 'product', true, $methods_own ),
);
// Apply the settings and persist them to the DB. All merchants use the same options.
$this->styling_settings->from_array( $location_styles );
$this->styling_settings->save();
}
/**
* Applies the default pay later messaging details for the shop.
*
* @param ConfigurationFlagsDTO $flags Shop configuration flags.
* @return void
*/
protected function apply_pay_later_messaging( ConfigurationFlagsDTO $flags ) : void {
$config = $this->paylater_messaging['read'];
$config['cart']['status'] = 'enabled';
$config['checkout']['status'] = 'enabled';
$config['product']['status'] = 'enabled';
$config['shop']['status'] = 'disabled';
$config['home']['status'] = 'disabled';
foreach ( $config['custom_placement'] as $key => $placement ) {
$config['custom_placement'][ $key ]['status'] = 'disabled';
}
$this->paylater_messaging['save']->save_config( $config );
}
}

View file

@ -36,6 +36,10 @@ use WooCommerce\PayPalCommerce\WcGateway\Gateway\OXXO\OXXO;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayUponInvoice\PayUponInvoiceGateway;
use WooCommerce\PayPalCommerce\WcGateway\Helper\DCCProductStatus;
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
use WooCommerce\PayPalCommerce\Settings\Service\SettingsDataManager;
use WooCommerce\PayPalCommerce\Settings\DTO\ConfigurationFlagsDTO;
use WooCommerce\PayPalCommerce\Settings\Enum\ProductChoicesEnum;
use WooCommerce\PayPalCommerce\Settings\Data\GeneralSettings;
/**
* Class SettingsModule
@ -122,7 +126,7 @@ class SettingsModule implements ServiceModule, ExecutableModule {
add_action(
'woocommerce_paypal_payments_gateway_migrate_on_update',
static fn () => ! get_option( SwitchSettingsUiEndpoint::OPTION_NAME_SHOULD_USE_OLD_UI )
static fn() => ! get_option( SwitchSettingsUiEndpoint::OPTION_NAME_SHOULD_USE_OLD_UI )
&& update_option( SwitchSettingsUiEndpoint::OPTION_NAME_SHOULD_USE_OLD_UI, 'yes' )
);
@ -288,12 +292,29 @@ class SettingsModule implements ServiceModule, ExecutableModule {
$onboarding_profile->set_completed( true );
$onboarding_profile->save();
// Try to apply a default configuration for the current store.
$data_manager = $container->get( 'settings.service.data-manager' );
assert( $data_manager instanceof SettingsDataManager );
$general_settings = $container->get( 'settings.data.general' );
assert( $general_settings instanceof GeneralSettings );
$flags = new ConfigurationFlagsDTO();
// TODO: Get the merchant country from PayPal here!
$flags->country_code = 'US';
$flags->is_business_seller = $general_settings->is_business_seller();
$flags->use_card_payments = $onboarding_profile->get_accept_card_payments();
$flags->use_subscriptions = in_array( ProductChoicesEnum::SUBSCRIPTIONS, $onboarding_profile->get_products(), true );
$data_manager->set_defaults_for_new_merchant( $flags );
}
);
add_filter(
'woocommerce_paypal_payments_payment_methods',
function( array $payment_methods ) use ( $container ) : array {
function ( array $payment_methods ) use ( $container ) : array {
$all_payment_methods = $payment_methods;
$dcc_product_status = $container->get( 'wcgateway.helper.dcc-product-status' );
@ -362,7 +383,7 @@ class SettingsModule implements ServiceModule, ExecutableModule {
*
* @psalm-suppress MissingClosureParamType
*/
static function ( $methods ) use ( $container ): array {
static function ( $methods ) use ( $container ) : array {
if ( ! is_array( $methods ) ) {
return $methods;
}
@ -390,7 +411,7 @@ class SettingsModule implements ServiceModule, ExecutableModule {
add_filter(
'woocommerce_paypal_payments_gateway_title',
function( string $title, WC_Payment_Gateway $gateway ) {
function ( string $title, WC_Payment_Gateway $gateway ) {
return $gateway->get_option( 'title', $title );
},
10,
@ -398,7 +419,7 @@ class SettingsModule implements ServiceModule, ExecutableModule {
);
add_filter(
'woocommerce_paypal_payments_gateway_description',
function( string $description, WC_Payment_Gateway $gateway ) {
function ( string $description, WC_Payment_Gateway $gateway ) {
return $gateway->get_option( 'description', $description );
},
10,
@ -409,7 +430,7 @@ class SettingsModule implements ServiceModule, ExecutableModule {
add_filter(
'woocommerce_paypal_payments_credit_card_gateway_form_fields',
function( array $form_fields ) {
function ( array $form_fields ) {
$form_fields['enabled'] = array(
'title' => __( 'Enable/Disable', 'woocommerce-paypal-payments' ),
'type' => 'checkbox',
@ -426,7 +447,7 @@ class SettingsModule implements ServiceModule, ExecutableModule {
add_filter(
'woocommerce_paypal_payments_credit_card_gateway_title',
function( string $title, WC_Payment_Gateway $gateway ) {
function ( string $title, WC_Payment_Gateway $gateway ) {
return $gateway->get_option( 'title', $title );
},
10,
@ -434,7 +455,7 @@ class SettingsModule implements ServiceModule, ExecutableModule {
);
add_filter(
'woocommerce_paypal_payments_credit_card_gateway_description',
function( string $description, WC_Payment_Gateway $gateway ) {
function ( string $description, WC_Payment_Gateway $gateway ) {
return $gateway->get_option( 'description', $description );
},
10,
@ -444,7 +465,7 @@ class SettingsModule implements ServiceModule, ExecutableModule {
add_filter( 'woocommerce_paypal_payments_axo_gateway_should_update_enabled', '__return_false' );
add_filter(
'woocommerce_paypal_payments_axo_gateway_title',
function( string $title, WC_Payment_Gateway $gateway ) {
function ( string $title, WC_Payment_Gateway $gateway ) {
return $gateway->get_option( 'title', $title );
},
10,
@ -452,7 +473,7 @@ class SettingsModule implements ServiceModule, ExecutableModule {
);
add_filter(
'woocommerce_paypal_payments_axo_gateway_description',
function( string $description, WC_Payment_Gateway $gateway ) {
function ( string $description, WC_Payment_Gateway $gateway ) {
return $gateway->get_option( 'description', $description );
},
10,