• I can’t find if this plugin supports the following functionality:

    1. If a customer opens a dispute in PayPal – a “on-hold” subscription status should be reflected on the site.
    2. When we make a refund in PayPal, the order on the site must have become “refunded” status.

    We use Woocommerce Subscriptions plugin.

    Regards

Viewing 3 replies - 1 through 3 (of 3 total)
  • Plugin Support Syde Niklas

    (@niklasinpsyde)

    Hi @komapa,

    PayPal Payments supports the WooCommerce Subscriptions plugin: https://woocommerce.com/document/woocommerce-paypal-payments/#subscriptions-faq

    1. If a customer opens a dispute in PayPal – a “on-hold” subscription status should be reflected on the site.

    Subscriptions usually remain active unless the last transaction failed. When a dispute is filed, the WooCommerce order may move to the status “On hold”, but there is no expectation for the subscription to move to “On hold” as well.
    I’m not sure if the order would fail after a successful dispute. But if it fails, then the subscription would also move to “On hold”.

    2. When we make a refund in PayPal, the order on the site must have become “refunded” status.

    The WooCommerce order receives the status “Refunded” when the complete order total (incl. shipping) has been refunded. This can be done either through the WooCommerce order directly or from the PayPal dashboard.
    Upon partial refunds, the WooCommerce order retains the previous status.

    Kind regards,
    Niklas

    Thread Starter Yordan Milenkov

    (@komapa)

    I create CustomerDisputeCreated.php

    And some changes in services.php

    But nothing happens, no logs, no errors…

    What’s wrong?

    
    declare(strict_types=1);
    
    namespace WooCommerce\PayPalCommerce\Webhooks\Handler;
    
    use Psr\Log\LoggerInterface;
    use WP_REST_Request;
    use WP_REST_Response;
    
    /**
     * Class PaymentCaptureCompleted
     */
    class CustomerDisputeCreated implements RequestHandler {
    
    	use PrefixTrait;
    
    	/**
    	 * The logger.
    	 *
    	 * @var LoggerInterface
    	 */
    	private $logger;
    
    	/**
    	 * PaymentCaptureCompleted constructor.
    	 *
    	 * @param LoggerInterface $logger The logger.
    	 */
    	public function __construct(
    		LoggerInterface $logger
    	) {
    		$this->logger = $logger;
    	}
    
    	/**
    	 * The event types a handler handles.
    	 *
    	 * @return string[]
    	 */
    	public function event_types(): array {
    		return array( 'CUSTOMER.DISPUTE.CREATED' );
    	}
    
    	/**
    	 * Whether a handler is responsible for a given request or not.
    	 *
    	 * @param \WP_REST_Request $request The request.
    	 *
    	 * @return bool
    	 */
    	public function responsible_for_request( \WP_REST_Request $request ): bool {
    		return in_array( $request['event_type'], $this->event_types(), true );
    	}
    
    	/**
    	 * Responsible for handling the request.
    	 *
    	 * @param WP_REST_Request $request The request.
    	 *
    	 * @return WP_REST_Response
    	 */
    	public function handle_request( WP_REST_Request $request ): WP_REST_Response {
    		
    		
    		$response = array( 'success' => false );
    		
    		
    		$order_id = $request['resource'] !== null && isset( $request['resource']['disputed_transactions'][0]['custom'] )
    			? $this->sanitize_custom_id( $request['resource']['disputed_transactions'][0]['custom'] )
    			: 0;
    		if ( ! $order_id ) {
    			$message = sprintf(
    			// translators: %s is the PayPal webhook Id.
    				__(
    					'No order for webhook event %s was found.',
    					'woocommerce-paypal-payments'
    				),
    				$request['id'] !== null && isset( $request['id'] ) ? $request['id'] : ''
    			);
    			$this->logger->log(
    				'warning',
    				$message,
    				array(
    					'request' => $request,
    				)
    			);
    			$response['message'] = $message;
    			return new WP_REST_Response( $response );
    		}
    
    		$resource = $request['resource'];
    		if ( ! is_array( $resource ) ) {
    			$message = 'Resource data not found in webhook request.';
    			$this->logger->warning( $message, array( 'request' => $request ) );
    			$response['message'] = $message;
    			return new WP_REST_Response( $response );
    		}
    		
    		$wc_order = wc_get_order( $order_id );
    		
    		if ( ! is_a( $wc_order, \WC_Order::class ) ) {
    			$message = sprintf(
    				'WC order for PayPal ID %s not found.',
    				$request['resource'] !== null && isset( $request['resource']['id'] ) ? $request['resource']['id'] : ''
    			);
    
    			$this->logger->warning( $message );
    
    			$response['message'] = $message;
    			return new WP_REST_Response( $response );
    		}
    
    		if ( $wc_order->get_status() === 'completed' ) {
    			$wc_order->update_status( 'on-hold', __( 'The order has been held because the customer has opened a dispute in PayPal.' ) );
    		
    
    				$subscriptions = wcs_get_subscriptions_for_order( $order_id );
    				if($subscriptions){
    					foreach ( $subscriptions as $subscription_id => $subscription ) {
    						$subscription->update_status( 'on-hold', __( 'The subscription has been held because the customer has opened a dispute in PayPal.' )  );
    
    					}
    				}
    
    		}
    		
    		
    		$response['success'] = true;
    		return new WP_REST_Response( $response );
    	}
    }
    Plugin Support Syde Niklas

    (@niklasinpsyde)

    Hi @komapa,

    Apologies for getting back to you just now.

    I checked back with the team and there is currently no dedicated handling for disputes. I can’t pinpoint what may be missing in the code you provided, but we are looking into integrating this with one of the next updates. It probably won’t be the next January update yet, but likely the following one.

    Kind regards,
    Niklas

Viewing 3 replies - 1 through 3 (of 3 total)
  • The topic ‘PayPal dispute callback’ is closed to new replies.