mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-06 12:25:15 +08:00
Merge pull request #2985 from woocommerce/PCP-4096-allow-merchant-logout-disconnect
Allow merchant logout/disconnect (4096)
This commit is contained in:
commit
60f722568e
13 changed files with 182 additions and 40 deletions
|
@ -21,11 +21,11 @@ export default {
|
|||
DO_PERSIST_DATA: 'COMMON:DO_PERSIST_DATA',
|
||||
DO_DIRECT_API_AUTHENTICATION: 'COMMON:DO_DIRECT_API_AUTHENTICATION',
|
||||
DO_OAUTH_AUTHENTICATION: 'COMMON:DO_OAUTH_AUTHENTICATION',
|
||||
DO_DISCONNECT_MERCHANT: 'COMMON:DO_DISCONNECT_MERCHANT',
|
||||
DO_GENERATE_ONBOARDING_URL: 'COMMON:DO_GENERATE_ONBOARDING_URL',
|
||||
DO_REFRESH_MERCHANT: 'COMMON:DO_REFRESH_MERCHANT',
|
||||
DO_REFRESH_FEATURES: 'COMMON:DO_REFRESH_FEATURES',
|
||||
DO_RESUBSCRIBE_WEBHOOKS: 'COMMON:DO_RESUBSCRIBE_WEBHOOKS',
|
||||
DO_START_WEBHOOK_SIMULATION: 'COMMON:DO_START_WEBHOOK_SIMULATION',
|
||||
DO_CHECK_WEBHOOK_SIMULATION_STATE:
|
||||
'COMMON:DO_CHECK_WEBHOOK_SIMULATION_STATE',
|
||||
DO_CHECK_WEBHOOK_SIMULATION: 'COMMON:DO_CHECK_WEBHOOK_SIMULATION',
|
||||
};
|
||||
|
|
|
@ -212,6 +212,15 @@ export const authenticateWithOAuth = function* (
|
|||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Side effect. Checks webhook simulation.
|
||||
*
|
||||
* @return {Action} The action.
|
||||
*/
|
||||
export const disconnectMerchant = function* () {
|
||||
return yield { type: ACTION_TYPES.DO_DISCONNECT_MERCHANT };
|
||||
};
|
||||
|
||||
/**
|
||||
* Side effect. Clears and refreshes the merchant data via a REST request.
|
||||
*
|
||||
|
@ -288,5 +297,5 @@ export const startWebhookSimulation = function* () {
|
|||
* @return {Action} The action.
|
||||
*/
|
||||
export const checkWebhookSimulationState = function* () {
|
||||
return yield { type: ACTION_TYPES.DO_CHECK_WEBHOOK_SIMULATION_STATE };
|
||||
return yield { type: ACTION_TYPES.DO_CHECK_WEBHOOK_SIMULATION };
|
||||
};
|
||||
|
|
|
@ -46,14 +46,26 @@ export const REST_DIRECT_AUTHENTICATION_PATH =
|
|||
'/wc/v3/wc_paypal/authenticate/direct';
|
||||
|
||||
/**
|
||||
* REST path to perform the ISU authentication check, using shared ID and authCode.
|
||||
* REST path to perform the OAuth authentication check, using shared ID and authCode.
|
||||
*
|
||||
* Used by: Controls
|
||||
* See: AuthenticateRestEndpoint.php
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
export const REST_ISU_AUTHENTICATION_PATH = '/wc/v3/wc_paypal/authenticate/isu';
|
||||
export const REST_OAUTH_AUTHENTICATION_PATH =
|
||||
'/wc/v3/wc_paypal/authenticate/oauth';
|
||||
|
||||
/**
|
||||
* REST path to disconnect the current merchant from PayPal.
|
||||
*
|
||||
* Used by: Controls
|
||||
* See: AuthenticateRestEndpoint.php
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
export const REST_DISCONNECT_MERCHANT_PATH =
|
||||
'/wc/v3/wc_paypal/authenticate/disconnect';
|
||||
|
||||
/**
|
||||
* REST path to generate an ISU URL for the PayPal-login.
|
||||
|
@ -66,24 +78,24 @@ export const REST_ISU_AUTHENTICATION_PATH = '/wc/v3/wc_paypal/authenticate/isu';
|
|||
export const REST_CONNECTION_URL_PATH = '/wc/v3/wc_paypal/login_link';
|
||||
|
||||
/**
|
||||
* REST path to fetch webhooks data or resubscribe webhooks,
|
||||
* REST path to fetch webhooks data or resubscribe webhooks.
|
||||
*
|
||||
* Used by: Controls
|
||||
* See: WebhookSettingsEndpoint.php
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
export const REST_WEBHOOKS = '/wc/v3/wc_paypal/webhook_settings';
|
||||
export const REST_WEBHOOKS = '/wc/v3/wc_paypal/webhooks';
|
||||
|
||||
/**
|
||||
* REST path to start webhook simulation and observe the state,
|
||||
* REST path to start webhook simulation and observe the state.
|
||||
*
|
||||
* Used by: Controls
|
||||
* See: WebhookSettingsEndpoint.php
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
export const REST_WEBHOOKS_SIMULATE = '/wc/v3/wc_paypal/webhook_simulate';
|
||||
export const REST_WEBHOOKS_SIMULATE = '/wc/v3/wc_paypal/webhooks/simulate';
|
||||
|
||||
/**
|
||||
* REST path to refresh the feature status.
|
||||
|
@ -93,5 +105,4 @@ export const REST_WEBHOOKS_SIMULATE = '/wc/v3/wc_paypal/webhook_simulate';
|
|||
*
|
||||
* @type {string}
|
||||
*/
|
||||
export const REST_REFRESH_FEATURES_PATH =
|
||||
'/wc/v3/wc_paypal/refresh-feature-status';
|
||||
export const REST_REFRESH_FEATURES_PATH = '/wc/v3/wc_paypal/refresh-features';
|
||||
|
|
|
@ -11,11 +11,12 @@ import apiFetch from '@wordpress/api-fetch';
|
|||
|
||||
import {
|
||||
REST_PERSIST_PATH,
|
||||
REST_DIRECT_AUTHENTICATION_PATH,
|
||||
REST_CONNECTION_URL_PATH,
|
||||
REST_HYDRATE_MERCHANT_PATH,
|
||||
REST_REFRESH_FEATURES_PATH,
|
||||
REST_ISU_AUTHENTICATION_PATH,
|
||||
REST_DIRECT_AUTHENTICATION_PATH,
|
||||
REST_OAUTH_AUTHENTICATION_PATH,
|
||||
REST_DISCONNECT_MERCHANT_PATH,
|
||||
REST_WEBHOOKS,
|
||||
REST_WEBHOOKS_SIMULATE,
|
||||
} from './constants';
|
||||
|
@ -82,7 +83,7 @@ export const controls = {
|
|||
} ) {
|
||||
try {
|
||||
return await apiFetch( {
|
||||
path: REST_ISU_AUTHENTICATION_PATH,
|
||||
path: REST_OAUTH_AUTHENTICATION_PATH,
|
||||
method: 'POST',
|
||||
data: {
|
||||
sharedId,
|
||||
|
@ -98,6 +99,13 @@ export const controls = {
|
|||
}
|
||||
},
|
||||
|
||||
async [ ACTION_TYPES.DO_DISCONNECT_MERCHANT ]() {
|
||||
return await apiFetch( {
|
||||
path: REST_DISCONNECT_MERCHANT_PATH,
|
||||
method: 'POST',
|
||||
} );
|
||||
},
|
||||
|
||||
async [ ACTION_TYPES.DO_REFRESH_MERCHANT ]() {
|
||||
try {
|
||||
return await apiFetch( { path: REST_HYDRATE_MERCHANT_PATH } );
|
||||
|
@ -138,7 +146,7 @@ export const controls = {
|
|||
} );
|
||||
},
|
||||
|
||||
async [ ACTION_TYPES.DO_CHECK_WEBHOOK_SIMULATION_STATE ]() {
|
||||
async [ ACTION_TYPES.DO_CHECK_WEBHOOK_SIMULATION ]() {
|
||||
return await apiFetch( {
|
||||
path: REST_WEBHOOKS_SIMULATE,
|
||||
} );
|
||||
|
|
|
@ -77,6 +77,8 @@ const commonReducer = createReducer( defaultTransient, defaultPersistent, {
|
|||
|
||||
// Keep "read-only" details and initialization flags.
|
||||
cleanState.wooSettings = { ...state.wooSettings };
|
||||
cleanState.merchant = { ...state.merchant };
|
||||
cleanState.features = { ...state.features };
|
||||
cleanState.isReady = true;
|
||||
|
||||
return cleanState;
|
||||
|
|
|
@ -5,6 +5,7 @@ export const addDebugTools = ( context, modules ) => {
|
|||
return;
|
||||
}
|
||||
|
||||
// Dump the current state of all our Redux stores.
|
||||
context.dumpStore = async () => {
|
||||
/* eslint-disable no-console */
|
||||
if ( ! console?.groupCollapsed ) {
|
||||
|
@ -32,21 +33,46 @@ export const addDebugTools = ( context, modules ) => {
|
|||
/* eslint-enable no-console */
|
||||
};
|
||||
|
||||
// Reset all Redux stores to their initial state.
|
||||
context.resetStore = () => {
|
||||
const stores = [ OnboardingStoreName, CommonStoreName ];
|
||||
const stores = [];
|
||||
const { isConnected } = wp.data.select( CommonStoreName ).merchant();
|
||||
|
||||
if ( isConnected ) {
|
||||
// Make sure the Onboarding wizard is "completed".
|
||||
const onboarding = wp.data.dispatch( OnboardingStoreName );
|
||||
onboarding.setCompleted( true );
|
||||
onboarding.persist();
|
||||
|
||||
// Reset all stores, except for the onboarding store.
|
||||
stores.push( CommonStoreName );
|
||||
// TODO: Add other stores here once they are available.
|
||||
} else {
|
||||
// Only reset the common & onboarding stores to restart the onboarding wizard.
|
||||
stores.push( CommonStoreName );
|
||||
stores.push( OnboardingStoreName );
|
||||
}
|
||||
|
||||
stores.forEach( ( storeName ) => {
|
||||
const store = wp.data.dispatch( storeName );
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log( `Reset store: ${ storeName }...` );
|
||||
|
||||
store.reset();
|
||||
store.persist();
|
||||
} );
|
||||
};
|
||||
|
||||
context.startOnboarding = () => {
|
||||
const onboarding = wp.data.dispatch( OnboardingStoreName );
|
||||
onboarding.setCompleted( false );
|
||||
onboarding.setStep( 0 );
|
||||
onboarding.persist();
|
||||
// Disconnect the merchant and display the onboarding wizard.
|
||||
context.disconnect = () => {
|
||||
const common = wp.data.dispatch( CommonStoreName );
|
||||
|
||||
common.disconnectMerchant();
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log( 'Disconnected from PayPal. Reloading the page...' );
|
||||
|
||||
window.location.reload();
|
||||
};
|
||||
};
|
||||
|
|
|
@ -67,6 +67,14 @@ class AuthenticationRestEndpoint extends RestEndpoint {
|
|||
* Configure REST API routes.
|
||||
*/
|
||||
public function register_routes() : void {
|
||||
/**
|
||||
* POST /wp-json/wc/v3/wc_paypal/authenticate/direct
|
||||
* {
|
||||
* clientId
|
||||
* clientSecret
|
||||
* useSandbox
|
||||
* }
|
||||
*/
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base . '/direct',
|
||||
|
@ -97,12 +105,20 @@ class AuthenticationRestEndpoint extends RestEndpoint {
|
|||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* POST /wp-json/wc/v3/wc_paypal/authenticate/oauth
|
||||
* {
|
||||
* sharedId
|
||||
* authCode
|
||||
* useSandbox
|
||||
* }
|
||||
*/
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base . '/isu',
|
||||
'/' . $this->rest_base . '/oauth',
|
||||
array(
|
||||
'methods' => WP_REST_Server::EDITABLE,
|
||||
'callback' => array( $this, 'connect_isu' ),
|
||||
'callback' => array( $this, 'connect_oauth' ),
|
||||
'permission_callback' => array( $this, 'check_permission' ),
|
||||
'args' => array(
|
||||
'sharedId' => array(
|
||||
|
@ -123,6 +139,19 @@ class AuthenticationRestEndpoint extends RestEndpoint {
|
|||
),
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* POST /wp-json/wc/v3/wc_paypal/authenticate/disconnect
|
||||
*/
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base . '/disconnect',
|
||||
array(
|
||||
'methods' => WP_REST_Server::EDITABLE,
|
||||
'callback' => array( $this, 'disconnect' ),
|
||||
'permission_callback' => array( $this, 'check_permission' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -152,14 +181,14 @@ class AuthenticationRestEndpoint extends RestEndpoint {
|
|||
}
|
||||
|
||||
/**
|
||||
* ISU login: Retrieves clientId and clientSecret using a sharedId and authCode.
|
||||
* OAuth login: Retrieves clientId and clientSecret using a sharedId and authCode.
|
||||
*
|
||||
* This is the final step in the UI-driven login via the ISU popup, which
|
||||
* This is the final step in the UI-driven login via the OAuth popup, which
|
||||
* is triggered by the LoginLinkRestEndpoint URL.
|
||||
*
|
||||
* @param WP_REST_Request $request Full data about the request.
|
||||
*/
|
||||
public function connect_isu( WP_REST_Request $request ) : WP_REST_Response {
|
||||
public function connect_oauth( WP_REST_Request $request ) : WP_REST_Response {
|
||||
$shared_id = $request->get_param( 'sharedId' );
|
||||
$auth_code = $request->get_param( 'authCode' );
|
||||
$use_sandbox = $request->get_param( 'useSandbox' );
|
||||
|
@ -176,4 +205,15 @@ class AuthenticationRestEndpoint extends RestEndpoint {
|
|||
|
||||
return $this->return_success( $response );
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnect the merchant and clear the authentication details.
|
||||
*
|
||||
* @return WP_REST_Response
|
||||
*/
|
||||
public function disconnect() : WP_REST_Response {
|
||||
$this->authentication_manager->disconnect();
|
||||
|
||||
return $this->return_success( 'OK' );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,7 +110,10 @@ class CommonRestEndpoint extends RestEndpoint {
|
|||
/**
|
||||
* Configure REST API routes.
|
||||
*/
|
||||
public function register_routes() {
|
||||
public function register_routes() : void {
|
||||
/**
|
||||
* GET /wp-json/wc/v3/wc_paypal/common
|
||||
*/
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base,
|
||||
|
@ -121,6 +124,12 @@ class CommonRestEndpoint extends RestEndpoint {
|
|||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* POST /wp-json/wc/v3/wc_paypal/common
|
||||
* {
|
||||
* // Fields mentioned in $field_map[]['js_name']
|
||||
* }
|
||||
*/
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base,
|
||||
|
@ -131,6 +140,9 @@ class CommonRestEndpoint extends RestEndpoint {
|
|||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* GET /wp-json/wc/v3/wc_paypal/common/merchant
|
||||
*/
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
"/$this->rest_base/merchant",
|
||||
|
|
|
@ -52,6 +52,13 @@ class LoginLinkRestEndpoint extends RestEndpoint {
|
|||
* Configure REST API routes.
|
||||
*/
|
||||
public function register_routes() : void {
|
||||
/**
|
||||
* POST /wp-json/wc/v3/wc_paypal/login_link
|
||||
* {
|
||||
* useSandbox
|
||||
* products
|
||||
* }
|
||||
*/
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base,
|
||||
|
|
|
@ -96,7 +96,10 @@ class OnboardingRestEndpoint extends RestEndpoint {
|
|||
/**
|
||||
* Configure REST API routes.
|
||||
*/
|
||||
public function register_routes() {
|
||||
public function register_routes() : void {
|
||||
/**
|
||||
* GET /wp-json/wc/v3/wc_paypal/onboarding
|
||||
*/
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base,
|
||||
|
@ -107,6 +110,12 @@ class OnboardingRestEndpoint extends RestEndpoint {
|
|||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* POST /wp-json/wc/v3/wc_paypal/onboarding
|
||||
* {
|
||||
* // Fields mentioned in $field_map[]['js_name']
|
||||
* }
|
||||
*/
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base,
|
||||
|
|
|
@ -25,7 +25,7 @@ class RefreshFeatureStatusEndpoint extends RestEndpoint {
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = 'refresh-feature-status';
|
||||
protected $rest_base = 'refresh-features';
|
||||
|
||||
/**
|
||||
* Cache timeout in seconds.
|
||||
|
@ -82,7 +82,10 @@ class RefreshFeatureStatusEndpoint extends RestEndpoint {
|
|||
/**
|
||||
* Configure REST API routes.
|
||||
*/
|
||||
public function register_routes() {
|
||||
public function register_routes() : void {
|
||||
/**
|
||||
* POST /wp-json/wc/v3/wc_paypal/refresh-features
|
||||
*/
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base,
|
||||
|
|
|
@ -29,14 +29,7 @@ class WebhookSettingsEndpoint extends RestEndpoint {
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = 'webhook_settings';
|
||||
|
||||
/**
|
||||
* Endpoint base to start webhook simulation and check the state
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected string $rest_simulate_base = 'webhook_simulate';
|
||||
protected $rest_base = 'webhooks';
|
||||
|
||||
/**
|
||||
* Application webhook endpoint
|
||||
|
@ -67,7 +60,11 @@ class WebhookSettingsEndpoint extends RestEndpoint {
|
|||
* @param WebhookRegistrar $webhook_registrar A service that allows resubscribing webhooks.
|
||||
* @param WebhookSimulation $webhook_simulation A service that allows webhook simulations.
|
||||
*/
|
||||
public function __construct( WebhookEndpoint $webhook_endpoint, WebhookRegistrar $webhook_registrar, WebhookSimulation $webhook_simulation ) {
|
||||
public function __construct(
|
||||
WebhookEndpoint $webhook_endpoint,
|
||||
WebhookRegistrar $webhook_registrar,
|
||||
WebhookSimulation $webhook_simulation
|
||||
) {
|
||||
$this->webhook_endpoint = $webhook_endpoint;
|
||||
$this->webhook_registrar = $webhook_registrar;
|
||||
$this->webhook_simulation = $webhook_simulation;
|
||||
|
@ -77,6 +74,10 @@ class WebhookSettingsEndpoint extends RestEndpoint {
|
|||
* Configure REST API routes.
|
||||
*/
|
||||
public function register_routes() : void {
|
||||
/**
|
||||
* GET /wp-json/wc/v3/wc_paypal/webhooks
|
||||
* POST /wp-json/wc/v3/wc_paypal/webhooks
|
||||
*/
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base,
|
||||
|
@ -94,9 +95,13 @@ class WebhookSettingsEndpoint extends RestEndpoint {
|
|||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* GET /wp-json/wc/v3/wc_paypal/webhooks/simulate
|
||||
* POST /wp-json/wc/v3/wc_paypal/webhooks/simulate
|
||||
*/
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_simulate_base,
|
||||
'/' . $this->rest_base . '/simulate',
|
||||
array(
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
|
|
|
@ -122,6 +122,11 @@ class AuthenticationManager {
|
|||
* is no need for it here, it's good house-keeping practice to clean up.
|
||||
*/
|
||||
do_action( 'woocommerce_paypal_payments_flush_api_cache' );
|
||||
|
||||
/**
|
||||
* Clear the APM eligibility flags from the default settings object.
|
||||
*/
|
||||
do_action( 'woocommerce_paypal_payments_clear_apm_product_status', null );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -420,6 +425,11 @@ class AuthenticationManager {
|
|||
*/
|
||||
do_action( 'woocommerce_paypal_payments_authenticated_merchant' );
|
||||
|
||||
/**
|
||||
* Clear the APM eligibility flags from the default settings object.
|
||||
*/
|
||||
do_action( 'woocommerce_paypal_payments_clear_apm_product_status', null );
|
||||
|
||||
/**
|
||||
* Subscribe the new merchant to relevant PayPal webhooks.
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue