\WP_REST_Server::CREATABLE, 'callback' => array( $this, 'handle_request' ), 'permission_callback' => array( $this, 'validate_request' ) ) ); } /** * Handles the current request. * * @param \WP_REST_Request $request * * @since 2.11 * @return \WP_REST_Response */ public function handle_request( \WP_REST_Request $request ) { edd_debug_log( sprintf( 'PayPal Commerce webhook endpoint loaded. Mode: %s; Event: %s', ( edd_is_test_mode() ? 'sandbox' : 'live' ), $request->get_param( 'event_type' ) ) ); edd_debug_log( sprintf( 'Payload: %s', json_encode( $this->event ) ) ); // @todo remove try { // We need to match this event to one of our handlers. $events = get_webhook_events(); if ( ! array_key_exists( $request->get_param( 'event_type' ), $events ) ) { throw new \Exception( sprintf( 'Event not registered. Event: %s', esc_html( $request->get_param( 'event_type' ) ) ), 200 ); } $class_name = $events[ $request->get_param( 'event_type' ) ]; if ( ! class_exists( $class_name ) ) { throw new \Exception( sprintf( 'Class %s doesn\'t exist for event type.', $class_name ), 500 ); } /** * Initialize the handler for this event. * * @var PayPal\Webhooks\Events\Webhook_Event $handler */ $handler = new $class_name( $request ); if ( ! method_exists( $handler, 'handle' ) ) { throw new \Exception( sprintf( 'handle() method doesn\'t exist in class %s.', $class_name ), 500 ); } edd_debug_log( sprintf( 'PayPal Commerce Webhook - Passing to handler %s', esc_html( $class_name ) ) ); $handler->handle(); $action_key = sanitize_key( strtolower( str_replace( '.', '_', $request->get_param( 'event_type' ) ) ) ); /** * Triggers once the handler has run successfully. * $action_key is a formatted version of the event type: * - All lowercase * - Full stops `.` replaced with underscores `_` * * Note: This action hook exists so you can execute custom code *after* a handler has run. * If you're registering a custom event, please build a custom handler by extending * the `Webhook_Event` class and not via this hook. * * @param \WP_REST_Request $event * * @since 2.11 */ do_action( 'edd_paypal_webhook_event_' . $action_key, $request ); return new \WP_REST_Response( 'Success', 200 ); } catch ( PayPal\Exceptions\Authentication_Exception $e ) { // Failure with PayPal credentials. edd_debug_log( sprintf( 'PayPal Commerce Webhook - Exiting due to authentication exception. Message: %s', $e->getMessage() ), true ); return new \WP_REST_Response( $e->getMessage(), 403 ); } catch ( PayPal\Exceptions\API_Exception $e ) { // Failure with a PayPal API request. edd_debug_log( sprintf( 'PayPal Commerce Webhook - Failure due to an API exception. Message: %s', $e->getMessage() ) ); return new \WP_REST_Response( $e->getMessage(), 500 ); } catch ( \Exception $e ) { edd_debug_log( sprintf( 'PayPal Commerce - Exiting webhook due to an exception. Message: %s', $e->getMessage() ), true ); $response_code = $e->getCode() > 0 ? $e->getCode() : 500; return new \WP_REST_Response( $e->getMessage(), $response_code ); } } /** * Validates the webhook * * @since 2.11 * @return bool|\WP_Error */ public function validate_request() { if ( ! PayPal\has_rest_api_connection() ) { return new \WP_Error( 'missing_api_credentials', 'API credentials not set.' ); } $this->event = json_decode( file_get_contents( 'php://input' ) ); try { Webhook_Validator::validate_from_request( $this->event ); edd_debug_log( 'PayPal Commerce webhook successfully validated.' ); return true; } catch ( \Exception $e ) { return new \WP_Error( 'validation_failure', $e->getMessage() ); } } } add_action( 'rest_api_init', function () { $handler = new Webhook_Handler(); $handler->register_routes(); } );