179 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			179 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * Account Status Validator
 | |
|  *
 | |
|  * This validator helps to check the status of a PayPal merchant account
 | |
|  * and ensure it's ready to receive payments. This is used to display
 | |
|  * the connection status on the admin settings page, and also to help
 | |
|  * determine if we should allow the merchant to start processing payments.
 | |
|  *
 | |
|  * @package   easy-digital-downloads
 | |
|  * @copyright Copyright (c) 2021, Sandhills Development, LLC
 | |
|  * @license   GPL2+
 | |
|  * @since     2.11
 | |
|  */
 | |
| 
 | |
| namespace EDD\Gateways\PayPal;
 | |
| 
 | |
| use EDD\Gateways\PayPal;
 | |
| 
 | |
| class AccountStatusValidator {
 | |
| 
 | |
| 	/**
 | |
| 	 * @var bool Whether or not we have REST API credentials.
 | |
| 	 */
 | |
| 	public $has_rest_credentials = false;
 | |
| 
 | |
| 	/**
 | |
| 	 * @var \WP_Error Errors thrown when checking REST API credentials.
 | |
| 	 */
 | |
| 	public $errors_for_credentials;
 | |
| 
 | |
| 	/**
 | |
| 	 * @var array|false Merchant details, if any.
 | |
| 	 */
 | |
| 	public $merchant_details = false;
 | |
| 
 | |
| 	/**
 | |
| 	 * @var \WP_Error Errors thrown when checking merchant account status.
 | |
| 	 */
 | |
| 	public $errors_for_merchant_account;
 | |
| 
 | |
| 	/**
 | |
| 	 * @var null|object Webhook object from the API.
 | |
| 	 */
 | |
| 	public $webhook;
 | |
| 
 | |
| 	/**
 | |
| 	 * @var array Enabled webhook event names.
 | |
| 	 */
 | |
| 	public $enabled_webhook_events = array();
 | |
| 
 | |
| 	/**
 | |
| 	 * @var \WP_Error Errors thrown when checking webhook status.
 | |
| 	 */
 | |
| 	public $errors_for_webhook;
 | |
| 
 | |
| 	/**
 | |
| 	 * @var string Identifier of the connected account -- if available.
 | |
| 	 */
 | |
| 	public $connected_account = '';
 | |
| 
 | |
| 	/**
 | |
| 	 * @var string Current store mode.
 | |
| 	 */
 | |
| 	private $mode;
 | |
| 
 | |
| 	/**
 | |
| 	 * AccountStatusValidator constructor.
 | |
| 	 *
 | |
| 	 * @param string $mode Mode to check (`live` or `sandbox`). If omitted, current store mode is used.
 | |
| 	 */
 | |
| 	public function __construct( $mode = '' ) {
 | |
| 		if ( empty( $mode ) ) {
 | |
| 			$mode = edd_is_test_mode() ? PayPal\API::MODE_SANDBOX : PayPal\API::MODE_LIVE;
 | |
| 		}
 | |
| 		$this->mode = $mode;
 | |
| 
 | |
| 		// Set up base error objects.
 | |
| 		$this->errors_for_credentials      = new \WP_Error();
 | |
| 		$this->errors_for_merchant_account = new \WP_Error();
 | |
| 		$this->errors_for_webhook          = new \WP_Error();
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Checks everything.
 | |
| 	 *
 | |
| 	 * @since 2.11
 | |
| 	 */
 | |
| 	public function check() {
 | |
| 		$this->check_rest();
 | |
| 		$this->check_merchant_account();
 | |
| 		$this->check_webhook();
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Checks for valid REST API credentials.
 | |
| 	 *
 | |
| 	 * @since 2.11
 | |
| 	 */
 | |
| 	public function check_rest() {
 | |
| 		$credentials = array(
 | |
| 			'client_id'     => edd_get_option( 'paypal_' . $this->mode . '_client_id' ),
 | |
| 			'client_secret' => edd_get_option( 'paypal_' . $this->mode . '_client_secret' ),
 | |
| 		);
 | |
| 
 | |
| 		foreach ( $credentials as $credential ) {
 | |
| 			if ( empty( $credential ) ) {
 | |
| 				$this->errors_for_credentials->add( 'no_credentials', __( 'Not connected.', 'easy-digital-downloads' ) );
 | |
| 				break;
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Determines if the merchant account is ready to accept payments.
 | |
| 	 * It's possible (I think) to have valid API credentials ( @see AccountStatusValidator::check_rest() )
 | |
| 	 * but still be unable to start taking payments, such as because your account
 | |
| 	 * email hasn't been confirmed yet.
 | |
| 	 *
 | |
| 	 * @since 2.11
 | |
| 	 */
 | |
| 	public function check_merchant_account() {
 | |
| 		try {
 | |
| 			$this->merchant_details = MerchantAccount::retrieve();
 | |
| 			$this->merchant_details->validate();
 | |
| 
 | |
| 			if ( ! $this->merchant_details->is_account_ready() ) {
 | |
| 				foreach ( $this->merchant_details->get_errors()->get_error_codes() as $code ) {
 | |
| 					$this->errors_for_merchant_account->add( $code, $this->merchant_details->get_errors()->get_error_message( $code ) );
 | |
| 				}
 | |
| 			}
 | |
| 		} catch ( Exceptions\MissingMerchantDetails $e ) {
 | |
| 			$this->errors_for_merchant_account->add( 'missing_merchant_details', __( 'Missing merchant details from PayPal. Please reconnect and make sure you click the button to be redirected back to your site.', 'easy-digital-downloads' ) );
 | |
| 		} catch ( Exceptions\InvalidMerchantDetails $e ) {
 | |
| 			$this->errors_for_merchant_account->add( 'invalid_merchant_details', $e->getMessage() );
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Confirms that the webhook is set up and has all the necessary events registered.
 | |
| 	 *
 | |
| 	 * @since 2.11
 | |
| 	 */
 | |
| 	public function check_webhook() {
 | |
| 		try {
 | |
| 			$this->webhook = Webhooks\get_webhook_details( $this->mode );
 | |
| 			if ( empty( $this->webhook->id ) ) {
 | |
| 				throw new \Exception( __( 'Webhook not configured. Some actions may not work properly.', 'easy-digital-downloads' ) );
 | |
| 			}
 | |
| 
 | |
| 			// Now compare the events to make sure we have them all.
 | |
| 			$expected_events = array_keys( Webhooks\get_webhook_events( $this->mode ) );
 | |
| 
 | |
| 			if ( ! empty( $this->webhook->event_types ) && is_array( $this->webhook->event_types ) ) {
 | |
| 				foreach ( $this->webhook->event_types as $event_type ) {
 | |
| 					if ( ! empty( $event_type->name ) && ! empty( $event_type->status ) && 'ENABLED' === strtoupper( $event_type->status ) ) {
 | |
| 						$this->enabled_webhook_events[] = $event_type->name;
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			$missing_events = array_diff( $expected_events, $this->enabled_webhook_events );
 | |
| 			$number_missing = count( $missing_events );
 | |
| 
 | |
| 			if ( $number_missing ) {
 | |
| 				$this->errors_for_webhook->add( 'missing_events', _n(
 | |
| 					'Webhook is configured but missing an event. Click "Sync Webhook" to correct this.',
 | |
| 					'Webhook is configured but missing events. Click "Sync Webhook" to correct this.',
 | |
| 					$number_missing,
 | |
| 					'easy-digital-downloads'
 | |
| 				) );
 | |
| 			}
 | |
| 		} catch ( \Exception $e ) {
 | |
| 			$this->errors_for_webhook->add( 'webhook_missing', $e->getMessage() );
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| }
 |