Automattic\WooCommerce\Internal\Admin\Settings\PaymentsProviders\WooPayments
WooPaymentsService::disable_test_account │ public │ WC 1.0
Disable a test account during the switch-to-live onboarding flow.
Method of the class: WooPaymentsService{}
No Hooks.
Returns
Array. The response from the WooPayments API.
Usage
$WooPaymentsService = new WooPaymentsService(); $WooPaymentsService->disable_test_account( $location, $from, ?string $source ): array;
- $location(string) (required)
- The location for which we are onboarding. This is an ISO 3166-1 alpha-2 country code.
- $from(string)
- Where in the UI the request is coming from. If not provided, it will identify the origin as the WC Admin Payments settings.
Default:'' - ?string $source
- .
Default:self::SESSION_ENTRY_DEFAULT
WooPaymentsService::disable_test_account() WooPaymentsService::disable test account code WC 11.0.0
public function disable_test_account( string $location, string $from = '', ?string $source = self::SESSION_ENTRY_DEFAULT ): array {
$this->check_if_onboarding_action_is_acceptable();
// Ensure the payment gateways logic is initialized in case actions need to be taken on payment gateway changes.
WC()->payment_gateways();
$response = array(
'success' => true,
);
$event_props = array();
$source = $this->validate_onboarding_source( $source );
$endpoint = '';
// Both internal calls take the same parameters; only the endpoint differs per account type.
$params = array(
'from' => ! empty( $from ) ? esc_attr( $from ) : self::FROM_PAYMENT_SETTINGS,
'source' => $source,
);
// The same message is reused wherever an unexpected exception is converted to a WP_Error.
$exception_error_message = esc_html__( 'An unexpected error happened while disabling the test account.', 'woocommerce' );
// Briefly lock the onboarding while Core determines the account transition to perform.
// The internal WooPayments endpoint must run after this lock is cleared because it may
// trigger account deletion webhooks that also touch the shared NOX lock option.
$this->set_onboarding_lock();
try {
$had_test_account = $this->has_test_account();
$had_sandbox_account = $this->has_sandbox_account();
$event_props = array(
'account_type' => $had_test_account ? 'test_drive' : ( $had_sandbox_account ? 'sandbox' : 'unknown' ),
'source' => $source,
);
if ( $had_test_account ) {
// Prepare the WooPayments API disable call for Phase 2, after the lock is released.
$endpoint = '/wc/v3/payments/onboarding/test_drive_account/disable';
} elseif ( $had_sandbox_account ) {
// Prepare the WooPayments API onboarding reset call for Phase 2, after the lock is released.
$endpoint = '/wc/v3/payments/onboarding/reset';
}
} catch ( Exception $e ) {
// Convert the exception to a WP_Error; the onboarding lock is released in the finally below.
$response = $this->get_onboarding_client_api_exception_error( $e, $exception_error_message );
} finally {
// Unlock before making the internal WooPayments request to avoid self-conflicting
// with WooPayments account cleanup and account.deleted webhook side effects.
$this->clear_onboarding_lock();
}
// Phase 2 runs after the shared lock is released to avoid the account.deleted webhook
// self-conflict. The WooPayments endpoint is not idempotent: a duplicate concurrent call is
// guarded against re-deleting the account (WooPayments overwrites its account cache before
// the delete, so is_stripe_connected() short-circuits), but it still surfaces to the second
// caller as a hard ApiException( FAILED_DEPENDENCY ) via the is_wp_error() check below.
// Request-scoped locking for that residual window is deferred to the broader
// Core/WooPayments shared-lock contract.
if ( ! is_wp_error( $response ) && ! empty( $endpoint ) ) {
try {
$response = $this->proxy->call_static(
Utils::class,
'rest_endpoint_post_request',
$endpoint,
$params
);
} catch ( Exception $e ) {
// Convert the exception to a WP_Error so the failure is surfaced to the caller.
$response = $this->get_onboarding_client_api_exception_error( $e, $exception_error_message );
}
}
// Make sure the onboarding mode is reset.
if ( class_exists( 'WC_Payments_Onboarding_Service' ) && defined( 'WC_Payments_Onboarding_Service::TEST_MODE_OPTION' ) ) {
$this->proxy->call_function( 'update_option', Constants::get_constant( 'WC_Payments_Onboarding_Service::TEST_MODE_OPTION' ), 'no' );
}
// Track the failure to disable the test account.
if ( is_wp_error( $response ) || ! is_array( $response ) || empty( $response['success'] ) ) {
$this->record_event(
self::EVENT_PREFIX . 'onboarding_test_account_disable_error',
$location,
array(
'source' => $source,
)
);
}
if ( is_wp_error( $response ) ) {
throw new ApiException(
'woocommerce_woopayments_onboarding_client_api_error',
esc_html( $response->get_error_message() ),
(int) WP_Http::FAILED_DEPENDENCY,
map_deep( (array) $response->get_error_data(), 'esc_html' )
);
}
if ( ! is_array( $response ) || empty( $response['success'] ) ) {
throw new ApiException(
'woocommerce_woopayments_onboarding_client_api_error',
esc_html__( 'Failed to disable the test account.', 'woocommerce' ),
(int) WP_Http::FAILED_DEPENDENCY
);
}
// The account mutation above has already committed, so the following is internal NOX state
// sync, not a new user action. Use the internal record path that does not re-check the
// onboarding lock: Phase 2 ran unlocked, so a concurrent request may now hold the lock, and
// re-checking it here would turn an already-successful disable into an onboarding-locked
// error (the shared, token-less lock also can't be safely reacquired around this bookkeeping).
// See record_onboarding_step_completed().
// For sanity, make sure the payment methods step is marked as completed.
// This is to avoid the user being prompted to set up payment methods again.
$this->record_onboarding_step_completed( self::ONBOARDING_STEP_PAYMENT_METHODS, $location );
// For sanity, make sure the test account step is marked as completed and not blocked or failed.
// After disabling a test account, the user should be prompted to set up a live account.
$this->record_onboarding_step_completed( self::ONBOARDING_STEP_TEST_ACCOUNT, $location );
$this->clear_onboarding_step_blocked( self::ONBOARDING_STEP_TEST_ACCOUNT, $location );
$this->clear_onboarding_step_failed( self::ONBOARDING_STEP_TEST_ACCOUNT, $location );
// Clear the NOX profile data for the business verification step sub-step data.
// This way the user will be prompted to complete ALL the business verification sub-steps.
$business_verification_sub_step_data = $this->get_nox_profile_onboarding_step_data_entry( self::ONBOARDING_STEP_BUSINESS_VERIFICATION, $location, 'sub_steps', array() );
if ( ! empty( $business_verification_sub_step_data ) ) {
$this->save_nox_profile_onboarding_step_data_entry( self::ONBOARDING_STEP_BUSINESS_VERIFICATION, $location, 'sub_steps', array() );
}
// Record an event for the test account being disabled.
$this->record_event(
self::EVENT_PREFIX . 'onboarding_test_account_disabled',
$location,
$event_props
);
return $response;
}