Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Partial capture #484

Merged
merged 6 commits into from
Feb 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* Enhancement - Improve onboarding notice #465
* Enhancement - Add transaction ID to WC order and order note when refund is received #473
* Enhancement - Asset caching may cause bugs on upgrades #501
* Enhancement - Allow partial capture #483

= 1.6.5 - 2022-01-31 =
* Fix - Allow guest users to purchase subscription products from checkout page #422
Expand Down
17 changes: 14 additions & 3 deletions modules/ppcp-api-client/src/Endpoint/PaymentsEndpoint.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Authorization;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Capture;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Money;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Refund;
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
Expand Down Expand Up @@ -146,22 +147,32 @@ public function authorization( string $authorization_id ): Authorization {
/**
* Capture an authorization by a given ID.
*
* @param string $authorization_id The id.
* @param string $authorization_id The id.
* @param Money|null $amount The amount to capture. If not specified, the whole authorized amount is captured.
*
* @return Capture
* @throws RuntimeException If the request fails.
* @throws PayPalApiException If the request fails.
*/
public function capture( string $authorization_id ): Capture {
public function capture( string $authorization_id, ?Money $amount = null ): Capture {
$bearer = $this->bearer->bearer();
$url = trailingslashit( $this->host ) . 'v2/payments/authorizations/' . $authorization_id . '/capture';
$args = array(

$data = array(
'final_capture' => true,
);
if ( $amount ) {
$data['amount'] = $amount->to_array();
}

$args = array(
'method' => 'POST',
'headers' => array(
'Authorization' => 'Bearer ' . $bearer->token(),
'Content-Type' => 'application/json',
'Prefer' => 'return=representation',
),
'body' => wp_json_encode( $data, JSON_FORCE_OBJECT ),
);

$response = $this->request( $url, $args );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@

use Exception;
use Psr\Log\LoggerInterface;
use WC_Order;
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PaymentsEndpoint;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Authorization;
use WooCommerce\PayPalCommerce\ApiClient\Entity\AuthorizationStatus;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Capture;
use WooCommerce\PayPalCommerce\ApiClient\Entity\CaptureStatus;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Money;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
use WooCommerce\PayPalCommerce\WcGateway\Notice\AuthorizeOrderActionNotice;
Expand Down Expand Up @@ -96,11 +98,11 @@ public function __construct(
/**
* Process a WooCommerce order.
*
* @param \WC_Order $wc_order The WooCommerce order.
* @param WC_Order $wc_order The WooCommerce order.
*
* @return string One of the AuthorizedPaymentsProcessor status constants.
*/
public function process( \WC_Order $wc_order ): string {
public function process( WC_Order $wc_order ): string {
$this->captures = array();

try {
Expand All @@ -123,7 +125,7 @@ public function process( \WC_Order $wc_order ): string {
}

try {
$this->capture_authorizations( ...$authorizations );
$this->captures[] = $this->capture_authorization( $wc_order, ...$authorizations );
} catch ( Exception $exception ) {
$this->logger->error( 'Failed to capture authorization: ' . $exception->getMessage() );
return self::FAILED;
Expand All @@ -144,11 +146,11 @@ public function captures(): array {
/**
* Captures an authorized payment for an WooCommerce order.
*
* @param \WC_Order $wc_order The WooCommerce order.
* @param WC_Order $wc_order The WooCommerce order.
*
* @return bool
*/
public function capture_authorized_payment( \WC_Order $wc_order ): bool {
public function capture_authorized_payment( WC_Order $wc_order ): bool {
$result_status = $this->process( $wc_order );
$this->render_authorization_message_for_status( $result_status );

Expand Down Expand Up @@ -211,11 +213,11 @@ private function render_authorization_message_for_status( string $status ): void
/**
* Returns the PayPal order from a given WooCommerce order.
*
* @param \WC_Order $wc_order The WooCommerce order.
* @param WC_Order $wc_order The WooCommerce order.
*
* @return Order
*/
private function paypal_order_from_wc_order( \WC_Order $wc_order ): Order {
private function paypal_order_from_wc_order( WC_Order $wc_order ): Order {
$order_id = $wc_order->get_meta( PayPalGateway::ORDER_ID_META_KEY );
return $this->order_endpoint->order( $order_id );
}
Expand All @@ -239,15 +241,21 @@ private function all_authorizations( Order $order ): array {
}

/**
* Captures the authorizations.
* Captures the authorization.
*
* @param WC_Order $order The order.
* @param Authorization ...$authorizations All authorizations.
* @throws Exception If capture failed.
*/
private function capture_authorizations( Authorization ...$authorizations ) {
private function capture_authorization( WC_Order $order, Authorization ...$authorizations ): Capture {
$uncaptured_authorizations = $this->authorizations_to_capture( ...$authorizations );
foreach ( $uncaptured_authorizations as $authorization ) {
$this->captures[] = $this->payments_endpoint->capture( $authorization->id() );
if ( ! $uncaptured_authorizations ) {
throw new Exception( 'No authorizations to capture.' );
}

$authorization = end( $uncaptured_authorizations );

return $this->payments_endpoint->capture( $authorization->id(), new Money( (float) $order->get_total(), $order->get_currency() ) );
}

/**
Expand Down
1 change: 1 addition & 0 deletions psalm.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -149,5 +149,6 @@
<MixedReturnTypeCoercion errorLevel="info"/>
<MixedStringOffsetAssignment errorLevel="info"/>
<ParamNameMismatch errorLevel="info"/>
<RedundantCastGivenDocblockType errorLevel="info"/>
</issueHandlers>
</psalm>
1 change: 1 addition & 0 deletions readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ Follow the steps below to connect the plugin to your PayPal account:
* Enhancement - Improve onboarding notice #465
* Enhancement - Add transaction ID to WC order and order note when refund is received #473
* Enhancement - Asset caching may cause bugs on upgrades #501
* Enhancement - Allow partial capture #483

= 1.6.5 =
* Fix - Allow guest users to purchase subscription products from checkout page #422
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
use Requests_Utility_CaseInsensitiveDictionary;
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache;
use WooCommerce\PayPalCommerce\ApiClient\TestCase;
use Psr\Log\LoggerInterface;
use Mockery;
use WooCommerce\PayPalCommerce\TestCase;
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
use function Brain\Monkey\Functions\expect;

Expand Down
5 changes: 1 addition & 4 deletions tests/PHPUnit/ApiClient/Endpoint/IdentityTokenTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
use WooCommerce\PayPalCommerce\ApiClient\Repository\CustomerRepository;
use WooCommerce\PayPalCommerce\ApiClient\TestCase;
use Mockery;
use WooCommerce\PayPalCommerce\TestCase;
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
use function Brain\Monkey\Functions\expect;
use function Brain\Monkey\Functions\when;
Expand Down Expand Up @@ -89,7 +89,6 @@ public function testGenerateForCustomerReturnsToken()

expect('is_wp_error')->with($rawResponse)->andReturn(false);
expect('wp_remote_retrieve_response_code')->with($rawResponse)->andReturn(200);
when('wc_print_r')->returnArg();
when('get_user_meta')->justReturn('');

$result = $this->sut->generate_for_user(1);
Expand All @@ -108,7 +107,6 @@ public function testGenerateForCustomerFailsBecauseWpError()
$headers->shouldReceive('getAll');
expect('wp_remote_get')->andReturn(['headers' => $headers,]);
expect('is_wp_error')->andReturn(true);
when('wc_print_r')->returnArg();
$this->logger->shouldReceive('log');
$this->logger->shouldReceive('debug');
$this->settings->shouldReceive('has')->andReturn(true);
Expand All @@ -135,7 +133,6 @@ public function testGenerateForCustomerFailsBecauseResponseCodeIsNot200()
]);
expect('is_wp_error')->andReturn(false);
expect('wp_remote_retrieve_response_code')->andReturn(500);
when('wc_print_r')->returnArg();
$this->logger->shouldReceive('log');
$this->logger->shouldReceive('debug');
$this->settings->shouldReceive('has')->andReturn(true);
Expand Down
3 changes: 1 addition & 2 deletions tests/PHPUnit/ApiClient/Endpoint/OrderEndpointTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@
use WooCommerce\PayPalCommerce\ApiClient\Helper\ErrorResponse;
use WooCommerce\PayPalCommerce\ApiClient\Repository\ApplicationContextRepository;
use WooCommerce\PayPalCommerce\ApiClient\Repository\PayPalRequestIdRepository;
use WooCommerce\PayPalCommerce\ApiClient\TestCase;
use Mockery;
use Psr\Log\LoggerInterface;
use WooCommerce\PayPalCommerce\Subscription\Helper\SubscriptionHelper;
use WooCommerce\PayPalCommerce\TestCase;
use function Brain\Monkey\Functions\expect;
use function Brain\Monkey\Functions\when;

Expand All @@ -38,7 +38,6 @@ class OrderEndpointTest extends TestCase
public function setUp(): void
{
parent::setUp();
when('wc_print_r')->returnArg();

$this->shipping = new Shipping('shipping', new Address('US', 'street', '', 'CA', '', '12345'));
}
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPUnit/ApiClient/Endpoint/OrderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
use WooCommerce\PayPalCommerce\ApiClient\Entity\Payer;
use WooCommerce\PayPalCommerce\ApiClient\Entity\PaymentSource;
use WooCommerce\PayPalCommerce\ApiClient\Entity\PurchaseUnit;
use WooCommerce\PayPalCommerce\ApiClient\TestCase;
use Mockery;
use WooCommerce\PayPalCommerce\TestCase;

class OrderTest extends TestCase
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentTokenFactory;
use WooCommerce\PayPalCommerce\ApiClient\Repository\CustomerRepository;
use WooCommerce\PayPalCommerce\ApiClient\TestCase;
use Mockery;
use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration;
use WooCommerce\PayPalCommerce\TestCase;
use function Brain\Monkey\Functions\expect;

class PaymentTokenEndpointTest extends TestCase
Expand Down
3 changes: 1 addition & 2 deletions tests/PHPUnit/ApiClient/Endpoint/PaymentsEndpointTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,9 @@
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
use WooCommerce\PayPalCommerce\ApiClient\Factory\AuthorizationFactory;
use WooCommerce\PayPalCommerce\ApiClient\Factory\CaptureFactory;
use WooCommerce\PayPalCommerce\ApiClient\TestCase;
use Mockery;

use Psr\Log\LoggerInterface;
use WooCommerce\PayPalCommerce\TestCase;
use function Brain\Monkey\Functions\expect;

class PaymentsEndpointTest extends TestCase
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPUnit/ApiClient/Entity/AddressTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace WooCommerce\PayPalCommerce\ApiClient\Entity;

use WooCommerce\PayPalCommerce\ApiClient\TestCase;
use WooCommerce\PayPalCommerce\TestCase;

class AddressTest extends TestCase
{
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPUnit/ApiClient/Entity/AmountBreakdownTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace WooCommerce\PayPalCommerce\ApiClient\Entity;

use WooCommerce\PayPalCommerce\ApiClient\TestCase;
use WooCommerce\PayPalCommerce\TestCase;
use Mockery;

class AmountBreakdownTest extends TestCase
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPUnit/ApiClient/Entity/AmountTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace WooCommerce\PayPalCommerce\ApiClient\Entity;

use WooCommerce\PayPalCommerce\ApiClient\TestCase;
use WooCommerce\PayPalCommerce\TestCase;
use Mockery;

class AmountTest extends TestCase
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPUnit/ApiClient/Entity/AuthorizationStatusTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace WooCommerce\PayPalCommerce\ApiClient\Entity;

use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
use WooCommerce\PayPalCommerce\ApiClient\TestCase;
use WooCommerce\PayPalCommerce\TestCase;

class AuthorizationStatusTest extends TestCase
{
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPUnit/ApiClient/Entity/AuthorizationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace WooCommerce\PayPalCommerce\ApiClient\Entity;

use WooCommerce\PayPalCommerce\ApiClient\TestCase;
use WooCommerce\PayPalCommerce\TestCase;

class AuthorizationTest extends TestCase
{
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPUnit/ApiClient/Entity/ItemTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace WooCommerce\PayPalCommerce\ApiClient\Entity;

use WooCommerce\PayPalCommerce\ApiClient\TestCase;
use WooCommerce\PayPalCommerce\TestCase;
use Mockery;

class ItemTest extends TestCase
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPUnit/ApiClient/Entity/MoneyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace WooCommerce\PayPalCommerce\ApiClient\Entity;

use WooCommerce\PayPalCommerce\ApiClient\TestCase;
use WooCommerce\PayPalCommerce\TestCase;

class MoneyTest extends TestCase
{
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPUnit/ApiClient/Entity/PayerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace WooCommerce\PayPalCommerce\ApiClient\Entity;

use WooCommerce\PayPalCommerce\ApiClient\TestCase;
use WooCommerce\PayPalCommerce\TestCase;
use Mockery;

class PayerTest extends TestCase
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPUnit/ApiClient/Entity/PaymentsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace WooCommerce\PayPalCommerce\ApiClient\Entity;

use WooCommerce\PayPalCommerce\ApiClient\TestCase;
use WooCommerce\PayPalCommerce\TestCase;

class PaymentsTest extends TestCase
{
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPUnit/ApiClient/Entity/PurchaseUnitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace WooCommerce\PayPalCommerce\ApiClient\Entity;

use WooCommerce\PayPalCommerce\ApiClient\TestCase;
use WooCommerce\PayPalCommerce\TestCase;
use Mockery;

class PurchaseUnitTest extends TestCase
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPUnit/ApiClient/Factory/AddressFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
namespace WooCommerce\PayPalCommerce\ApiClient\Factory;

use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
use WooCommerce\PayPalCommerce\ApiClient\TestCase;
use WooCommerce\PayPalCommerce\TestCase;
use Mockery;

class AddressFactoryTest extends TestCase
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPUnit/ApiClient/Factory/AmountFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
use WooCommerce\PayPalCommerce\ApiClient\Entity\Item;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Money;
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
use WooCommerce\PayPalCommerce\ApiClient\TestCase;
use WooCommerce\PayPalCommerce\TestCase;
use Mockery;
use function Brain\Monkey\Functions\expect;
use function Brain\Monkey\Functions\when;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use WooCommerce\PayPalCommerce\ApiClient\Entity\Authorization;
use WooCommerce\PayPalCommerce\ApiClient\Entity\AuthorizationStatus;
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
use WooCommerce\PayPalCommerce\ApiClient\TestCase;
use WooCommerce\PayPalCommerce\TestCase;

class AuthorizationFactoryTest extends TestCase
{
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPUnit/ApiClient/Factory/ItemFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

use WooCommerce\PayPalCommerce\ApiClient\Entity\Item;
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
use WooCommerce\PayPalCommerce\ApiClient\TestCase;
use WooCommerce\PayPalCommerce\TestCase;
use function Brain\Monkey\Functions\expect;
use function Brain\Monkey\Functions\when;
use Mockery;
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPUnit/ApiClient/Factory/OrderFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use WooCommerce\PayPalCommerce\ApiClient\Entity\PurchaseUnit;
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
use WooCommerce\PayPalCommerce\ApiClient\Repository\ApplicationContextRepository;
use WooCommerce\PayPalCommerce\ApiClient\TestCase;
use WooCommerce\PayPalCommerce\TestCase;
use Mockery;

class OrderFactoryTest extends TestCase
Expand Down
Loading