Capture virtual renewal orders functionality for subscriptions

This commit is contained in:
Narek Zakarian 2022-06-29 16:52:19 +04:00
parent 998a327ebc
commit 90c2a01350
3 changed files with 94 additions and 15 deletions

View file

@ -24,13 +24,17 @@ return array(
$purchase_unit_factory = $container->get( 'api.factory.purchase-unit' );
$payer_factory = $container->get( 'api.factory.payer' );
$environment = $container->get( 'onboarding.environment' );
$settings = $container->get( 'wcgateway.settings' );
$authorized_payments_processor = $container->get( 'wcgateway.processor.authorized-payments' );
return new RenewalHandler(
$logger,
$repository,
$endpoint,
$purchase_unit_factory,
$payer_factory,
$environment
$environment,
$settings,
$authorized_payments_processor
);
},
'subscription.repository.payment-token' => static function ( ContainerInterface $container ): PaymentTokenRepository {

View file

@ -10,16 +10,19 @@ declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\Subscription;
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentToken;
use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory;
use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
use WooCommerce\PayPalCommerce\Onboarding\Environment;
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
use Psr\Log\LoggerInterface;
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor;
use WooCommerce\PayPalCommerce\WcGateway\Processor\OrderMetaTrait;
use WooCommerce\PayPalCommerce\WcGateway\Processor\PaymentsStatusHandlingTrait;
use WooCommerce\PayPalCommerce\WcGateway\Processor\TransactionIdHandlingTrait;
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
/**
* Class RenewalHandler
@ -72,15 +75,31 @@ class RenewalHandler {
*/
protected $environment;
/**
* The settings
*
* @var Settings
*/
protected $settings;
/**
* The processor for authorized payments.
*
* @var AuthorizedPaymentsProcessor
*/
protected $authorized_payments_processor;
/**
* RenewalHandler constructor.
*
* @param LoggerInterface $logger The logger.
* @param PaymentTokenRepository $repository The payment token repository.
* @param OrderEndpoint $order_endpoint The order endpoint.
* @param PurchaseUnitFactory $purchase_unit_factory The purchase unit factory.
* @param PayerFactory $payer_factory The payer factory.
* @param Environment $environment The environment.
* @param LoggerInterface $logger The logger.
* @param PaymentTokenRepository $repository The payment token repository.
* @param OrderEndpoint $order_endpoint The order endpoint.
* @param PurchaseUnitFactory $purchase_unit_factory The purchase unit factory.
* @param PayerFactory $payer_factory The payer factory.
* @param Environment $environment The environment.
* @param Settings $settings The Settings.
* @param AuthorizedPaymentsProcessor $authorized_payments_processor The Authorized Payments Processor.
*/
public function __construct(
LoggerInterface $logger,
@ -88,15 +107,19 @@ class RenewalHandler {
OrderEndpoint $order_endpoint,
PurchaseUnitFactory $purchase_unit_factory,
PayerFactory $payer_factory,
Environment $environment
Environment $environment,
Settings $settings,
AuthorizedPaymentsProcessor $authorized_payments_processor
) {
$this->logger = $logger;
$this->repository = $repository;
$this->order_endpoint = $order_endpoint;
$this->purchase_unit_factory = $purchase_unit_factory;
$this->payer_factory = $payer_factory;
$this->environment = $environment;
$this->logger = $logger;
$this->repository = $repository;
$this->order_endpoint = $order_endpoint;
$this->purchase_unit_factory = $purchase_unit_factory;
$this->payer_factory = $payer_factory;
$this->environment = $environment;
$this->settings = $settings;
$this->authorized_payments_processor = $authorized_payments_processor;
}
/**
@ -163,6 +186,14 @@ class RenewalHandler {
}
$this->handle_new_order_status( $order, $wc_order );
if ( $this->capture_authorized_downloads( $order ) && AuthorizedPaymentsProcessor::SUCCESSFUL === $this->authorized_payments_processor->process( $wc_order ) ) {
$wc_order->add_order_note(
__( 'Payment successfully captured.', 'woocommerce-paypal-payments' )
);
$wc_order->update_meta_data( AuthorizedPaymentsProcessor::CAPTURED_META_KEY, 'true' );
$wc_order->update_status( 'completed' );
}
}
/**
@ -213,4 +244,39 @@ class RenewalHandler {
return current( $tokens );
}
/**
* Returns if an order should be captured immediately.
*
* @param Order $order The PayPal order.
*
* @return bool
* @throws NotFoundException When a setting was not found.
*/
protected function capture_authorized_downloads( Order $order ): bool {
if (
! $this->settings->has( 'capture_for_virtual_only' )
|| ! $this->settings->get( 'capture_for_virtual_only' )
) {
return false;
}
if ( $order->intent() === 'CAPTURE' ) {
return false;
}
/**
* We fetch the order again as the authorize endpoint (from which the Order derives)
* drops the item's category, making it impossible to check, if purchase units contain
* physical goods.
*/
$order = $this->order_endpoint->order( $order->id() );
foreach ( $order->purchase_units() as $unit ) {
if ( $unit->contains_physical_goods() ) {
return false;
}
}
return true;
}
}

View file

@ -22,6 +22,8 @@ use Mockery;
use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration;
use WooCommerce\PayPalCommerce\Vaulting\PaymentTokenRepository;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor;
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
class RenewalHandlerTest extends TestCase
{
@ -45,6 +47,11 @@ class RenewalHandlerTest extends TestCase
$this->purchaseUnitFactory = Mockery::mock(PurchaseUnitFactory::class);
$this->payerFactory = Mockery::mock(PayerFactory::class);
$this->environment = new Environment(new Dictionary([]));
$authorizedPaymentProcessor = Mockery::mock(AuthorizedPaymentsProcessor::class);
$settings = Mockery::mock(Settings::class);
$settings
->shouldReceive('has')
->andReturnFalse();
$this->logger->shouldReceive('error')->andReturnUsing(function ($msg) {
throw new Exception($msg);
@ -57,7 +64,9 @@ class RenewalHandlerTest extends TestCase
$this->orderEndpoint,
$this->purchaseUnitFactory,
$this->payerFactory,
$this->environment
$this->environment,
$settings,
$authorizedPaymentProcessor
);
}