-
Notifications
You must be signed in to change notification settings - Fork 50
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add REST routes related to onboarding
Adds various routes under `/wc-paypal/v1/onboarding` including `/status` (onboarding status), `/set-credentials` (manually set merchant ID/email and keys) and `/get-params` (information useful for presenting the user with an onboarding button).
- Loading branch information
1 parent
b887041
commit 78a61eb
Showing
4 changed files
with
333 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
311 changes: 311 additions & 0 deletions
311
modules/ppcp-onboarding/src/class-onboarding-rest-controller.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,311 @@ | ||
<?php | ||
/** | ||
* Onboarding REST controller. | ||
* | ||
* @package WooCommerce\PayPalCommerce\Onboarding | ||
*/ | ||
|
||
declare(strict_types=1); | ||
|
||
namespace WooCommerce\PayPalCommerce\Onboarding; | ||
|
||
use Psr\Container\ContainerInterface; | ||
use WooCommerce\PayPalCommerce\Onboarding\State; | ||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; | ||
|
||
/** | ||
* Exposes and handles REST routes related to onboarding. | ||
*/ | ||
class Onboarding_REST_Controller { | ||
|
||
/** | ||
* REST namespace. | ||
* | ||
* @var string | ||
*/ | ||
protected $rest_namespace = 'wc-paypal/v1'; | ||
|
||
/** | ||
* REST base. | ||
* | ||
* @var string | ||
*/ | ||
protected $rest_base = 'onboarding'; | ||
|
||
/** | ||
* Module container with access to plugin services. | ||
* | ||
* @var ContainerInterface | ||
*/ | ||
private $container = null; | ||
|
||
/** | ||
* Used to temporarily store URL arguments to add to the return URL associated to a signup link. | ||
* | ||
* @var array | ||
*/ | ||
private $return_url_args = array(); | ||
|
||
|
||
/** | ||
* OnboardingRESTController constructor. | ||
* | ||
* @param ContainerInterface $container Module container with access to plugin services. | ||
*/ | ||
public function __construct( ContainerInterface $container ) { | ||
$this->container = $container; | ||
} | ||
|
||
/** | ||
* Registers REST routes under 'wc-paypal/v1/onboarding'. | ||
* Specifically: | ||
* - `/onboarding/get-params`, which returns information useful to display an onboarding button. | ||
* - `/onboarding/get-status`, which returns information about the current environment and its onboarding state. | ||
* - `/onboarding/set-credentials`, which allows setting merchant/API credentials. | ||
*/ | ||
public function register_routes() { | ||
register_rest_route( | ||
$this->rest_namespace, | ||
'/' . $this->rest_base . '/get-params', | ||
array( | ||
'methods' => 'POST', | ||
'callback' => array( $this, 'get_params' ), | ||
'permission_callback' => array( $this, 'check_permission' ), | ||
) | ||
); | ||
|
||
register_rest_route( | ||
$this->rest_namespace, | ||
'/' . $this->rest_base . '/get-status', | ||
array( | ||
'methods' => 'GET', | ||
'callback' => array( $this, 'get_status' ), | ||
'permission_callback' => array( $this, 'check_permission' ), | ||
) | ||
); | ||
|
||
register_rest_route( | ||
$this->rest_namespace, | ||
'/' . $this->rest_base . '/set-credentials', | ||
array( | ||
'methods' => 'POST', | ||
'callback' => array( $this, 'set_credentials' ), | ||
'permission_callback' => array( $this, 'check_permission' ), | ||
) | ||
); | ||
} | ||
|
||
/** | ||
* Validate the requester's permissions. | ||
* | ||
* @param WP_REST_Request $request The request. | ||
* @return bool | ||
*/ | ||
public function check_permission( $request ) { | ||
return current_user_can( 'install_plugins' ); | ||
} | ||
|
||
/** | ||
* Callback for the `/onboarding/get-params` endpoint. | ||
* | ||
* @param WP_REST_Request $request The request. | ||
* @return array | ||
*/ | ||
public function get_params( $request ) { | ||
$params = $request->get_json_params(); | ||
|
||
$environment = ( isset( $params['environment'] ) && in_array( $params['environment'], array( 'production', 'sandbox' ), true ) ) ? $params['environment'] : 'sandbox'; | ||
|
||
return array( | ||
'scriptURL' => trailingslashit( $this->container->get( 'onboarding.url' ) ) . 'assets/js/onboarding.js', | ||
'scriptData' => $this->container->get( 'onboarding.assets' )->get_script_data(), | ||
'environment' => $environment, | ||
'onboardCompleteCallback' => 'ppcp_onboarding_' . $environment . 'Callback', | ||
'signupLink' => $this->generate_signup_link( $environment, ( ! empty( $params['returnUrlArgs'] ) ? $params['returnUrlArgs'] : array() ) ), | ||
); | ||
} | ||
|
||
/** | ||
* Callback for the `/onboarding/get-status` endpoint. | ||
* | ||
* @param WP_REST_Request $request The request. | ||
* @return array | ||
*/ | ||
public function get_status( $request ) { | ||
$environment = $this->container->get( 'onboarding.environment' ); | ||
$state = $this->container->get( 'onboarding.state' ); | ||
|
||
return array( | ||
'environment' => $environment->current_environment(), | ||
'onboarded' => ( $state->current_state() >= State::STATE_ONBOARDED ), | ||
'state' => $this->get_onboarding_state_name( $state->current_state() ), | ||
'sandbox' => array( | ||
'state' => $this->get_onboarding_state_name( $state->sandbox_state() ), | ||
'onboarded' => ( $state->sandbox_state() >= State::STATE_ONBOARDED ), | ||
), | ||
'production' => array( | ||
'state' => $this->get_onboarding_state_name( $state->production_state() ), | ||
'onboarded' => ( $state->production_state() >= State::STATE_ONBOARDED ), | ||
), | ||
); | ||
} | ||
|
||
/** | ||
* Callback for the `/onboarding/set-credentials` endpoint. | ||
* | ||
* @param WP_REST_Request $request The request. | ||
* @return WP_Error|array | ||
*/ | ||
public function set_credentials( $request ) { | ||
static $credential_keys = array( | ||
'merchant_id', | ||
'merchant_email', | ||
'client_id', | ||
'client_secret', | ||
); | ||
|
||
// Sanitize params. | ||
$params = array_filter( array_map( 'trim', $request->get_json_params() ) ); | ||
|
||
// Validate 'environment'. | ||
if ( empty( $params['environment'] ) || ! in_array( $params['environment'], array( 'sandbox', 'production' ), true ) ) { | ||
return new \WP_Error( | ||
'woocommerce_paypal_payments_invalid_environment', | ||
sprintf( | ||
/* translators: placeholder is an arbitrary string. */ | ||
__( 'Environment "%s" is invalid. Use "sandbox" or "production".', 'woocommerce-paypal-payments' ), | ||
isset( $params['environment'] ) ? $params['environment'] : '' | ||
), | ||
array( 'status' => 400 ) | ||
); | ||
} | ||
|
||
// Validate the other fields. | ||
$missing_keys = array_values( array_diff( $credential_keys, array_keys( $params ) ) ); | ||
if ( $missing_keys ) { | ||
return new \WP_Error( | ||
'woocommerce_paypal_payments_credentials_incomplete', | ||
sprintf( | ||
/* translators: placeholder is a comma-separated list of fields. */ | ||
__( 'Credentials are incomplete. Missing fields: %s.', 'woocommerce-paypal-payments' ), | ||
implode( ', ', $missing_keys ) | ||
), | ||
array( | ||
'missing_fields' => $missing_keys, | ||
'status' => 400, | ||
) | ||
); | ||
} | ||
|
||
$settings = $this->container->get( 'wcgateway.settings' ); | ||
$skip_persist = true; | ||
|
||
$sandbox_on = ( 'sandbox' === $params['environment'] ); | ||
if ( ! $settings->has( 'sandbox_on' ) || ( (bool) $settings->get( 'sandbox_on' ) !== $sandbox_on ) ) { | ||
$settings->set( 'sandbox_on', $sandbox_on ); | ||
$skip_persist = false; | ||
} | ||
|
||
// Enable gateway. | ||
if ( ! $settings->has( 'enabled' ) || ! $settings->get( 'enabled' ) ) { | ||
$settings->set( 'enabled', true ); | ||
$skip_persist = false; | ||
} | ||
|
||
foreach ( WC()->payment_gateways->payment_gateways() as $gateway ) { | ||
if ( PayPalGateway::ID === $gateway->id ) { | ||
$gateway->update_option( 'enabled', 'yes' ); | ||
break; | ||
} | ||
} | ||
|
||
// Update settings. | ||
foreach ( $credential_keys as $key ) { | ||
$value = $params[ $key ]; | ||
$env_key = $key . '_' . $params['environment']; | ||
|
||
if ( ! $settings->has( $key ) || ! $settings->has( $env_key ) || $settings->get( $key ) !== $value || $settings->get( $env_key ) !== $value ) { | ||
$settings->set( $key, $value ); | ||
$settings->set( $env_key, $value ); | ||
$skip_persist = false; | ||
} | ||
} | ||
|
||
if ( ! $skip_persist && ! $settings->persist() ) { | ||
return new \WP_Error( | ||
'woocommerce_paypal_payments_credentials_not_saved', | ||
__( 'An error occurred while saving the credentials.', 'woocommerce-paypal-payments' ), | ||
array( | ||
'status' => 500, | ||
) | ||
); | ||
} | ||
|
||
return array(); | ||
} | ||
|
||
/** | ||
* Appends URL parameters stored in this class to a given URL. | ||
* | ||
* @hooked woocommerce_paypal_payments_partner_config_override_return_url - 10 | ||
* @param string $url URL. | ||
* @return string The URL with the stored URL parameters added to it. | ||
*/ | ||
public function add_args_to_return_url( $url ) { | ||
return add_query_arg( $this->return_url_args, $url ); | ||
} | ||
|
||
/** | ||
* Translates an onboarding state to a string. | ||
* | ||
* @param int $state An onboarding state to translate as returned by {@link State} methods. | ||
* @return string A string representing the state: "start", "progressive" or "onboarded". | ||
* @see State::current_state(), State::sandbox_state(), State::production_state(). | ||
*/ | ||
public function get_onboarding_state_name( $state ) { | ||
$name = 'unknown'; | ||
|
||
switch ( absint( $state ) ) { | ||
case State::STATE_START: | ||
$name = 'start'; | ||
break; | ||
case State::STATE_PROGRESSIVE: | ||
$name = 'progressive'; | ||
break; | ||
case State::STATE_ONBOARDED: | ||
$name = 'onboarded'; | ||
break; | ||
default: | ||
break; | ||
|
||
} | ||
|
||
return $name; | ||
} | ||
|
||
/** | ||
* Generates a signup link for onboarding for a given environment and optionally adding certain URL arguments | ||
* to the URL users are redirected after completing the onboarding flow. | ||
* | ||
* @param string $environment The environment to use. Either 'sandbox' or 'production'. Defaults to 'sandbox'. | ||
* @param array $url_args An array of URL arguments to add to the return URL via {@link add_query_arg()}. | ||
* @return string | ||
*/ | ||
private function generate_signup_link( $environment = 'sandbox', $url_args = array() ) { | ||
$this->return_url_args = ( ! empty( $url_args ) && is_array( $url_args ) ) ? $url_args : array(); | ||
|
||
if ( $this->return_url_args ) { | ||
add_filter( 'woocommerce_paypal_payments_partner_config_override_return_url', array( $this, 'add_args_to_return_url' ) ); | ||
} | ||
|
||
$link = $this->container->get( 'onboarding.render' )->get_signup_link( 'production' === $environment ); | ||
|
||
if ( $this->return_url_args ) { | ||
remove_filter( 'woocommerce_paypal_payments_partner_config_override_return_url', array( $this, 'add_args_to_return_url' ) ); | ||
$this->return_url_args = array(); | ||
} | ||
|
||
return $link; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters