mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-04 08:47:23 +08:00
Merge pull request #2995 from woocommerce/PCP-3867-redux-store-for-payment-methods
Redux store for Payment Methods (3867)
This commit is contained in:
commit
cb7682b362
19 changed files with 878 additions and 274 deletions
|
@ -1,25 +1,25 @@
|
|||
import { useState, useCallback } from '@wordpress/element';
|
||||
import SettingsBlock from './SettingsBlock';
|
||||
import PaymentMethodItemBlock from './PaymentMethodItemBlock';
|
||||
import { usePaymentMethods } from '../../../data/payment/hooks';
|
||||
|
||||
const PaymentMethodsBlock = ( {
|
||||
paymentMethods,
|
||||
className = '',
|
||||
onTriggerModal,
|
||||
} ) => {
|
||||
const [ selectedMethods, setSelectedMethods ] = useState( {} );
|
||||
|
||||
const handleSelect = useCallback( ( methodId, isSelected ) => {
|
||||
setSelectedMethods( ( prev ) => ( {
|
||||
...prev,
|
||||
[ methodId ]: isSelected,
|
||||
} ) );
|
||||
}, [] );
|
||||
const { setPersistent } = usePaymentMethods();
|
||||
|
||||
if ( ! paymentMethods?.length ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const handleSelect = ( paymentMethod, isSelected ) => {
|
||||
setPersistent( paymentMethod.id, {
|
||||
...paymentMethod,
|
||||
enabled: isSelected,
|
||||
} );
|
||||
};
|
||||
|
||||
return (
|
||||
<SettingsBlock
|
||||
className={ `ppcp-r-settings-block__payment-methods ${ className }` }
|
||||
|
@ -28,11 +28,9 @@ const PaymentMethodsBlock = ( {
|
|||
<PaymentMethodItemBlock
|
||||
key={ paymentMethod.id }
|
||||
{ ...paymentMethod }
|
||||
isSelected={ Boolean(
|
||||
selectedMethods[ paymentMethod.id ]
|
||||
) }
|
||||
isSelected={ paymentMethod.enabled }
|
||||
onSelect={ ( checked ) =>
|
||||
handleSelect( paymentMethod.id, checked )
|
||||
handleSelect( paymentMethod, checked )
|
||||
}
|
||||
onTriggerModal={ () =>
|
||||
onTriggerModal?.( paymentMethod.id )
|
||||
|
|
|
@ -1,44 +1,30 @@
|
|||
import { __ } from '@wordpress/i18n';
|
||||
import { useMemo } from '@wordpress/element';
|
||||
|
||||
import SettingsCard from '../../ReusableComponents/SettingsCard';
|
||||
import PaymentMethodsBlock from '../../ReusableComponents/SettingsBlocks/PaymentMethodsBlock';
|
||||
import { CommonHooks } from '../../../data';
|
||||
import { PaymentHooks } from '../../../data';
|
||||
import { useActiveModal } from '../../../data/common/hooks';
|
||||
import Modal from './TabSettingsElements/Blocks/Modal';
|
||||
|
||||
const TabPaymentMethods = () => {
|
||||
const { storeCountry, storeCurrency } = CommonHooks.useWooSettings();
|
||||
const { paymentMethodsPayPalCheckout } =
|
||||
PaymentHooks.usePaymentMethodsPayPalCheckout();
|
||||
const { paymentMethodsOnlineCardPayments } =
|
||||
PaymentHooks.usePaymentMethodsOnlineCardPayments();
|
||||
const { paymentMethodsAlternative } =
|
||||
PaymentHooks.usePaymentMethodsAlternative();
|
||||
|
||||
const { activeModal, setActiveModal } = useActiveModal();
|
||||
|
||||
const filteredPaymentMethods = useMemo( () => {
|
||||
const contextProps = { storeCountry, storeCurrency };
|
||||
|
||||
return {
|
||||
payPalCheckout: filterPaymentMethods(
|
||||
paymentMethodsPayPalCheckout,
|
||||
contextProps
|
||||
),
|
||||
onlineCardPayments: filterPaymentMethods(
|
||||
paymentMethodsOnlineCardPayments,
|
||||
contextProps
|
||||
),
|
||||
alternative: filterPaymentMethods(
|
||||
paymentMethodsAlternative,
|
||||
contextProps
|
||||
),
|
||||
};
|
||||
}, [ storeCountry, storeCurrency ] );
|
||||
|
||||
const getActiveMethod = () => {
|
||||
if ( ! activeModal ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const allMethods = [
|
||||
...filteredPaymentMethods.payPalCheckout,
|
||||
...filteredPaymentMethods.onlineCardPayments,
|
||||
...filteredPaymentMethods.alternative,
|
||||
...paymentMethodsPayPalCheckout,
|
||||
...paymentMethodsOnlineCardPayments,
|
||||
...paymentMethodsAlternative,
|
||||
];
|
||||
|
||||
return allMethods.find( ( method ) => method.id === activeModal );
|
||||
|
@ -57,7 +43,7 @@ const TabPaymentMethods = () => {
|
|||
contentContainer={ false }
|
||||
>
|
||||
<PaymentMethodsBlock
|
||||
paymentMethods={ filteredPaymentMethods.payPalCheckout }
|
||||
paymentMethods={ paymentMethodsPayPalCheckout }
|
||||
onTriggerModal={ setActiveModal }
|
||||
/>
|
||||
</SettingsCard>
|
||||
|
@ -75,7 +61,7 @@ const TabPaymentMethods = () => {
|
|||
contentContainer={ false }
|
||||
>
|
||||
<PaymentMethodsBlock
|
||||
paymentMethods={ filteredPaymentMethods.onlineCardPayments }
|
||||
paymentMethods={ paymentMethodsOnlineCardPayments }
|
||||
onTriggerModal={ setActiveModal }
|
||||
/>
|
||||
</SettingsCard>
|
||||
|
@ -93,7 +79,7 @@ const TabPaymentMethods = () => {
|
|||
contentContainer={ false }
|
||||
>
|
||||
<PaymentMethodsBlock
|
||||
paymentMethods={ filteredPaymentMethods.alternative }
|
||||
paymentMethods={ paymentMethodsAlternative }
|
||||
onTriggerModal={ setActiveModal }
|
||||
/>
|
||||
</SettingsCard>
|
||||
|
@ -116,193 +102,4 @@ const TabPaymentMethods = () => {
|
|||
);
|
||||
};
|
||||
|
||||
function filterPaymentMethods( paymentMethods, contextProps ) {
|
||||
return paymentMethods.filter( ( method ) =>
|
||||
typeof method.condition === 'function'
|
||||
? method.condition( contextProps )
|
||||
: true
|
||||
);
|
||||
}
|
||||
|
||||
const paymentMethodsPayPalCheckout = [
|
||||
{
|
||||
id: 'paypal',
|
||||
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',
|
||||
},
|
||||
{
|
||||
id: 'venmo',
|
||||
title: __( 'Venmo', 'woocommerce-paypal-payments' ),
|
||||
description: __(
|
||||
'Offer Venmo at checkout to millions of active users.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
icon: 'payment-method-venmo',
|
||||
},
|
||||
{
|
||||
id: 'paypal_credit',
|
||||
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',
|
||||
},
|
||||
{
|
||||
id: 'credit_and_debit_card_payments',
|
||||
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',
|
||||
},
|
||||
];
|
||||
|
||||
const paymentMethodsOnlineCardPayments = [
|
||||
{
|
||||
id: 'advanced_credit_and_debit_card_payments',
|
||||
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',
|
||||
},
|
||||
{
|
||||
id: 'fastlane',
|
||||
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',
|
||||
},
|
||||
{
|
||||
id: 'apple_pay',
|
||||
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',
|
||||
},
|
||||
{
|
||||
id: 'google_pay',
|
||||
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',
|
||||
},
|
||||
];
|
||||
|
||||
const paymentMethodsAlternative = [
|
||||
{
|
||||
id: 'bancontact',
|
||||
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',
|
||||
},
|
||||
{
|
||||
id: 'ideal',
|
||||
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',
|
||||
},
|
||||
{
|
||||
id: 'eps',
|
||||
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',
|
||||
},
|
||||
{
|
||||
id: 'blik',
|
||||
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',
|
||||
},
|
||||
{
|
||||
id: 'mybank',
|
||||
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',
|
||||
},
|
||||
{
|
||||
id: 'przelewy24',
|
||||
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',
|
||||
},
|
||||
{
|
||||
id: 'trustly',
|
||||
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',
|
||||
},
|
||||
{
|
||||
id: 'multibanco',
|
||||
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',
|
||||
},
|
||||
{
|
||||
id: 'pui',
|
||||
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: 'payment-method-ratepay',
|
||||
condition: ( { storeCountry, storeCurrency } ) =>
|
||||
storeCountry === 'DE' && storeCurrency === 'EUR',
|
||||
},
|
||||
{
|
||||
id: 'oxxo',
|
||||
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) 800–925–0304',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
icon: 'payment-method-oxxo',
|
||||
condition: ( { storeCountry, storeCurrency } ) =>
|
||||
storeCountry === 'MX' && storeCurrency === 'MXN',
|
||||
},
|
||||
];
|
||||
|
||||
export default TabPaymentMethods;
|
||||
|
|
|
@ -19,7 +19,7 @@ const createStandardFields = ( methodId, defaultTitle ) => ( {
|
|||
|
||||
const paymentMethods = {
|
||||
// PayPal Checkout methods
|
||||
paypal: {
|
||||
'ppcp-gateway': {
|
||||
fields: {
|
||||
...createStandardFields( 'paypal', 'PayPal' ),
|
||||
showLogo: {
|
||||
|
@ -29,12 +29,6 @@ const paymentMethods = {
|
|||
},
|
||||
},
|
||||
},
|
||||
venmo: {
|
||||
fields: createStandardFields( 'venmo', 'Venmo' ),
|
||||
},
|
||||
paypal_credit: {
|
||||
fields: createStandardFields( 'paypal_credit', 'PayPal Credit' ),
|
||||
},
|
||||
credit_and_debit_card_payments: {
|
||||
fields: createStandardFields(
|
||||
'credit_and_debit_card_payments',
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
import { OnboardingStoreName, CommonStoreName } from './index';
|
||||
import {
|
||||
OnboardingStoreName,
|
||||
CommonStoreName,
|
||||
PaymentStoreName,
|
||||
} from './index';
|
||||
|
||||
export const addDebugTools = ( context, modules ) => {
|
||||
if ( ! context || ! context?.debug ) {
|
||||
|
@ -47,7 +51,8 @@ export const addDebugTools = ( context, modules ) => {
|
|||
// Reset all stores, except for the onboarding store.
|
||||
stores.push( CommonStoreName );
|
||||
// TODO: Add other stores here once they are available.
|
||||
} else {
|
||||
stores.push( PaymentStoreName );
|
||||
} else {
|
||||
// Only reset the common & onboarding stores to restart the onboarding wizard.
|
||||
stores.push( CommonStoreName );
|
||||
stores.push( OnboardingStoreName );
|
||||
|
|
|
@ -2,19 +2,23 @@ import { addDebugTools } from './debug';
|
|||
import * as Onboarding from './onboarding';
|
||||
import * as Common from './common';
|
||||
import * as Styling from './styling';
|
||||
import * as Payment from './payment';
|
||||
|
||||
Onboarding.initStore();
|
||||
Common.initStore();
|
||||
Payment.initStore();
|
||||
Styling.initStore();
|
||||
|
||||
export const OnboardingHooks = Onboarding.hooks;
|
||||
export const CommonHooks = Common.hooks;
|
||||
export const PaymentHooks = Payment.hooks;
|
||||
export const StylingHooks = Styling.hooks;
|
||||
|
||||
export const OnboardingStoreName = Onboarding.STORE_NAME;
|
||||
export const CommonStoreName = Common.STORE_NAME;
|
||||
export const PaymentStoreName = Payment.STORE_NAME;
|
||||
export const StylingStoreName = Styling.STORE_NAME;
|
||||
|
||||
export * from './configuration';
|
||||
|
||||
addDebugTools( window.ppcpSettings, [ Onboarding, Common, Styling ] );
|
||||
addDebugTools( window.ppcpSettings, [ Onboarding, Common, Payment, Styling ] );
|
||||
|
|
45
modules/ppcp-settings/resources/js/data/payment/README.md
Normal file
45
modules/ppcp-settings/resources/js/data/payment/README.md
Normal file
|
@ -0,0 +1,45 @@
|
|||
# Store template
|
||||
|
||||
This template contains all files for a Redux store.
|
||||
|
||||
## New Store: Redux integration
|
||||
|
||||
1. Copy this folder, give it a correct name.
|
||||
2. Check each file for `<UNKNOWN>` placeholders and `TODO` remarks.
|
||||
3. Edit the main store-index file and add the relevant store integration there.
|
||||
4. Check the debug-module, and add relevant debug code.
|
||||
- Register the store in the `reset()` method.
|
||||
|
||||
---
|
||||
|
||||
Main store-index:
|
||||
`modules/ppcp-settings/resources/js/data/index.js`
|
||||
|
||||
Sample store integration:
|
||||
```js
|
||||
import * as YourStore from './yourStore';
|
||||
// ...
|
||||
YourStore.initStore();
|
||||
// ...
|
||||
export const YourStoreHooks = YourStore.hooks;
|
||||
// ...
|
||||
export const YourStoreName = YourStore.STORE_NAME;
|
||||
// ...
|
||||
addDebugTools( window.ppcpSettings, [ ..., YourStoreName ] );
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### New Store: PHP integration
|
||||
|
||||
1. Create the **REST endpoint** for hydrating and persisting data.
|
||||
- `modules/ppcp-settings/src/Endpoint/YourStoreRestEndpoint.php`
|
||||
- Extend from base class `RestEndpoint`
|
||||
2. Create the **data model** class to manage the DB interaction.
|
||||
- `modules/ppcp-settings/src/Data/YourStoreSettings.php`
|
||||
- Extend from base class `AbstractDataModel`
|
||||
3. Create relevant **DI services** for both files.
|
||||
- `modules/ppcp-settings/services.php`
|
||||
4. Register the REST endpoint in the **service module**.
|
||||
- `modules/ppcp-settings/src/SettingsModule.php`
|
||||
- Find the action `rest_api_init`
|
|
@ -0,0 +1,18 @@
|
|||
/**
|
||||
* Action Types: Define unique identifiers for actions across all store modules.
|
||||
*
|
||||
* @file
|
||||
*/
|
||||
|
||||
export default {
|
||||
// Transient data.
|
||||
SET_TRANSIENT: 'PAYMENT:SET_TRANSIENT',
|
||||
|
||||
// Persistent data.
|
||||
SET_PERSISTENT: 'PAYMENT:SET_PERSISTENT',
|
||||
RESET: 'PAYMENT:RESET',
|
||||
HYDRATE: 'PAYMENT:HYDRATE',
|
||||
|
||||
// Controls - always start with "DO_".
|
||||
DO_PERSIST_DATA: 'PAYMENT:DO_PERSIST_DATA',
|
||||
};
|
71
modules/ppcp-settings/resources/js/data/payment/actions.js
Normal file
71
modules/ppcp-settings/resources/js/data/payment/actions.js
Normal file
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* Action Creators: Define functions to create action objects.
|
||||
*
|
||||
* These functions update state or trigger side effects (e.g., async operations).
|
||||
* Actions are categorized as Transient, Persistent, or Side effect.
|
||||
*
|
||||
* @file
|
||||
*/
|
||||
|
||||
import { select } from '@wordpress/data';
|
||||
|
||||
import ACTION_TYPES from './action-types';
|
||||
import { STORE_NAME } from './constants';
|
||||
|
||||
/**
|
||||
* @typedef {Object} Action An action object that is handled by a reducer or control.
|
||||
* @property {string} type - The action type.
|
||||
* @property {Object?} payload - Optional payload for the action.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Special. Resets all values in the store to initial defaults.
|
||||
*
|
||||
* @return {Action} The action.
|
||||
*/
|
||||
export const reset = () => ( { type: ACTION_TYPES.RESET } );
|
||||
|
||||
/**
|
||||
* Persistent. Set the full store details during app initialization.
|
||||
*
|
||||
* @param {{data: {}, flags?: {}}} payload
|
||||
* @return {Action} The action.
|
||||
*/
|
||||
export const hydrate = ( payload ) => ( {
|
||||
type: ACTION_TYPES.HYDRATE,
|
||||
payload,
|
||||
} );
|
||||
|
||||
/**
|
||||
* Transient. Marks the store as "ready", i.e., fully initialized.
|
||||
*
|
||||
* @param {boolean} isReady
|
||||
* @return {Action} The action.
|
||||
*/
|
||||
export const setIsReady = ( isReady ) => ( {
|
||||
type: ACTION_TYPES.SET_TRANSIENT,
|
||||
payload: { isReady },
|
||||
} );
|
||||
|
||||
/**
|
||||
* Side effect. Triggers the persistence of store data to the server.
|
||||
*
|
||||
* @return {Action} The action.
|
||||
*/
|
||||
export const persist = function* () {
|
||||
const data = yield select( STORE_NAME ).persistentData();
|
||||
|
||||
yield { type: ACTION_TYPES.DO_PERSIST_DATA, data };
|
||||
};
|
||||
|
||||
/**
|
||||
* Generic persistent-data updater.
|
||||
*
|
||||
* @param {string} prop Name of the property to update.
|
||||
* @param {any} value The new value of the property.
|
||||
* @return {Action} The action.
|
||||
*/
|
||||
export const setPersistent = ( prop, value ) => ( {
|
||||
type: ACTION_TYPES.SET_PERSISTENT,
|
||||
payload: { [ prop ]: value },
|
||||
} );
|
28
modules/ppcp-settings/resources/js/data/payment/constants.js
Normal file
28
modules/ppcp-settings/resources/js/data/payment/constants.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* Name of the Redux store module.
|
||||
*
|
||||
* Used by: Reducer, Selector, Index
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
export const STORE_NAME = 'wc/paypal/payment';
|
||||
|
||||
/**
|
||||
* REST path to hydrate data of this module by loading data from the WP DB.
|
||||
*
|
||||
* Used by: Resolvers
|
||||
* See: payment.php
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
export const REST_HYDRATE_PATH = '/wc/v3/wc_paypal/payment';
|
||||
|
||||
/**
|
||||
* REST path to persist data of this module to the WP DB.
|
||||
*
|
||||
* Used by: Controls
|
||||
* See: payment.php
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
export const REST_PERSIST_PATH = '/wc/v3/wc_paypal/payment';
|
23
modules/ppcp-settings/resources/js/data/payment/controls.js
vendored
Normal file
23
modules/ppcp-settings/resources/js/data/payment/controls.js
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* Controls: Implement side effects, typically asynchronous operations.
|
||||
*
|
||||
* Controls use ACTION_TYPES keys as identifiers.
|
||||
* They are triggered by corresponding actions and handle external interactions.
|
||||
*
|
||||
* @file
|
||||
*/
|
||||
|
||||
import apiFetch from '@wordpress/api-fetch';
|
||||
|
||||
import { REST_PERSIST_PATH } from './constants';
|
||||
import ACTION_TYPES from './action-types';
|
||||
|
||||
export const controls = {
|
||||
async [ ACTION_TYPES.DO_PERSIST_DATA ]( { data } ) {
|
||||
return await apiFetch( {
|
||||
path: REST_PERSIST_PATH,
|
||||
method: 'POST',
|
||||
data,
|
||||
} );
|
||||
},
|
||||
};
|
155
modules/ppcp-settings/resources/js/data/payment/hooks.js
Normal file
155
modules/ppcp-settings/resources/js/data/payment/hooks.js
Normal file
|
@ -0,0 +1,155 @@
|
|||
/**
|
||||
* Hooks: Provide the main API for components to interact with the store.
|
||||
*
|
||||
* These encapsulate store interactions, offering a consistent interface.
|
||||
* Hooks simplify data access and manipulation for components.
|
||||
*
|
||||
* @file
|
||||
*/
|
||||
|
||||
import { useSelect, useDispatch } from '@wordpress/data';
|
||||
|
||||
import { STORE_NAME } from './constants';
|
||||
|
||||
const useTransient = ( key ) =>
|
||||
useSelect(
|
||||
( select ) => select( STORE_NAME ).transientData()?.[ key ],
|
||||
[ key ]
|
||||
);
|
||||
|
||||
const usePersistent = ( key ) =>
|
||||
useSelect(
|
||||
( select ) => select( STORE_NAME ).persistentData()?.[ key ],
|
||||
[ key ]
|
||||
);
|
||||
|
||||
const useHooks = () => {
|
||||
const { persist, setPersistent } = useDispatch( STORE_NAME );
|
||||
|
||||
// Read-only flags and derived state.
|
||||
// Nothing here yet.
|
||||
|
||||
// Transient accessors.
|
||||
const isReady = useTransient( 'isReady' );
|
||||
|
||||
// PayPal checkout.
|
||||
const paypal = usePersistent( 'ppcp-gateway' );
|
||||
const venmo = usePersistent( 'venmo' );
|
||||
const payLater = usePersistent( 'pay-later' );
|
||||
const creditCard = usePersistent( 'ppcp-card-button-gateway' );
|
||||
|
||||
// Online card Payments.
|
||||
const advancedCreditCard = usePersistent( 'ppcp-credit-card-gateway' );
|
||||
const fastlane = usePersistent( 'ppcp-axo-gateway' );
|
||||
const applePay = usePersistent( 'ppcp-applepay' );
|
||||
const googlePay = usePersistent( 'ppcp-googlepay' );
|
||||
|
||||
// Alternative payment methods.
|
||||
const bancontact = usePersistent( 'ppcp-bancontact' );
|
||||
const blik = usePersistent( 'ppcp-blik' );
|
||||
const eps = usePersistent( 'ppcp-eps' );
|
||||
const ideal = usePersistent( 'ppcp-ideal' );
|
||||
const mybank = usePersistent( 'ppcp-mybank' );
|
||||
const p24 = usePersistent( 'ppcp-p24' );
|
||||
const trustly = usePersistent( 'ppcp-trustly' );
|
||||
const multibanco = usePersistent( 'ppcp-multibanco' );
|
||||
const pui = usePersistent( 'ppcp-pay-upon-invoice-gateway' );
|
||||
const oxxo = usePersistent( 'ppcp-oxxo-gateway' );
|
||||
|
||||
return {
|
||||
persist,
|
||||
isReady,
|
||||
setPersistent,
|
||||
paypal,
|
||||
venmo,
|
||||
payLater,
|
||||
creditCard,
|
||||
advancedCreditCard,
|
||||
fastlane,
|
||||
applePay,
|
||||
googlePay,
|
||||
bancontact,
|
||||
blik,
|
||||
eps,
|
||||
ideal,
|
||||
mybank,
|
||||
p24,
|
||||
trustly,
|
||||
multibanco,
|
||||
pui,
|
||||
oxxo,
|
||||
};
|
||||
};
|
||||
|
||||
export const useState = () => {
|
||||
const { persist, isReady } = useHooks();
|
||||
return { persist, isReady };
|
||||
};
|
||||
|
||||
export const usePaymentMethods = () => {
|
||||
const { setPersistent } = useHooks();
|
||||
|
||||
return {
|
||||
setPersistent,
|
||||
};
|
||||
};
|
||||
|
||||
export const usePaymentMethodsPayPalCheckout = () => {
|
||||
const { paypal, venmo, payLater, creditCard } = useHooks();
|
||||
const paymentMethodsPayPalCheckout = [
|
||||
paypal,
|
||||
venmo,
|
||||
payLater,
|
||||
creditCard,
|
||||
];
|
||||
|
||||
return {
|
||||
paymentMethodsPayPalCheckout,
|
||||
};
|
||||
};
|
||||
|
||||
export const usePaymentMethodsOnlineCardPayments = () => {
|
||||
const { advancedCreditCard, fastlane, applePay, googlePay } = useHooks();
|
||||
const paymentMethodsOnlineCardPayments = [
|
||||
advancedCreditCard,
|
||||
fastlane,
|
||||
applePay,
|
||||
googlePay,
|
||||
];
|
||||
|
||||
return {
|
||||
paymentMethodsOnlineCardPayments,
|
||||
};
|
||||
};
|
||||
|
||||
export const usePaymentMethodsAlternative = () => {
|
||||
const {
|
||||
bancontact,
|
||||
blik,
|
||||
eps,
|
||||
ideal,
|
||||
mybank,
|
||||
p24,
|
||||
trustly,
|
||||
multibanco,
|
||||
pui,
|
||||
oxxo,
|
||||
} = useHooks();
|
||||
|
||||
const paymentMethodsAlternative = [
|
||||
bancontact,
|
||||
blik,
|
||||
eps,
|
||||
ideal,
|
||||
mybank,
|
||||
p24,
|
||||
trustly,
|
||||
multibanco,
|
||||
pui,
|
||||
oxxo,
|
||||
];
|
||||
|
||||
return {
|
||||
paymentMethodsAlternative,
|
||||
};
|
||||
};
|
24
modules/ppcp-settings/resources/js/data/payment/index.js
Normal file
24
modules/ppcp-settings/resources/js/data/payment/index.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
import { createReduxStore, register } from '@wordpress/data';
|
||||
import { controls as wpControls } from '@wordpress/data-controls';
|
||||
|
||||
import { STORE_NAME } from './constants';
|
||||
import reducer from './reducer';
|
||||
import * as selectors from './selectors';
|
||||
import * as actions from './actions';
|
||||
import * as hooks from './hooks';
|
||||
import { resolvers } from './resolvers';
|
||||
import { controls } from './controls';
|
||||
|
||||
export const initStore = () => {
|
||||
const store = createReduxStore( STORE_NAME, {
|
||||
reducer,
|
||||
controls: { ...wpControls, ...controls },
|
||||
actions,
|
||||
selectors,
|
||||
resolvers,
|
||||
} );
|
||||
|
||||
register( store );
|
||||
};
|
||||
|
||||
export { hooks, selectors, STORE_NAME };
|
72
modules/ppcp-settings/resources/js/data/payment/reducer.js
Normal file
72
modules/ppcp-settings/resources/js/data/payment/reducer.js
Normal file
|
@ -0,0 +1,72 @@
|
|||
/**
|
||||
* Reducer: Defines store structure and state updates for this module.
|
||||
*
|
||||
* Manages both transient (temporary) and persistent (saved) state.
|
||||
* The initial state must define all properties, as dynamic additions are not supported.
|
||||
*
|
||||
* @file
|
||||
*/
|
||||
|
||||
import { createReducer, createSetters } from '../utils';
|
||||
import ACTION_TYPES from './action-types';
|
||||
|
||||
// Store structure.
|
||||
|
||||
// Transient: Values that are _not_ saved to the DB (like app lifecycle-flags).
|
||||
const defaultTransient = Object.freeze( {
|
||||
isReady: false,
|
||||
} );
|
||||
|
||||
// Persistent: Values that are loaded from the DB.
|
||||
const defaultPersistent = Object.freeze( {
|
||||
'ppcp-gateway': {},
|
||||
venmo: {},
|
||||
'pay-later': {},
|
||||
'ppcp-card-button-gateway': {},
|
||||
'ppcp-credit-card-gateway': {},
|
||||
'ppcp-axo-gateway': {},
|
||||
'ppcp-applepay': {},
|
||||
'ppcp-googlepay': {},
|
||||
'ppcp-bancontact': {},
|
||||
'ppcp-blik': {},
|
||||
'ppcp-eps': {},
|
||||
'ppcp-ideal': {},
|
||||
'ppcp-mybank': {},
|
||||
'ppcp-p24': {},
|
||||
'ppcp-trustly': {},
|
||||
'ppcp-multibanco': {},
|
||||
'ppcp-pay-upon-invoice-gateway': {},
|
||||
'ppcp-oxxo-gateway': {},
|
||||
} );
|
||||
|
||||
// Reducer logic.
|
||||
|
||||
const [ setTransient, setPersistent ] = createSetters(
|
||||
defaultTransient,
|
||||
defaultPersistent
|
||||
);
|
||||
|
||||
const reducer = createReducer( defaultTransient, defaultPersistent, {
|
||||
[ ACTION_TYPES.SET_TRANSIENT ]: ( state, payload ) =>
|
||||
setTransient( state, payload ),
|
||||
|
||||
[ ACTION_TYPES.SET_PERSISTENT ]: ( state, payload ) =>
|
||||
setPersistent( state, payload ),
|
||||
|
||||
[ ACTION_TYPES.RESET ]: ( state ) => {
|
||||
const cleanState = setTransient(
|
||||
setPersistent( state, defaultPersistent ),
|
||||
defaultTransient
|
||||
);
|
||||
|
||||
// Keep "read-only" details and initialization flags.
|
||||
cleanState.isReady = true;
|
||||
|
||||
return cleanState;
|
||||
},
|
||||
|
||||
[ ACTION_TYPES.HYDRATE ]: ( state, payload ) =>
|
||||
setPersistent( state, payload.data ),
|
||||
} );
|
||||
|
||||
export default reducer;
|
36
modules/ppcp-settings/resources/js/data/payment/resolvers.js
Normal file
36
modules/ppcp-settings/resources/js/data/payment/resolvers.js
Normal file
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* Resolvers: Handle asynchronous data fetching for the store.
|
||||
*
|
||||
* These functions update store state with data from external sources.
|
||||
* Each resolver corresponds to a specific selector (selector with same name must exist).
|
||||
* Resolvers are called automatically when selectors request unavailable data.
|
||||
*
|
||||
* @file
|
||||
*/
|
||||
|
||||
import { dispatch } from '@wordpress/data';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { apiFetch } from '@wordpress/data-controls';
|
||||
|
||||
import { STORE_NAME, REST_HYDRATE_PATH } from './constants';
|
||||
|
||||
export const resolvers = {
|
||||
/**
|
||||
* Retrieve settings from the site's REST API.
|
||||
*/
|
||||
*persistentData() {
|
||||
try {
|
||||
const result = yield apiFetch( { path: REST_HYDRATE_PATH } );
|
||||
|
||||
yield dispatch( STORE_NAME ).hydrate( result );
|
||||
yield dispatch( STORE_NAME ).setIsReady( true );
|
||||
} catch ( e ) {
|
||||
yield dispatch( 'core/notices' ).createErrorNotice(
|
||||
__(
|
||||
'Error retrieving payment details.',
|
||||
'woocommerce-paypal-payments'
|
||||
)
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
21
modules/ppcp-settings/resources/js/data/payment/selectors.js
Normal file
21
modules/ppcp-settings/resources/js/data/payment/selectors.js
Normal file
|
@ -0,0 +1,21 @@
|
|||
/**
|
||||
* Selectors: Extract specific pieces of state from the store.
|
||||
*
|
||||
* These functions provide a consistent interface for accessing store data.
|
||||
* They allow components to retrieve data without knowing the store structure.
|
||||
*
|
||||
* @file
|
||||
*/
|
||||
|
||||
const EMPTY_OBJ = Object.freeze( {} );
|
||||
|
||||
const getState = ( state ) => state || EMPTY_OBJ;
|
||||
|
||||
export const persistentData = ( state ) => {
|
||||
return getState( state ).data || EMPTY_OBJ;
|
||||
};
|
||||
|
||||
export const transientData = ( state ) => {
|
||||
const { data, ...transientState } = getState( state );
|
||||
return transientState || EMPTY_OBJ;
|
||||
};
|
|
@ -13,11 +13,13 @@ use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
|
|||
use WooCommerce\PayPalCommerce\Settings\Ajax\SwitchSettingsUiEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Settings\Data\GeneralSettings;
|
||||
use WooCommerce\PayPalCommerce\Settings\Data\OnboardingProfile;
|
||||
use WooCommerce\PayPalCommerce\Settings\Data\PaymentSettings;
|
||||
use WooCommerce\PayPalCommerce\Settings\Data\SettingsModel;
|
||||
use WooCommerce\PayPalCommerce\Settings\Endpoint\AuthenticationRestEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Settings\Endpoint\CommonRestEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Settings\Endpoint\LoginLinkRestEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Settings\Endpoint\OnboardingRestEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Settings\Endpoint\PaymentRestEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Settings\Endpoint\RefreshFeatureStatusEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Settings\Endpoint\WebhookSettingsEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Settings\Endpoint\SettingsRestEndpoint;
|
||||
|
@ -80,6 +82,9 @@ return array(
|
|||
'settings.rest.common' => static function ( ContainerInterface $container ) : CommonRestEndpoint {
|
||||
return new CommonRestEndpoint( $container->get( 'settings.data.general' ) );
|
||||
},
|
||||
'settings.rest.payment' => static function ( ContainerInterface $container ) : PaymentRestEndpoint {
|
||||
return new PaymentRestEndpoint();
|
||||
},
|
||||
'settings.rest.styling' => static function ( ContainerInterface $container ) : StylingRestEndpoint {
|
||||
return new StylingRestEndpoint(
|
||||
$container->get( 'settings.data.styling' ),
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* PaymentSettings class
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Settings\Data
|
||||
*/
|
||||
|
||||
declare( strict_types = 1 );
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Settings\Data;
|
||||
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* This class serves as a container for managing the payment settings.
|
||||
*/
|
||||
class PaymentSettings extends AbstractDataModel {
|
||||
|
||||
/**
|
||||
* Option key where profile details are stored.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected const OPTION_KEY = 'woocommerce-ppcp-data-payment-settings';
|
||||
|
||||
/**
|
||||
* Get default values for the model.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_defaults() : array {
|
||||
return array();
|
||||
}
|
||||
}
|
341
modules/ppcp-settings/src/Endpoint/PaymentRestEndpoint.php
Normal file
341
modules/ppcp-settings/src/Endpoint/PaymentRestEndpoint.php
Normal file
|
@ -0,0 +1,341 @@
|
|||
<?php
|
||||
/**
|
||||
* REST endpoint to manage the payment methods page.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Settings\Endpoint
|
||||
*/
|
||||
|
||||
declare( strict_types = 1 );
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Settings\Endpoint;
|
||||
|
||||
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\IDealGateway;
|
||||
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\MultibancoGateway;
|
||||
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\MyBankGateway;
|
||||
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\P24Gateway;
|
||||
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\TrustlyGateway;
|
||||
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;
|
||||
use WP_REST_Server;
|
||||
use WP_REST_Response;
|
||||
use WP_REST_Request;
|
||||
use WooCommerce\PayPalCommerce\Applepay\ApplePayGateway;
|
||||
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\EPSGateway;
|
||||
|
||||
/**
|
||||
* REST controller for the "Payment Methods" settings tab.
|
||||
*
|
||||
* This API acts as the intermediary between the "external world" and our
|
||||
* internal data model.
|
||||
*/
|
||||
class PaymentRestEndpoint extends RestEndpoint {
|
||||
/**
|
||||
* The base path for this REST controller.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = 'payment';
|
||||
|
||||
/**
|
||||
* Field mapping for request to profile transformation.
|
||||
*
|
||||
* @return array[]
|
||||
*/
|
||||
protected function gateways():array {
|
||||
return array(
|
||||
// PayPal checkout.
|
||||
PayPalGateway::ID => array(
|
||||
'id' => 'ppcp-gateway',
|
||||
'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',
|
||||
),
|
||||
'venmo' => 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',
|
||||
),
|
||||
'pay-later' => array(
|
||||
'id' => 'paypal_credit',
|
||||
'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',
|
||||
),
|
||||
CardButtonGateway::ID => array(
|
||||
'id' => 'credit_and_debit_card_payments',
|
||||
'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',
|
||||
),
|
||||
|
||||
// Online card Payments.
|
||||
CreditCardGateway::ID => array(
|
||||
'id' => 'advanced_credit_and_debit_card_payments',
|
||||
'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',
|
||||
),
|
||||
AxoGateway::ID => array(
|
||||
'id' => 'fastlane',
|
||||
'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',
|
||||
),
|
||||
ApplePayGateway::ID => array(
|
||||
'id' => 'apple_pay',
|
||||
'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',
|
||||
),
|
||||
GooglePayGateway::ID => array(
|
||||
'id' => 'google_pay',
|
||||
'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',
|
||||
),
|
||||
|
||||
// Alternative payment methods.
|
||||
BancontactGateway::ID => array(
|
||||
'id' => 'bancontact',
|
||||
'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',
|
||||
),
|
||||
BlikGateway::ID => array(
|
||||
'id' => 'blik',
|
||||
'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',
|
||||
),
|
||||
EPSGateway::ID => array(
|
||||
'id' => 'eps',
|
||||
'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',
|
||||
),
|
||||
IDealGateway::ID => array(
|
||||
'id' => 'ideal',
|
||||
'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',
|
||||
),
|
||||
MyBankGateway::ID => array(
|
||||
'id' => 'mybank',
|
||||
'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',
|
||||
),
|
||||
P24Gateway::ID => array(
|
||||
'id' => 'przelewy24',
|
||||
'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',
|
||||
),
|
||||
TrustlyGateway::ID => array(
|
||||
'id' => 'trustly',
|
||||
'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',
|
||||
),
|
||||
MultibancoGateway::ID => array(
|
||||
'id' => 'multibanco',
|
||||
'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',
|
||||
),
|
||||
PayUponInvoiceGateway::ID => array(
|
||||
'id' => 'pui',
|
||||
'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' => '',
|
||||
),
|
||||
OXXO::ID => array(
|
||||
'id' => 'oxxo',
|
||||
'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) 800–925–0304',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'icon' => '',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure REST API routes.
|
||||
*/
|
||||
public function register_routes() : void {
|
||||
/**
|
||||
* GET wc/v3/wc_paypal/payment
|
||||
*/
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base,
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_details' ),
|
||||
'permission_callback' => array( $this, 'check_permission' ),
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* POST wc/v3/wc_paypal/payment
|
||||
* {
|
||||
* [gateway_id]: {
|
||||
* enabled
|
||||
* title
|
||||
* description
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base,
|
||||
array(
|
||||
'methods' => WP_REST_Server::EDITABLE,
|
||||
'callback' => array( $this, 'update_details' ),
|
||||
'permission_callback' => array( $this, 'check_permission' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all payment methods details.
|
||||
*
|
||||
* @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();
|
||||
|
||||
foreach ( $this->gateways() as $key => $value ) {
|
||||
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' => false,
|
||||
'icon' => $this->gateways()[ $key ]['icon'] ?? '',
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$gateway = $all_gateways[ $key ];
|
||||
|
||||
$gateway_settings[ $key ] = array(
|
||||
'enabled' => 'yes' === $gateway->enabled,
|
||||
'title' => $this->gateways()[ $key ]['title'] ?? $gateway->get_title(),
|
||||
'description' => $this->gateways()[ $key ]['description'] ?? $gateway->get_description(),
|
||||
'method_title' => $gateway->get_method_title(),
|
||||
'id' => $this->gateways()[ $key ]['id'] ?? $key,
|
||||
'icon' => $this->gateways()[ $key ]['icon'] ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
return $this->return_success( $gateway_settings );
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates payment methods details based on the request.
|
||||
*
|
||||
* @param WP_REST_Request $request Full data about the request.
|
||||
*
|
||||
* @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();
|
||||
|
||||
foreach ( $this->gateways() as $key => $value ) {
|
||||
// Check if the REST body contains details for this gateway.
|
||||
if ( ! isset( $request_data[ $key ] ) || ! isset( $all_gateways[ $key ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$gateway = $all_gateways[ $key ];
|
||||
$new_data = $request_data[ $key ];
|
||||
|
||||
if ( isset( $new_data['enabled'] ) ) {
|
||||
$gateway->update_option( 'enabled', $new_data['enabled'] ? 'yes' : 'no' );
|
||||
}
|
||||
if ( isset( $new_data['title'] ) ) {
|
||||
$gateway->update_option( 'title', sanitize_text_field( $new_data['title'] ) );
|
||||
}
|
||||
if ( isset( $new_data['description'] ) ) {
|
||||
$gateway->update_option( 'description', wp_kses_post( $new_data['description'] ) );
|
||||
}
|
||||
|
||||
$gateway->process_admin_options();
|
||||
}
|
||||
|
||||
return $this->get_details();
|
||||
}
|
||||
}
|
|
@ -211,6 +211,7 @@ class SettingsModule implements ServiceModule, ExecutableModule {
|
|||
'login_link' => $container->get( 'settings.rest.login_link' ),
|
||||
'webhooks' => $container->get( 'settings.rest.webhooks' ),
|
||||
'refresh_feature_status' => $container->get( 'settings.rest.refresh_feature_status' ),
|
||||
'payment' => $container->get( 'settings.rest.payment' ),
|
||||
'settings' => $container->get( 'settings.rest.settings' ),
|
||||
'styling' => $container->get( 'settings.rest.styling' ),
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue