mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-05 08:59:14 +08:00
Merge pull request #1578 from woocommerce/PCP-1512-pay-pal-fee-and-pay-pal-payout-do-not-change-on-order-if-we-do-partial-refund
PayPal fee and PayPal Payout do not change on order if we do partial refund (1512)
This commit is contained in:
commit
2571d31ad8
28 changed files with 1508 additions and 81 deletions
|
@ -19,6 +19,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
||||||
use WooCommerce\PayPalCommerce\PPCP;
|
use WooCommerce\PayPalCommerce\PPCP;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Helper\RefundFeesUpdater;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor;
|
use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor;
|
use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor;
|
||||||
|
|
||||||
|
@ -107,3 +108,14 @@ function ppcp_void_order( WC_Order $wc_order ): void {
|
||||||
|
|
||||||
$refund_processor->void( $order );
|
$refund_processor->void( $order );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the PayPal refund fees totals on an order.
|
||||||
|
*
|
||||||
|
* @param WC_Order $wc_order The WC order.
|
||||||
|
*/
|
||||||
|
function ppcp_update_order_refund_fees( WC_Order $wc_order ): void {
|
||||||
|
$updater = PPCP::container()->get( 'wcgateway.helper.refund-fees-updater' );
|
||||||
|
assert( $updater instanceof RefundFeesUpdater );
|
||||||
|
$updater->update( $wc_order );
|
||||||
|
}
|
||||||
|
|
|
@ -12,10 +12,14 @@ namespace WooCommerce\PayPalCommerce\ApiClient;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingSubscriptions;
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingSubscriptions;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\CatalogProducts;
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\CatalogProducts;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingPlans;
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingPlans;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerPayableBreakdown;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\BillingCycleFactory;
|
use WooCommerce\PayPalCommerce\ApiClient\Factory\BillingCycleFactory;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentPreferencesFactory;
|
use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentPreferencesFactory;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Factory\RefundFactory;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PlanFactory;
|
use WooCommerce\PayPalCommerce\ApiClient\Factory\PlanFactory;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\ProductFactory;
|
use WooCommerce\PayPalCommerce\ApiClient\Factory\ProductFactory;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Factory\RefundPayerFactory;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Factory\SellerPayableBreakdownFactory;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\ShippingOptionFactory;
|
use WooCommerce\PayPalCommerce\ApiClient\Factory\ShippingOptionFactory;
|
||||||
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
||||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||||
|
@ -289,6 +293,14 @@ return array(
|
||||||
$container->get( 'api.factory.fraud-processor-response' )
|
$container->get( 'api.factory.fraud-processor-response' )
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
'api.factory.refund' => static function ( ContainerInterface $container ): RefundFactory {
|
||||||
|
$amount_factory = $container->get( 'api.factory.amount' );
|
||||||
|
return new RefundFactory(
|
||||||
|
$amount_factory,
|
||||||
|
$container->get( 'api.factory.seller-payable-breakdown' ),
|
||||||
|
$container->get( 'api.factory.refund_payer' )
|
||||||
|
);
|
||||||
|
},
|
||||||
'api.factory.purchase-unit' => static function ( ContainerInterface $container ): PurchaseUnitFactory {
|
'api.factory.purchase-unit' => static function ( ContainerInterface $container ): PurchaseUnitFactory {
|
||||||
|
|
||||||
$amount_factory = $container->get( 'api.factory.amount' );
|
$amount_factory = $container->get( 'api.factory.amount' );
|
||||||
|
@ -351,6 +363,9 @@ return array(
|
||||||
$address_factory = $container->get( 'api.factory.address' );
|
$address_factory = $container->get( 'api.factory.address' );
|
||||||
return new PayerFactory( $address_factory );
|
return new PayerFactory( $address_factory );
|
||||||
},
|
},
|
||||||
|
'api.factory.refund_payer' => static function ( ContainerInterface $container ): RefundPayerFactory {
|
||||||
|
return new RefundPayerFactory();
|
||||||
|
},
|
||||||
'api.factory.address' => static function ( ContainerInterface $container ): AddressFactory {
|
'api.factory.address' => static function ( ContainerInterface $container ): AddressFactory {
|
||||||
return new AddressFactory();
|
return new AddressFactory();
|
||||||
},
|
},
|
||||||
|
@ -374,7 +389,8 @@ return array(
|
||||||
'api.factory.payments' => static function ( ContainerInterface $container ): PaymentsFactory {
|
'api.factory.payments' => static function ( ContainerInterface $container ): PaymentsFactory {
|
||||||
$authorizations_factory = $container->get( 'api.factory.authorization' );
|
$authorizations_factory = $container->get( 'api.factory.authorization' );
|
||||||
$capture_factory = $container->get( 'api.factory.capture' );
|
$capture_factory = $container->get( 'api.factory.capture' );
|
||||||
return new PaymentsFactory( $authorizations_factory, $capture_factory );
|
$refund_factory = $container->get( 'api.factory.refund' );
|
||||||
|
return new PaymentsFactory( $authorizations_factory, $capture_factory, $refund_factory );
|
||||||
},
|
},
|
||||||
'api.factory.authorization' => static function ( ContainerInterface $container ): AuthorizationFactory {
|
'api.factory.authorization' => static function ( ContainerInterface $container ): AuthorizationFactory {
|
||||||
return new AuthorizationFactory();
|
return new AuthorizationFactory();
|
||||||
|
@ -395,6 +411,12 @@ return array(
|
||||||
$container->get( 'api.factory.platform-fee' )
|
$container->get( 'api.factory.platform-fee' )
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
'api.factory.seller-payable-breakdown' => static function ( ContainerInterface $container ): SellerPayableBreakdownFactory {
|
||||||
|
return new SellerPayableBreakdownFactory(
|
||||||
|
$container->get( 'api.factory.money' ),
|
||||||
|
$container->get( 'api.factory.platform-fee' )
|
||||||
|
);
|
||||||
|
},
|
||||||
'api.factory.fraud-processor-response' => static function ( ContainerInterface $container ): FraudProcessorResponseFactory {
|
'api.factory.fraud-processor-response' => static function ( ContainerInterface $container ): FraudProcessorResponseFactory {
|
||||||
return new FraudProcessorResponseFactory();
|
return new FraudProcessorResponseFactory();
|
||||||
},
|
},
|
||||||
|
|
|
@ -54,8 +54,6 @@ class BillingPlans {
|
||||||
private $plan_factory;
|
private $plan_factory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The logger.
|
|
||||||
*
|
|
||||||
* The logger.
|
* The logger.
|
||||||
*
|
*
|
||||||
* @var LoggerInterface
|
* @var LoggerInterface
|
||||||
|
|
|
@ -13,7 +13,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Authorization;
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Authorization;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Capture;
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Capture;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Money;
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Money;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Refund;
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\RefundCapture;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\AuthorizationFactory;
|
use WooCommerce\PayPalCommerce\ApiClient\Factory\AuthorizationFactory;
|
||||||
|
@ -196,13 +196,13 @@ class PaymentsEndpoint {
|
||||||
/**
|
/**
|
||||||
* Refunds a payment.
|
* Refunds a payment.
|
||||||
*
|
*
|
||||||
* @param Refund $refund The refund to be processed.
|
* @param RefundCapture $refund The refund to be processed.
|
||||||
*
|
*
|
||||||
* @return string Refund ID.
|
* @return string Refund ID.
|
||||||
* @throws RuntimeException If the request fails.
|
* @throws RuntimeException If the request fails.
|
||||||
* @throws PayPalApiException If the request fails.
|
* @throws PayPalApiException If the request fails.
|
||||||
*/
|
*/
|
||||||
public function refund( Refund $refund ) : string {
|
public function refund( RefundCapture $refund ) : string {
|
||||||
$bearer = $this->bearer->bearer();
|
$bearer = $this->bearer->bearer();
|
||||||
$url = trailingslashit( $this->host ) . 'v2/payments/captures/' . $refund->for_capture()->id() . '/refund';
|
$url = trailingslashit( $this->host ) . 'v2/payments/captures/' . $refund->for_capture()->id() . '/refund';
|
||||||
$args = array(
|
$args = array(
|
||||||
|
|
|
@ -28,13 +28,21 @@ class Payments {
|
||||||
*/
|
*/
|
||||||
private $captures;
|
private $captures;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Refunds.
|
||||||
|
*
|
||||||
|
* @var Refund[]
|
||||||
|
*/
|
||||||
|
private $refunds;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Payments constructor.
|
* Payments constructor.
|
||||||
*
|
*
|
||||||
* @param array $authorizations The Authorizations.
|
* @param array $authorizations The Authorizations.
|
||||||
* @param array $captures The Captures.
|
* @param array $captures The Captures.
|
||||||
|
* @param array $refunds The Refunds.
|
||||||
*/
|
*/
|
||||||
public function __construct( array $authorizations, array $captures ) {
|
public function __construct( array $authorizations, array $captures, array $refunds = array() ) {
|
||||||
foreach ( $authorizations as $key => $authorization ) {
|
foreach ( $authorizations as $key => $authorization ) {
|
||||||
if ( is_a( $authorization, Authorization::class ) ) {
|
if ( is_a( $authorization, Authorization::class ) ) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -47,8 +55,15 @@ class Payments {
|
||||||
}
|
}
|
||||||
unset( $captures[ $key ] );
|
unset( $captures[ $key ] );
|
||||||
}
|
}
|
||||||
|
foreach ( $refunds as $key => $refund ) {
|
||||||
|
if ( is_a( $refund, Refund::class ) ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
unset( $refunds[ $key ] );
|
||||||
|
}
|
||||||
$this->authorizations = $authorizations;
|
$this->authorizations = $authorizations;
|
||||||
$this->captures = $captures;
|
$this->captures = $captures;
|
||||||
|
$this->refunds = $refunds;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,6 +85,12 @@ class Payments {
|
||||||
},
|
},
|
||||||
$this->captures()
|
$this->captures()
|
||||||
),
|
),
|
||||||
|
'refunds' => array_map(
|
||||||
|
static function ( Refund $refund ): array {
|
||||||
|
return $refund->to_array();
|
||||||
|
},
|
||||||
|
$this->refunds()
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,4 +111,13 @@ class Payments {
|
||||||
public function captures(): array {
|
public function captures(): array {
|
||||||
return $this->captures;
|
return $this->captures;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Refunds.
|
||||||
|
*
|
||||||
|
* @return Refund[]
|
||||||
|
**/
|
||||||
|
public function refunds(): array {
|
||||||
|
return $this->refunds;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* The refund object.
|
* The refund entity.
|
||||||
|
*
|
||||||
|
* @link https://developer.paypal.com/docs/api/orders/v2/#definition-refund
|
||||||
*
|
*
|
||||||
* @package WooCommerce\PayPalCommerce\ApiClient\Entity
|
* @package WooCommerce\PayPalCommerce\ApiClient\Entity
|
||||||
*/
|
*/
|
||||||
|
@ -15,11 +17,32 @@ namespace WooCommerce\PayPalCommerce\ApiClient\Entity;
|
||||||
class Refund {
|
class Refund {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Capture.
|
* The ID.
|
||||||
*
|
*
|
||||||
* @var Capture
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $capture;
|
private $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The status.
|
||||||
|
*
|
||||||
|
* @var RefundStatus
|
||||||
|
*/
|
||||||
|
private $status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The amount.
|
||||||
|
*
|
||||||
|
* @var Amount
|
||||||
|
*/
|
||||||
|
private $amount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The detailed breakdown of the refund activity (fees, ...).
|
||||||
|
*
|
||||||
|
* @var SellerPayableBreakdown|null
|
||||||
|
*/
|
||||||
|
private $seller_payable_breakdown;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The invoice id.
|
* The invoice id.
|
||||||
|
@ -29,50 +52,97 @@ class Refund {
|
||||||
private $invoice_id;
|
private $invoice_id;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The note to the payer.
|
* The custom id.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $custom_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The acquirer reference number.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $acquirer_reference_number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The acquirer reference number.
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $note_to_payer;
|
private $note_to_payer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Amount.
|
* The payer of the refund.
|
||||||
*
|
*
|
||||||
* @var Amount|null
|
* @var ?RefundPayer
|
||||||
*/
|
*/
|
||||||
private $amount;
|
private $payer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refund constructor.
|
* Refund constructor.
|
||||||
*
|
*
|
||||||
* @param Capture $capture The capture where the refund is supposed to be applied at.
|
* @param string $id The ID.
|
||||||
* @param string $invoice_id The invoice id.
|
* @param RefundStatus $status The status.
|
||||||
* @param string $note_to_payer The note to the payer.
|
* @param Amount $amount The amount.
|
||||||
* @param Amount|null $amount The Amount.
|
* @param string $invoice_id The invoice id.
|
||||||
|
* @param string $custom_id The custom id.
|
||||||
|
* @param SellerPayableBreakdown|null $seller_payable_breakdown The detailed breakdown of the refund activity (fees, ...).
|
||||||
|
* @param string $acquirer_reference_number The acquirer reference number.
|
||||||
|
* @param string $note_to_payer The note to payer.
|
||||||
|
* @param RefundPayer|null $payer The payer.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
Capture $capture,
|
string $id,
|
||||||
|
RefundStatus $status,
|
||||||
|
Amount $amount,
|
||||||
string $invoice_id,
|
string $invoice_id,
|
||||||
string $note_to_payer = '',
|
string $custom_id,
|
||||||
Amount $amount = null
|
?SellerPayableBreakdown $seller_payable_breakdown,
|
||||||
|
string $acquirer_reference_number,
|
||||||
|
string $note_to_payer,
|
||||||
|
?RefundPayer $payer
|
||||||
) {
|
) {
|
||||||
$this->capture = $capture;
|
$this->id = $id;
|
||||||
$this->invoice_id = $invoice_id;
|
$this->status = $status;
|
||||||
$this->note_to_payer = $note_to_payer;
|
$this->amount = $amount;
|
||||||
$this->amount = $amount;
|
$this->invoice_id = $invoice_id;
|
||||||
|
$this->custom_id = $custom_id;
|
||||||
|
$this->seller_payable_breakdown = $seller_payable_breakdown;
|
||||||
|
$this->acquirer_reference_number = $acquirer_reference_number;
|
||||||
|
$this->note_to_payer = $note_to_payer;
|
||||||
|
$this->payer = $payer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the capture for the refund.
|
* Returns the ID.
|
||||||
*
|
*
|
||||||
* @return Capture
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function for_capture() : Capture {
|
public function id() : string {
|
||||||
return $this->capture;
|
return $this->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the invoice id.
|
* Returns the status.
|
||||||
|
*
|
||||||
|
* @return RefundStatus
|
||||||
|
*/
|
||||||
|
public function status() : RefundStatus {
|
||||||
|
return $this->status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the amount.
|
||||||
|
*
|
||||||
|
* @return Amount
|
||||||
|
*/
|
||||||
|
public function amount() : Amount {
|
||||||
|
return $this->amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the invoice id.
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
@ -81,7 +151,34 @@ class Refund {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the note to the payer.
|
* Returns the custom id.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function custom_id() : string {
|
||||||
|
return $this->custom_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the detailed breakdown of the refund activity (fees, ...).
|
||||||
|
*
|
||||||
|
* @return SellerPayableBreakdown|null
|
||||||
|
*/
|
||||||
|
public function seller_payable_breakdown() : ?SellerPayableBreakdown {
|
||||||
|
return $this->seller_payable_breakdown;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The acquirer reference number.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function acquirer_reference_number() : string {
|
||||||
|
return $this->acquirer_reference_number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The note to payer.
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
@ -90,28 +187,38 @@ class Refund {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Amount.
|
* Returns the refund payer.
|
||||||
*
|
*
|
||||||
* @return Amount|null
|
* @return RefundPayer|null
|
||||||
*/
|
*/
|
||||||
public function amount() {
|
public function payer() : ?RefundPayer {
|
||||||
return $this->amount;
|
return $this->payer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the object as array.
|
* Returns the entity as array.
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function to_array() : array {
|
public function to_array() : array {
|
||||||
$data = array(
|
$data = array(
|
||||||
'invoice_id' => $this->invoice_id(),
|
'id' => $this->id(),
|
||||||
|
'status' => $this->status()->name(),
|
||||||
|
'amount' => $this->amount()->to_array(),
|
||||||
|
'invoice_id' => $this->invoice_id(),
|
||||||
|
'custom_id' => $this->custom_id(),
|
||||||
|
'acquirer_reference_number' => $this->acquirer_reference_number(),
|
||||||
|
'note_to_payer' => (array) $this->note_to_payer(),
|
||||||
);
|
);
|
||||||
if ( $this->note_to_payer() ) {
|
$details = $this->status()->details();
|
||||||
$data['note_to_payer'] = $this->note_to_payer();
|
if ( $details ) {
|
||||||
|
$data['status_details'] = array( 'reason' => $details->reason() );
|
||||||
}
|
}
|
||||||
if ( $this->amount() ) {
|
if ( $this->seller_payable_breakdown ) {
|
||||||
$data['amount'] = $this->amount()->to_array();
|
$data['seller_payable_breakdown'] = $this->seller_payable_breakdown->to_array();
|
||||||
|
}
|
||||||
|
if ( $this->payer ) {
|
||||||
|
$data['payer'] = $this->payer->to_array();
|
||||||
}
|
}
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
118
modules/ppcp-api-client/src/Entity/RefundCapture.php
Normal file
118
modules/ppcp-api-client/src/Entity/RefundCapture.php
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* The refund capture object.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\ApiClient\Entity
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare( strict_types=1 );
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\ApiClient\Entity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class RefundCapture
|
||||||
|
*/
|
||||||
|
class RefundCapture {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Capture.
|
||||||
|
*
|
||||||
|
* @var Capture
|
||||||
|
*/
|
||||||
|
private $capture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The invoice id.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $invoice_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The note to the payer.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $note_to_payer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Amount.
|
||||||
|
*
|
||||||
|
* @var Amount|null
|
||||||
|
*/
|
||||||
|
private $amount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refund constructor.
|
||||||
|
*
|
||||||
|
* @param Capture $capture The capture where the refund is supposed to be applied at.
|
||||||
|
* @param string $invoice_id The invoice id.
|
||||||
|
* @param string $note_to_payer The note to the payer.
|
||||||
|
* @param Amount|null $amount The Amount.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
Capture $capture,
|
||||||
|
string $invoice_id,
|
||||||
|
string $note_to_payer = '',
|
||||||
|
Amount $amount = null
|
||||||
|
) {
|
||||||
|
$this->capture = $capture;
|
||||||
|
$this->invoice_id = $invoice_id;
|
||||||
|
$this->note_to_payer = $note_to_payer;
|
||||||
|
$this->amount = $amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the capture for the refund.
|
||||||
|
*
|
||||||
|
* @return Capture
|
||||||
|
*/
|
||||||
|
public function for_capture() : Capture {
|
||||||
|
return $this->capture;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the invoice id.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function invoice_id() : string {
|
||||||
|
return $this->invoice_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the note to the payer.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function note_to_payer() : string {
|
||||||
|
return $this->note_to_payer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Amount.
|
||||||
|
*
|
||||||
|
* @return Amount|null
|
||||||
|
*/
|
||||||
|
public function amount() {
|
||||||
|
return $this->amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the object as array.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function to_array() : array {
|
||||||
|
$data = array(
|
||||||
|
'invoice_id' => $this->invoice_id(),
|
||||||
|
);
|
||||||
|
if ( $this->note_to_payer() ) {
|
||||||
|
$data['note_to_payer'] = $this->note_to_payer();
|
||||||
|
}
|
||||||
|
if ( $this->amount ) {
|
||||||
|
$data['amount'] = $this->amount->to_array();
|
||||||
|
}
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
}
|
79
modules/ppcp-api-client/src/Entity/RefundPayer.php
Normal file
79
modules/ppcp-api-client/src/Entity/RefundPayer.php
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* The refund payer object.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\ApiClient\Entity
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\ApiClient\Entity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class RefundPayer
|
||||||
|
* The customer who sends the money.
|
||||||
|
*/
|
||||||
|
class RefundPayer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The email address.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $email_address;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The merchant id.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $merchant_id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RefundPayer constructor.
|
||||||
|
*
|
||||||
|
* @param string $email_address The email.
|
||||||
|
* @param string $merchant_id The merchant id.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
string $email_address,
|
||||||
|
string $merchant_id
|
||||||
|
) {
|
||||||
|
|
||||||
|
$this->email_address = $email_address;
|
||||||
|
$this->merchant_id = $merchant_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the email address.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function email_address(): string {
|
||||||
|
return $this->email_address;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the merchant id.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function merchant_id(): string {
|
||||||
|
return $this->merchant_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the object as array.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function to_array() {
|
||||||
|
$payer = array(
|
||||||
|
'email_address' => $this->email_address(),
|
||||||
|
);
|
||||||
|
if ( $this->merchant_id ) {
|
||||||
|
$payer['merchant_id'] = $this->merchant_id();
|
||||||
|
}
|
||||||
|
return $payer;
|
||||||
|
}
|
||||||
|
}
|
77
modules/ppcp-api-client/src/Entity/RefundStatus.php
Normal file
77
modules/ppcp-api-client/src/Entity/RefundStatus.php
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* The RefundStatus object.
|
||||||
|
*
|
||||||
|
* @see https://developer.paypal.com/docs/api/orders/v2/#definition-refund_status
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\ApiClient\Entity
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\ApiClient\Entity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class RefundStatus
|
||||||
|
*/
|
||||||
|
class RefundStatus {
|
||||||
|
|
||||||
|
const COMPLETED = 'COMPLETED';
|
||||||
|
const CANCELLED = 'CANCELLED';
|
||||||
|
const FAILED = 'FAILED';
|
||||||
|
const PENDING = 'PENDING';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The status.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The details.
|
||||||
|
*
|
||||||
|
* @var RefundStatusDetails|null
|
||||||
|
*/
|
||||||
|
private $details;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RefundStatus constructor.
|
||||||
|
*
|
||||||
|
* @param string $status The status.
|
||||||
|
* @param RefundStatusDetails|null $details The details.
|
||||||
|
*/
|
||||||
|
public function __construct( string $status, ?RefundStatusDetails $details = null ) {
|
||||||
|
$this->status = $status;
|
||||||
|
$this->details = $details;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares the current status with a given one.
|
||||||
|
*
|
||||||
|
* @param string $status The status to compare with.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function is( string $status ): bool {
|
||||||
|
return $this->status === $status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the status.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function name(): string {
|
||||||
|
return $this->status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the details.
|
||||||
|
*
|
||||||
|
* @return RefundStatusDetails|null
|
||||||
|
*/
|
||||||
|
public function details(): ?RefundStatusDetails {
|
||||||
|
return $this->details;
|
||||||
|
}
|
||||||
|
}
|
71
modules/ppcp-api-client/src/Entity/RefundStatusDetails.php
Normal file
71
modules/ppcp-api-client/src/Entity/RefundStatusDetails.php
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* The RefundStatusDetails object.
|
||||||
|
*
|
||||||
|
* @see https://developer.paypal.com/docs/api/payments/v2/#definition-refund_status_details
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\ApiClient\Entity
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\ApiClient\Entity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class RefundStatusDetails
|
||||||
|
*/
|
||||||
|
class RefundStatusDetails {
|
||||||
|
|
||||||
|
const ECHECK = 'ECHECK';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The reason.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $reason;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RefundStatusDetails constructor.
|
||||||
|
*
|
||||||
|
* @param string $reason The reason explaining refund status.
|
||||||
|
*/
|
||||||
|
public function __construct( string $reason ) {
|
||||||
|
$this->reason = $reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares the current reason with a given one.
|
||||||
|
*
|
||||||
|
* @param string $reason The reason to compare with.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function is( string $reason ): bool {
|
||||||
|
return $this->reason === $reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the reason explaining refund status.
|
||||||
|
* One of RefundStatusDetails constants.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function reason(): string {
|
||||||
|
return $this->reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the human-readable reason text explaining refund status.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function text(): string {
|
||||||
|
switch ( $this->reason ) {
|
||||||
|
case self::ECHECK:
|
||||||
|
return __( 'The payer paid by an eCheck that has not yet cleared.', 'woocommerce-paypal-payments' );
|
||||||
|
default:
|
||||||
|
return $this->reason;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
202
modules/ppcp-api-client/src/Entity/SellerPayableBreakdown.php
Normal file
202
modules/ppcp-api-client/src/Entity/SellerPayableBreakdown.php
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* The info about fees and amount that will be paid by the seller.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\ApiClient\Entity
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\ApiClient\Entity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class SellerPayableBreakdown
|
||||||
|
*/
|
||||||
|
class SellerPayableBreakdown {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The amount for this refunded payment in the currency of the transaction.
|
||||||
|
*
|
||||||
|
* @var Money|null
|
||||||
|
*/
|
||||||
|
private $gross_amount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The applicable fee for this refunded payment in the currency of the transaction.
|
||||||
|
*
|
||||||
|
* @var Money|null
|
||||||
|
*/
|
||||||
|
private $paypal_fee;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The applicable fee for this captured payment in the receivable currency.
|
||||||
|
*
|
||||||
|
* Present only in cases the fee is charged in the receivable currency.
|
||||||
|
*
|
||||||
|
* @var Money|null
|
||||||
|
*/
|
||||||
|
private $paypal_fee_in_receivable_currency;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The net amount that the payee receives for this refunded payment in their PayPal account.
|
||||||
|
*
|
||||||
|
* Computed as gross_amount minus the paypal_fee minus the platform_fees.
|
||||||
|
*
|
||||||
|
* @var Money|null
|
||||||
|
*/
|
||||||
|
private $net_amount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The net amount for this refunded payment in the receivable currency.
|
||||||
|
*
|
||||||
|
* @var Money|null
|
||||||
|
*/
|
||||||
|
private $net_amount_in_receivable_currency;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The total amount for this refund.
|
||||||
|
*
|
||||||
|
* @var Money|null
|
||||||
|
*/
|
||||||
|
private $total_refunded_amount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array of platform or partner fees, commissions, or brokerage fees that associated with the captured payment.
|
||||||
|
*
|
||||||
|
* @var PlatformFee[]
|
||||||
|
*/
|
||||||
|
private $platform_fees;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SellerPayableBreakdown constructor.
|
||||||
|
*
|
||||||
|
* @param Money|null $gross_amount The amount for this refunded payment in the currency of the transaction.
|
||||||
|
* @param Money|null $paypal_fee The applicable fee for this refunded payment in the currency of the transaction.
|
||||||
|
* @param Money|null $paypal_fee_in_receivable_currency The applicable fee for this refunded payment in the receivable currency.
|
||||||
|
* @param Money|null $net_amount The net amount that the payee receives for this refunded payment in their PayPal account.
|
||||||
|
* @param Money|null $net_amount_in_receivable_currency The net amount for this refunded payment in the receivable currency.
|
||||||
|
* @param Money|null $total_refunded_amount The total amount for this refund.
|
||||||
|
* @param PlatformFee[] $platform_fees An array of platform or partner fees, commissions, or brokerage fees that associated with the captured payment.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
?Money $gross_amount,
|
||||||
|
?Money $paypal_fee,
|
||||||
|
?Money $paypal_fee_in_receivable_currency,
|
||||||
|
?Money $net_amount,
|
||||||
|
?Money $net_amount_in_receivable_currency,
|
||||||
|
?Money $total_refunded_amount,
|
||||||
|
array $platform_fees
|
||||||
|
) {
|
||||||
|
$this->gross_amount = $gross_amount;
|
||||||
|
$this->paypal_fee = $paypal_fee;
|
||||||
|
$this->paypal_fee_in_receivable_currency = $paypal_fee_in_receivable_currency;
|
||||||
|
$this->net_amount = $net_amount;
|
||||||
|
$this->net_amount_in_receivable_currency = $net_amount_in_receivable_currency;
|
||||||
|
$this->total_refunded_amount = $total_refunded_amount;
|
||||||
|
$this->platform_fees = $platform_fees;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The amount for this refunded payment in the currency of the transaction.
|
||||||
|
*
|
||||||
|
* @return Money|null
|
||||||
|
*/
|
||||||
|
public function gross_amount(): ?Money {
|
||||||
|
return $this->gross_amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The applicable fee for this refunded payment in the currency of the transaction.
|
||||||
|
*
|
||||||
|
* @return Money|null
|
||||||
|
*/
|
||||||
|
public function paypal_fee(): ?Money {
|
||||||
|
return $this->paypal_fee;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The applicable fee for this refunded payment in the receivable currency.
|
||||||
|
*
|
||||||
|
* Present only in cases the fee is charged in the receivable currency.
|
||||||
|
*
|
||||||
|
* @return Money|null
|
||||||
|
*/
|
||||||
|
public function paypal_fee_in_receivable_currency(): ?Money {
|
||||||
|
return $this->paypal_fee_in_receivable_currency;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The net amount that the payee receives for this refunded payment in their PayPal account.
|
||||||
|
*
|
||||||
|
* Computed as gross_amount minus the paypal_fee minus the platform_fees.
|
||||||
|
*
|
||||||
|
* @return Money|null
|
||||||
|
*/
|
||||||
|
public function net_amount(): ?Money {
|
||||||
|
return $this->net_amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The net amount for this refunded payment in the receivable currency.
|
||||||
|
*
|
||||||
|
* @return Money|null
|
||||||
|
*/
|
||||||
|
public function net_amount_in_receivable_currency(): ?Money {
|
||||||
|
return $this->net_amount_in_receivable_currency;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The total amount for this refund.
|
||||||
|
*
|
||||||
|
* @return Money|null
|
||||||
|
*/
|
||||||
|
public function total_refunded_amount(): ?Money {
|
||||||
|
return $this->total_refunded_amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An array of platform or partner fees, commissions, or brokerage fees that associated with the refunded payment.
|
||||||
|
*
|
||||||
|
* @return PlatformFee[]
|
||||||
|
*/
|
||||||
|
public function platform_fees(): array {
|
||||||
|
return $this->platform_fees;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the object as array.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function to_array(): array {
|
||||||
|
$data = array();
|
||||||
|
if ( $this->gross_amount ) {
|
||||||
|
$data['gross_amount'] = $this->gross_amount->to_array();
|
||||||
|
}
|
||||||
|
if ( $this->paypal_fee ) {
|
||||||
|
$data['paypal_fee'] = $this->paypal_fee->to_array();
|
||||||
|
}
|
||||||
|
if ( $this->paypal_fee_in_receivable_currency ) {
|
||||||
|
$data['paypal_fee_in_receivable_currency'] = $this->paypal_fee_in_receivable_currency->to_array();
|
||||||
|
}
|
||||||
|
if ( $this->net_amount ) {
|
||||||
|
$data['net_amount'] = $this->net_amount->to_array();
|
||||||
|
}
|
||||||
|
if ( $this->net_amount_in_receivable_currency ) {
|
||||||
|
$data['net_amount_in_receivable_currency'] = $this->net_amount_in_receivable_currency->to_array();
|
||||||
|
}
|
||||||
|
if ( $this->total_refunded_amount ) {
|
||||||
|
$data['total_refunded_amount'] = $this->total_refunded_amount->to_array();
|
||||||
|
}
|
||||||
|
if ( $this->platform_fees ) {
|
||||||
|
$data['platform_fees'] = array_map(
|
||||||
|
function ( PlatformFee $fee ) {
|
||||||
|
return $fee->to_array();
|
||||||
|
},
|
||||||
|
$this->platform_fees
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ namespace WooCommerce\PayPalCommerce\ApiClient\Factory;
|
||||||
|
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Authorization;
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Authorization;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Capture;
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Capture;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Refund;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Payments;
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Payments;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,19 +33,29 @@ class PaymentsFactory {
|
||||||
*/
|
*/
|
||||||
private $capture_factory;
|
private $capture_factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Refund factory.
|
||||||
|
*
|
||||||
|
* @var RefundFactory
|
||||||
|
*/
|
||||||
|
private $refund_factory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PaymentsFactory constructor.
|
* PaymentsFactory constructor.
|
||||||
*
|
*
|
||||||
* @param AuthorizationFactory $authorization_factory The Authorization factory.
|
* @param AuthorizationFactory $authorization_factory The Authorization factory.
|
||||||
* @param CaptureFactory $capture_factory The Capture factory.
|
* @param CaptureFactory $capture_factory The Capture factory.
|
||||||
|
* @param RefundFactory $refund_factory The Refund factory.
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
AuthorizationFactory $authorization_factory,
|
AuthorizationFactory $authorization_factory,
|
||||||
CaptureFactory $capture_factory
|
CaptureFactory $capture_factory,
|
||||||
|
RefundFactory $refund_factory
|
||||||
) {
|
) {
|
||||||
|
|
||||||
$this->authorization_factory = $authorization_factory;
|
$this->authorization_factory = $authorization_factory;
|
||||||
$this->capture_factory = $capture_factory;
|
$this->capture_factory = $capture_factory;
|
||||||
|
$this->refund_factory = $refund_factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,12 +73,18 @@ class PaymentsFactory {
|
||||||
isset( $data->authorizations ) ? $data->authorizations : array()
|
isset( $data->authorizations ) ? $data->authorizations : array()
|
||||||
);
|
);
|
||||||
$captures = array_map(
|
$captures = array_map(
|
||||||
function ( \stdClass $authorization ): Capture {
|
function ( \stdClass $capture ): Capture {
|
||||||
return $this->capture_factory->from_paypal_response( $authorization );
|
return $this->capture_factory->from_paypal_response( $capture );
|
||||||
},
|
},
|
||||||
isset( $data->captures ) ? $data->captures : array()
|
isset( $data->captures ) ? $data->captures : array()
|
||||||
);
|
);
|
||||||
$payments = new Payments( $authorizations, $captures );
|
$refunds = array_map(
|
||||||
|
function ( \stdClass $refund ): Refund {
|
||||||
|
return $this->refund_factory->from_paypal_response( $refund );
|
||||||
|
},
|
||||||
|
isset( $data->refunds ) ? $data->refunds : array()
|
||||||
|
);
|
||||||
|
$payments = new Payments( $authorizations, $captures, $refunds );
|
||||||
return $payments;
|
return $payments;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
91
modules/ppcp-api-client/src/Factory/RefundFactory.php
Normal file
91
modules/ppcp-api-client/src/Factory/RefundFactory.php
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* The refund factory.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\ApiClient\Factory
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare( strict_types=1 );
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\ApiClient\Factory;
|
||||||
|
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Refund;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\RefundStatus;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\RefundStatusDetails;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class RefundFactory
|
||||||
|
*/
|
||||||
|
class RefundFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Amount factory.
|
||||||
|
*
|
||||||
|
* @var AmountFactory
|
||||||
|
*/
|
||||||
|
private $amount_factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The SellerPayableBreakdownFactory factory.
|
||||||
|
*
|
||||||
|
* @var SellerPayableBreakdownFactory
|
||||||
|
*/
|
||||||
|
private $seller_payable_breakdown_factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The RefundPayerFactory factory.
|
||||||
|
*
|
||||||
|
* @var RefundPayerFactory
|
||||||
|
*/
|
||||||
|
private $refund_payer_factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RefundFactory constructor.
|
||||||
|
*
|
||||||
|
* @param AmountFactory $amount_factory The amount factory.
|
||||||
|
* @param SellerPayableBreakdownFactory $seller_payable_breakdown_factory The payable breakdown factory.
|
||||||
|
* @param RefundPayerFactory $refund_payer_factory The payer breakdown factory.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
AmountFactory $amount_factory,
|
||||||
|
SellerPayableBreakdownFactory $seller_payable_breakdown_factory,
|
||||||
|
RefundPayerFactory $refund_payer_factory
|
||||||
|
) {
|
||||||
|
$this->amount_factory = $amount_factory;
|
||||||
|
$this->seller_payable_breakdown_factory = $seller_payable_breakdown_factory;
|
||||||
|
$this->refund_payer_factory = $refund_payer_factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the refund object based off the PayPal response.
|
||||||
|
*
|
||||||
|
* @param \stdClass $data The PayPal response.
|
||||||
|
*
|
||||||
|
* @return Refund
|
||||||
|
*/
|
||||||
|
public function from_paypal_response( \stdClass $data ) : Refund {
|
||||||
|
$reason = $data->status_details->reason ?? null;
|
||||||
|
$seller_payable_breakdown = isset( $data->seller_payable_breakdown ) ?
|
||||||
|
$this->seller_payable_breakdown_factory->from_paypal_response( $data->seller_payable_breakdown )
|
||||||
|
: null;
|
||||||
|
|
||||||
|
$payer = isset( $data->payer ) ?
|
||||||
|
$this->refund_payer_factory->from_paypal_response( $data->payer )
|
||||||
|
: null;
|
||||||
|
|
||||||
|
return new Refund(
|
||||||
|
(string) $data->id,
|
||||||
|
new RefundStatus(
|
||||||
|
(string) $data->status,
|
||||||
|
$reason ? new RefundStatusDetails( $reason ) : null
|
||||||
|
),
|
||||||
|
$this->amount_factory->from_paypal_response( $data->amount ),
|
||||||
|
(string) ( $data->invoice_id ?? '' ),
|
||||||
|
(string) ( $data->custom_id ?? '' ),
|
||||||
|
$seller_payable_breakdown,
|
||||||
|
(string) ( $data->acquirer_reference_number ?? '' ),
|
||||||
|
(string) ( $data->note_to_payer ?? '' ),
|
||||||
|
$payer
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
39
modules/ppcp-api-client/src/Factory/RefundPayerFactory.php
Normal file
39
modules/ppcp-api-client/src/Factory/RefundPayerFactory.php
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* The RefundPayerFactory factory.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\ApiClient\Factory
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\ApiClient\Factory;
|
||||||
|
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Address;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Payer;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\PayerName;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\PayerTaxInfo;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Phone;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\PhoneWithType;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\RefundPayer;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class RefundPayerFactory
|
||||||
|
*/
|
||||||
|
class RefundPayerFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a Refund Payer object based off a PayPal Response.
|
||||||
|
*
|
||||||
|
* @param \stdClass $data The JSON object.
|
||||||
|
*
|
||||||
|
* @return RefundPayer
|
||||||
|
*/
|
||||||
|
public function from_paypal_response( \stdClass $data ): RefundPayer {
|
||||||
|
return new RefundPayer(
|
||||||
|
isset( $data->email_address ) ? $data->email_address : '',
|
||||||
|
isset( $data->merchant_id ) ? $data->merchant_id : ''
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* The SellerPayableBreakdownFactory Factory.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\ApiClient\Factory
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\ApiClient\Factory;
|
||||||
|
|
||||||
|
use stdClass;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\PlatformFee;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerPayableBreakdown;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class SellerPayableBreakdownFactory
|
||||||
|
*/
|
||||||
|
class SellerPayableBreakdownFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Money factory.
|
||||||
|
*
|
||||||
|
* @var MoneyFactory
|
||||||
|
*/
|
||||||
|
private $money_factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The PlatformFee factory.
|
||||||
|
*
|
||||||
|
* @var PlatformFeeFactory
|
||||||
|
*/
|
||||||
|
private $platform_fee_factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SellerPayableBreakdownFactory constructor.
|
||||||
|
*
|
||||||
|
* @param MoneyFactory $money_factory The Money factory.
|
||||||
|
* @param PlatformFeeFactory $platform_fee_factory The PlatformFee factory.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
MoneyFactory $money_factory,
|
||||||
|
PlatformFeeFactory $platform_fee_factory
|
||||||
|
) {
|
||||||
|
$this->money_factory = $money_factory;
|
||||||
|
$this->platform_fee_factory = $platform_fee_factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a SellerPayableBreakdownFactory object based off a PayPal Response.
|
||||||
|
*
|
||||||
|
* @param stdClass $data The JSON object.
|
||||||
|
*
|
||||||
|
* @return SellerPayableBreakdown
|
||||||
|
*/
|
||||||
|
public function from_paypal_response( stdClass $data ): SellerPayableBreakdown {
|
||||||
|
|
||||||
|
$gross_amount = ( isset( $data->gross_amount ) ) ? $this->money_factory->from_paypal_response( $data->gross_amount ) : null;
|
||||||
|
$paypal_fee = ( isset( $data->paypal_fee ) ) ? $this->money_factory->from_paypal_response( $data->paypal_fee ) : null;
|
||||||
|
$paypal_fee_in_receivable_currency = ( isset( $data->paypal_fee_in_receivable_currency ) ) ? $this->money_factory->from_paypal_response( $data->paypal_fee_in_receivable_currency ) : null;
|
||||||
|
$net_amount = ( isset( $data->net_amount ) ) ? $this->money_factory->from_paypal_response( $data->net_amount ) : null;
|
||||||
|
$net_amount_in_receivable_currency = ( isset( $data->net_amount_in_receivable_currency ) ) ? $this->money_factory->from_paypal_response( $data->net_amount_in_receivable_currency ) : null;
|
||||||
|
$total_refunded_amount = ( isset( $data->total_refunded_amount ) ) ? $this->money_factory->from_paypal_response( $data->total_refunded_amount ) : null;
|
||||||
|
$platform_fees = ( isset( $data->platform_fees ) ) ? array_map(
|
||||||
|
function ( stdClass $fee_data ): PlatformFee {
|
||||||
|
return $this->platform_fee_factory->from_paypal_response( $fee_data );
|
||||||
|
},
|
||||||
|
$data->platform_fees
|
||||||
|
) : array();
|
||||||
|
|
||||||
|
return new SellerPayableBreakdown(
|
||||||
|
$gross_amount,
|
||||||
|
$paypal_fee,
|
||||||
|
$paypal_fee_in_receivable_currency,
|
||||||
|
$net_amount,
|
||||||
|
$net_amount_in_receivable_currency,
|
||||||
|
$total_refunded_amount,
|
||||||
|
$platform_fees
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -53,6 +53,7 @@ use WooCommerce\PayPalCommerce\WcGateway\Helper\CheckoutHelper;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Helper\DCCProductStatus;
|
use WooCommerce\PayPalCommerce\WcGateway\Helper\DCCProductStatus;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Helper\PayUponInvoiceHelper;
|
use WooCommerce\PayPalCommerce\WcGateway\Helper\PayUponInvoiceHelper;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Helper\PayUponInvoiceProductStatus;
|
use WooCommerce\PayPalCommerce\WcGateway\Helper\PayUponInvoiceProductStatus;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Helper\RefundFeesUpdater;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Helper\SettingsStatus;
|
use WooCommerce\PayPalCommerce\WcGateway\Helper\SettingsStatus;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Notice\AuthorizeOrderActionNotice;
|
use WooCommerce\PayPalCommerce\WcGateway\Notice\AuthorizeOrderActionNotice;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Notice\ConnectAdminNotice;
|
use WooCommerce\PayPalCommerce\WcGateway\Notice\ConnectAdminNotice;
|
||||||
|
@ -336,10 +337,11 @@ return array(
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
'wcgateway.processor.refunds' => static function ( ContainerInterface $container ): RefundProcessor {
|
'wcgateway.processor.refunds' => static function ( ContainerInterface $container ): RefundProcessor {
|
||||||
$order_endpoint = $container->get( 'api.endpoint.order' );
|
$order_endpoint = $container->get( 'api.endpoint.order' );
|
||||||
$payments_endpoint = $container->get( 'api.endpoint.payments' );
|
$payments_endpoint = $container->get( 'api.endpoint.payments' );
|
||||||
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
$refund_fees_updater = $container->get( 'wcgateway.helper.refund-fees-updater' );
|
||||||
return new RefundProcessor( $order_endpoint, $payments_endpoint, $logger );
|
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
||||||
|
return new RefundProcessor( $order_endpoint, $payments_endpoint, $refund_fees_updater, $logger );
|
||||||
},
|
},
|
||||||
'wcgateway.processor.authorized-payments' => static function ( ContainerInterface $container ): AuthorizedPaymentsProcessor {
|
'wcgateway.processor.authorized-payments' => static function ( ContainerInterface $container ): AuthorizedPaymentsProcessor {
|
||||||
$order_endpoint = $container->get( 'api.endpoint.order' );
|
$order_endpoint = $container->get( 'api.endpoint.order' );
|
||||||
|
@ -1010,6 +1012,12 @@ return array(
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'wcgateway.helper.refund-fees-updater' => static function ( ContainerInterface $container ): RefundFeesUpdater {
|
||||||
|
$order_endpoint = $container->get( 'api.endpoint.order' );
|
||||||
|
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
||||||
|
return new RefundFeesUpdater( $order_endpoint, $logger );
|
||||||
|
},
|
||||||
|
|
||||||
'button.helper.messages-disclaimers' => static function ( ContainerInterface $container ): MessagesDisclaimers {
|
'button.helper.messages-disclaimers' => static function ( ContainerInterface $container ): MessagesDisclaimers {
|
||||||
return new MessagesDisclaimers(
|
return new MessagesDisclaimers(
|
||||||
$container->get( 'api.shop.country' )
|
$container->get( 'api.shop.country' )
|
||||||
|
|
|
@ -24,11 +24,18 @@ class FeesRenderer {
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function render( WC_Order $wc_order ) : string {
|
public function render( WC_Order $wc_order ) : string {
|
||||||
$breakdown = $wc_order->get_meta( PayPalGateway::FEES_META_KEY );
|
$breakdown = $wc_order->get_meta( PayPalGateway::FEES_META_KEY );
|
||||||
|
$refund_breakdown = $wc_order->get_meta( PayPalGateway::REFUND_FEES_META_KEY ) ?: array();
|
||||||
|
|
||||||
if ( ! is_array( $breakdown ) ) {
|
if ( ! is_array( $breakdown ) ) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$refund_fee = $refund_breakdown['paypal_fee'] ?? array();
|
||||||
|
$refund_amount = $refund_breakdown['net_amount'] ?? array();
|
||||||
|
$refund_total = ( $refund_fee['value'] ?? 0 ) + ( $refund_amount['value'] ?? 0 );
|
||||||
|
$refund_currency = ( ( $refund_amount['currency_code'] ?? '' ) === ( $refund_fee['currency_code'] ?? '' ) ) ? ( $refund_amount['currency_code'] ?? '' ) : '';
|
||||||
|
|
||||||
$html = '';
|
$html = '';
|
||||||
|
|
||||||
$fee = $breakdown['paypal_fee'] ?? null;
|
$fee = $breakdown['paypal_fee'] ?? null;
|
||||||
|
@ -42,6 +49,28 @@ class FeesRenderer {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( $refund_fee ) {
|
||||||
|
$html .= $this->render_money_row(
|
||||||
|
__( 'PayPal Refund Fee:', 'woocommerce-paypal-payments' ),
|
||||||
|
__( 'The fee PayPal collects for the refund transactions.', 'woocommerce-paypal-payments' ),
|
||||||
|
$refund_fee['value'],
|
||||||
|
$refund_fee['currency_code'],
|
||||||
|
true,
|
||||||
|
'refunded-total'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $refund_amount ) {
|
||||||
|
$html .= $this->render_money_row(
|
||||||
|
__( 'PayPal Refunded:', 'woocommerce-paypal-payments' ),
|
||||||
|
__( 'The net amount that was refunded.', 'woocommerce-paypal-payments' ),
|
||||||
|
$refund_amount['value'],
|
||||||
|
$refund_amount['currency_code'],
|
||||||
|
true,
|
||||||
|
'refunded-total'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
$net = $breakdown['net_amount'] ?? null;
|
$net = $breakdown['net_amount'] ?? null;
|
||||||
if ( is_array( $net ) ) {
|
if ( is_array( $net ) ) {
|
||||||
$html .= $this->render_money_row(
|
$html .= $this->render_money_row(
|
||||||
|
@ -50,6 +79,15 @@ class FeesRenderer {
|
||||||
$net['value'],
|
$net['value'],
|
||||||
$net['currency_code']
|
$net['currency_code']
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if ( ( $refund_total > 0.0 && $refund_currency === $net['currency_code'] ) ) {
|
||||||
|
$html .= $this->render_money_row(
|
||||||
|
__( 'PayPal Net Total:', 'woocommerce-paypal-payments' ),
|
||||||
|
__( 'The net total that will be credited to your PayPal account minus the refunds.', 'woocommerce-paypal-payments' ),
|
||||||
|
$net['value'] - $refund_total,
|
||||||
|
$net['currency_code']
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $html;
|
return $html;
|
||||||
|
@ -63,9 +101,10 @@ class FeesRenderer {
|
||||||
* @param string|float $value The money value.
|
* @param string|float $value The money value.
|
||||||
* @param string $currency The currency code.
|
* @param string $currency The currency code.
|
||||||
* @param bool $negative Whether to add the minus sign.
|
* @param bool $negative Whether to add the minus sign.
|
||||||
|
* @param string $html_class Html class to add to the elements.
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
private function render_money_row( string $title, string $tooltip, $value, string $currency, bool $negative = false ): string {
|
private function render_money_row( string $title, string $tooltip, $value, string $currency, bool $negative = false, string $html_class = '' ): string {
|
||||||
/**
|
/**
|
||||||
* Bad type hint in WC phpdoc.
|
* Bad type hint in WC phpdoc.
|
||||||
*
|
*
|
||||||
|
@ -73,10 +112,10 @@ class FeesRenderer {
|
||||||
*/
|
*/
|
||||||
return '
|
return '
|
||||||
<tr>
|
<tr>
|
||||||
<td class="label">' . wc_help_tip( $tooltip ) . ' ' . esc_html( $title ) . '
|
<td class="' . trim( 'label ' . $html_class ) . '">' . wc_help_tip( $tooltip ) . ' ' . esc_html( $title ) . '
|
||||||
</td>
|
</td>
|
||||||
<td width="1%"></td>
|
<td width="1%"></td>
|
||||||
<td class="total">
|
<td class="' . trim( 'total ' . $html_class ) . '">
|
||||||
' .
|
' .
|
||||||
( $negative ? ' - ' : '' ) .
|
( $negative ? ' - ' : '' ) .
|
||||||
wc_price( $value, array( 'currency' => $currency ) ) . '
|
wc_price( $value, array( 'currency' => $currency ) ) . '
|
||||||
|
|
|
@ -48,6 +48,7 @@ class PayPalGateway extends \WC_Payment_Gateway {
|
||||||
const ORDER_PAYMENT_MODE_META_KEY = '_ppcp_paypal_payment_mode';
|
const ORDER_PAYMENT_MODE_META_KEY = '_ppcp_paypal_payment_mode';
|
||||||
const ORDER_PAYMENT_SOURCE_META_KEY = '_ppcp_paypal_payment_source';
|
const ORDER_PAYMENT_SOURCE_META_KEY = '_ppcp_paypal_payment_source';
|
||||||
const FEES_META_KEY = '_ppcp_paypal_fees';
|
const FEES_META_KEY = '_ppcp_paypal_fees';
|
||||||
|
const REFUND_FEES_META_KEY = '_ppcp_paypal_refund_fees';
|
||||||
const REFUNDS_META_KEY = '_ppcp_refunds';
|
const REFUNDS_META_KEY = '_ppcp_refunds';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
195
modules/ppcp-wc-gateway/src/Helper/RefundFeesUpdater.php
Normal file
195
modules/ppcp-wc-gateway/src/Helper/RefundFeesUpdater.php
Normal file
|
@ -0,0 +1,195 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* The RefundFeesUpdater helper.
|
||||||
|
*
|
||||||
|
* @package WooCommerce\PayPalCommerce\WcGateway\Helper;
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\WcGateway\Helper;
|
||||||
|
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use WC_Order;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Money;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||||
|
use WP_Comment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CheckoutHelper class.
|
||||||
|
*/
|
||||||
|
class RefundFeesUpdater {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Order Endpoint.
|
||||||
|
*
|
||||||
|
* @var OrderEndpoint
|
||||||
|
*/
|
||||||
|
private $order_endpoint;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The logger.
|
||||||
|
*
|
||||||
|
* @var LoggerInterface
|
||||||
|
*/
|
||||||
|
private $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RefundFeesUpdater constructor.
|
||||||
|
*
|
||||||
|
* @param OrderEndpoint $order_endpoint The Order Endpoint.
|
||||||
|
* @param LoggerInterface $logger The logger.
|
||||||
|
*/
|
||||||
|
public function __construct( OrderEndpoint $order_endpoint, LoggerInterface $logger ) {
|
||||||
|
$this->order_endpoint = $order_endpoint;
|
||||||
|
$this->logger = $logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the fees meta for a given order.
|
||||||
|
*
|
||||||
|
* @param WC_Order $wc_order The WooCommerce order.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function update( WC_Order $wc_order ): void {
|
||||||
|
$paypal_order_id = $wc_order->get_meta( PayPalGateway::ORDER_ID_META_KEY );
|
||||||
|
|
||||||
|
if ( ! $paypal_order_id ) {
|
||||||
|
$this->logger->error(
|
||||||
|
sprintf( 'Failed to update order paypal refund fees. No PayPal order_id. [wc_order: %s]', $wc_order->get_id() )
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->logger->debug(
|
||||||
|
sprintf( 'Updating order paypal refund fees. [wc_order: %s, paypal_order: %s]', $wc_order->get_id(), $paypal_order_id )
|
||||||
|
);
|
||||||
|
|
||||||
|
$paypal_order = $this->order_endpoint->order( $paypal_order_id );
|
||||||
|
$purchase_units = $paypal_order->purchase_units();
|
||||||
|
|
||||||
|
$gross_amount_total = 0.0;
|
||||||
|
$fee_total = 0.0;
|
||||||
|
$net_amount_total = 0.0;
|
||||||
|
$currency_codes = array();
|
||||||
|
$refunds_ids = array();
|
||||||
|
|
||||||
|
foreach ( $purchase_units as $purchase_unit ) {
|
||||||
|
$payments = $purchase_unit->payments();
|
||||||
|
|
||||||
|
if ( ! $payments ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$refunds = $payments->refunds();
|
||||||
|
|
||||||
|
foreach ( $refunds as $refund ) {
|
||||||
|
$breakdown = $refund->seller_payable_breakdown();
|
||||||
|
$refunds_ids[] = $refund->id();
|
||||||
|
|
||||||
|
if ( ! $breakdown ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$gross_amount = $breakdown->gross_amount();
|
||||||
|
if ( $gross_amount ) {
|
||||||
|
$gross_amount_total += $gross_amount->value();
|
||||||
|
$currency_codes[] = $gross_amount->currency_code();
|
||||||
|
}
|
||||||
|
|
||||||
|
$paypal_fee = $breakdown->paypal_fee();
|
||||||
|
if ( $paypal_fee ) {
|
||||||
|
$fee_total += $paypal_fee->value();
|
||||||
|
$currency_codes[] = $paypal_fee->currency_code();
|
||||||
|
}
|
||||||
|
|
||||||
|
$net_amount = $breakdown->net_amount();
|
||||||
|
if ( $net_amount ) {
|
||||||
|
$net_amount_total += $net_amount->value();
|
||||||
|
$currency_codes[] = $net_amount->currency_code();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$currency_codes = array_unique( $currency_codes );
|
||||||
|
|
||||||
|
if ( count( $currency_codes ) > 1 ) {
|
||||||
|
// There are multiple different currencies codes in the refunds.
|
||||||
|
|
||||||
|
$this->logger->warning(
|
||||||
|
sprintf(
|
||||||
|
'Updating order paypal refund fees. Multiple currencies detected. [wc_order: %s, paypal_order: %s, currencies: %s]',
|
||||||
|
$wc_order->get_id(),
|
||||||
|
$paypal_order_id,
|
||||||
|
implode( ',', $currency_codes )
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$wc_order->update_meta_data( PayPalGateway::REFUND_FEES_META_KEY, array() );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$currency_code = current( $currency_codes ) ?: '';
|
||||||
|
|
||||||
|
$meta_data = array(
|
||||||
|
'gross_amount' => ( new Money( $gross_amount_total, $currency_code ) )->to_array(),
|
||||||
|
'paypal_fee' => ( new Money( $fee_total, $currency_code ) )->to_array(),
|
||||||
|
'net_amount' => ( new Money( $net_amount_total, $currency_code ) )->to_array(),
|
||||||
|
);
|
||||||
|
|
||||||
|
$wc_order->update_meta_data( PayPalGateway::REFUND_FEES_META_KEY, $meta_data );
|
||||||
|
$wc_order->save();
|
||||||
|
|
||||||
|
$order_notes = $this->get_order_notes( $wc_order );
|
||||||
|
|
||||||
|
foreach ( $refunds_ids as $refund_id ) {
|
||||||
|
$has_note = false;
|
||||||
|
foreach ( $order_notes as $order_note ) {
|
||||||
|
if ( strpos( $order_note->comment_content, $refund_id ) !== false ) {
|
||||||
|
$has_note = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( ! $has_note ) {
|
||||||
|
$wc_order->add_order_note( sprintf( 'PayPal refund ID: %s', $refund_id ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->logger->debug(
|
||||||
|
sprintf( 'Updated order paypal refund fees. [wc_order: %s, paypal_order: %s]', $wc_order->get_id(), $paypal_order_id )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all order notes
|
||||||
|
* Based on WC_Order::get_customer_order_notes
|
||||||
|
*
|
||||||
|
* @param WC_Order $wc_order The WooCommerce order.
|
||||||
|
* @return WP_Comment[]
|
||||||
|
*/
|
||||||
|
private function get_order_notes( WC_Order $wc_order ): array {
|
||||||
|
$notes = array();
|
||||||
|
$args = array(
|
||||||
|
'post_id' => $wc_order->get_id(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// By default, WooCommerce excludes comments of the comment_type order_note.
|
||||||
|
// We need to remove this filter to get the order notes.
|
||||||
|
remove_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ) );
|
||||||
|
|
||||||
|
$comments = get_comments( $args );
|
||||||
|
|
||||||
|
if ( is_array( $comments ) ) {
|
||||||
|
foreach ( $comments as $comment ) {
|
||||||
|
if ( $comment instanceof WP_Comment ) {
|
||||||
|
$notes[] = $comment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
add_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ) );
|
||||||
|
|
||||||
|
return $notes;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -20,9 +20,10 @@ use WooCommerce\PayPalCommerce\ApiClient\Entity\AuthorizationStatus;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Money;
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Money;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Payments;
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Payments;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Refund;
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\RefundCapture;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Helper\RefundFeesUpdater;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class RefundProcessor
|
* Class RefundProcessor
|
||||||
|
@ -55,18 +56,27 @@ class RefundProcessor {
|
||||||
*/
|
*/
|
||||||
private $logger;
|
private $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The refund fees updater.
|
||||||
|
*
|
||||||
|
* @var RefundFeesUpdater
|
||||||
|
*/
|
||||||
|
private $refund_fees_updater;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RefundProcessor constructor.
|
* RefundProcessor constructor.
|
||||||
*
|
*
|
||||||
* @param OrderEndpoint $order_endpoint The order endpoint.
|
* @param OrderEndpoint $order_endpoint The order endpoint.
|
||||||
* @param PaymentsEndpoint $payments_endpoint The payments endpoint.
|
* @param PaymentsEndpoint $payments_endpoint The payments endpoint.
|
||||||
* @param LoggerInterface $logger The logger.
|
* @param RefundFeesUpdater $refund_fees_updater The refund fees updater.
|
||||||
|
* @param LoggerInterface $logger The logger.
|
||||||
*/
|
*/
|
||||||
public function __construct( OrderEndpoint $order_endpoint, PaymentsEndpoint $payments_endpoint, LoggerInterface $logger ) {
|
public function __construct( OrderEndpoint $order_endpoint, PaymentsEndpoint $payments_endpoint, RefundFeesUpdater $refund_fees_updater, LoggerInterface $logger ) {
|
||||||
|
|
||||||
$this->order_endpoint = $order_endpoint;
|
$this->order_endpoint = $order_endpoint;
|
||||||
$this->payments_endpoint = $payments_endpoint;
|
$this->payments_endpoint = $payments_endpoint;
|
||||||
$this->logger = $logger;
|
$this->refund_fees_updater = $refund_fees_updater;
|
||||||
|
$this->logger = $logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -106,6 +116,7 @@ class RefundProcessor {
|
||||||
$refund_id = $this->refund( $order, $wc_order, $amount, $reason );
|
$refund_id = $this->refund( $order, $wc_order, $amount, $reason );
|
||||||
|
|
||||||
$this->add_refund_to_meta( $wc_order, $refund_id );
|
$this->add_refund_to_meta( $wc_order, $refund_id );
|
||||||
|
$this->refund_fees_updater->update( $wc_order );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case self::REFUND_MODE_VOID:
|
case self::REFUND_MODE_VOID:
|
||||||
|
@ -151,7 +162,7 @@ class RefundProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
$capture = $captures[0];
|
$capture = $captures[0];
|
||||||
$refund = new Refund(
|
$refund = new RefundCapture(
|
||||||
$capture,
|
$capture,
|
||||||
$capture->invoice_id(),
|
$capture->invoice_id(),
|
||||||
$reason,
|
$reason,
|
||||||
|
|
|
@ -80,6 +80,7 @@ return array(
|
||||||
$order_endpoint = $container->get( 'api.endpoint.order' );
|
$order_endpoint = $container->get( 'api.endpoint.order' );
|
||||||
$authorized_payments_processor = $container->get( 'wcgateway.processor.authorized-payments' );
|
$authorized_payments_processor = $container->get( 'wcgateway.processor.authorized-payments' );
|
||||||
$payment_token_factory = $container->get( 'vaulting.payment-token-factory' );
|
$payment_token_factory = $container->get( 'vaulting.payment-token-factory' );
|
||||||
|
$refund_fees_updater = $container->get( 'wcgateway.helper.refund-fees-updater' );
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
new CheckoutOrderApproved(
|
new CheckoutOrderApproved(
|
||||||
|
@ -91,14 +92,14 @@ return array(
|
||||||
),
|
),
|
||||||
new CheckoutOrderCompleted( $logger ),
|
new CheckoutOrderCompleted( $logger ),
|
||||||
new CheckoutPaymentApprovalReversed( $logger ),
|
new CheckoutPaymentApprovalReversed( $logger ),
|
||||||
new PaymentCaptureRefunded( $logger ),
|
new PaymentCaptureRefunded( $logger, $refund_fees_updater ),
|
||||||
new PaymentCaptureReversed( $logger ),
|
new PaymentCaptureReversed( $logger ),
|
||||||
new PaymentCaptureCompleted( $logger, $order_endpoint ),
|
new PaymentCaptureCompleted( $logger, $order_endpoint ),
|
||||||
new VaultPaymentTokenCreated( $logger, $prefix, $authorized_payments_processor, $payment_token_factory ),
|
new VaultPaymentTokenCreated( $logger, $prefix, $authorized_payments_processor, $payment_token_factory ),
|
||||||
new VaultPaymentTokenDeleted( $logger ),
|
new VaultPaymentTokenDeleted( $logger ),
|
||||||
new PaymentCapturePending( $logger ),
|
new PaymentCapturePending( $logger ),
|
||||||
new PaymentSaleCompleted( $logger ),
|
new PaymentSaleCompleted( $logger ),
|
||||||
new PaymentSaleRefunded( $logger ),
|
new PaymentSaleRefunded( $logger, $refund_fees_updater ),
|
||||||
new BillingSubscriptionCancelled( $logger ),
|
new BillingSubscriptionCancelled( $logger ),
|
||||||
new BillingPlanPricingChangeActivated( $logger ),
|
new BillingPlanPricingChangeActivated( $logger ),
|
||||||
new CatalogProductUpdated( $logger ),
|
new CatalogProductUpdated( $logger ),
|
||||||
|
|
|
@ -11,6 +11,7 @@ namespace WooCommerce\PayPalCommerce\Webhooks\Handler;
|
||||||
|
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
use WC_Order;
|
use WC_Order;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Helper\RefundFeesUpdater;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundMetaTrait;
|
use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundMetaTrait;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\TransactionIdHandlingTrait;
|
use WooCommerce\PayPalCommerce\WcGateway\Processor\TransactionIdHandlingTrait;
|
||||||
use WP_Error;
|
use WP_Error;
|
||||||
|
@ -31,13 +32,22 @@ class PaymentCaptureRefunded implements RequestHandler {
|
||||||
*/
|
*/
|
||||||
private $logger;
|
private $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The refund fees updater.
|
||||||
|
*
|
||||||
|
* @var RefundFeesUpdater
|
||||||
|
*/
|
||||||
|
private $refund_fees_updater;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PaymentCaptureRefunded constructor.
|
* PaymentCaptureRefunded constructor.
|
||||||
*
|
*
|
||||||
* @param LoggerInterface $logger The logger.
|
* @param LoggerInterface $logger The logger.
|
||||||
|
* @param RefundFeesUpdater $refund_fees_updater The refund fees updater.
|
||||||
*/
|
*/
|
||||||
public function __construct( LoggerInterface $logger ) {
|
public function __construct( LoggerInterface $logger, RefundFeesUpdater $refund_fees_updater ) {
|
||||||
$this->logger = $logger;
|
$this->logger = $logger;
|
||||||
|
$this->refund_fees_updater = $refund_fees_updater;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -68,9 +78,11 @@ class PaymentCaptureRefunded implements RequestHandler {
|
||||||
* @return WP_REST_Response
|
* @return WP_REST_Response
|
||||||
*/
|
*/
|
||||||
public function handle_request( WP_REST_Request $request ): WP_REST_Response {
|
public function handle_request( WP_REST_Request $request ): WP_REST_Response {
|
||||||
$order_id = isset( $request['resource']['custom_id'] ) ?
|
$resource = ( $request['resource'] ?? array() ) ?: array();
|
||||||
$request['resource']['custom_id'] : 0;
|
|
||||||
$refund_id = (string) ( $request['resource']['id'] ?? '' );
|
$order_id = $resource['custom_id'] ?? 0;
|
||||||
|
$refund_id = (string) ( $resource['id'] ?? '' );
|
||||||
|
|
||||||
if ( ! $order_id ) {
|
if ( ! $order_id ) {
|
||||||
$message = sprintf(
|
$message = sprintf(
|
||||||
'No order for webhook event %s was found.',
|
'No order for webhook event %s was found.',
|
||||||
|
@ -122,6 +134,7 @@ class PaymentCaptureRefunded implements RequestHandler {
|
||||||
if ( $refund_id ) {
|
if ( $refund_id ) {
|
||||||
$this->update_transaction_id( $refund_id, $wc_order, $this->logger );
|
$this->update_transaction_id( $refund_id, $wc_order, $this->logger );
|
||||||
$this->add_refund_to_meta( $wc_order, $refund_id );
|
$this->add_refund_to_meta( $wc_order, $refund_id );
|
||||||
|
$this->refund_fees_updater->update( $wc_order );
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->success_response();
|
return $this->success_response();
|
||||||
|
|
|
@ -10,6 +10,7 @@ declare(strict_types=1);
|
||||||
namespace WooCommerce\PayPalCommerce\Webhooks\Handler;
|
namespace WooCommerce\PayPalCommerce\Webhooks\Handler;
|
||||||
|
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Helper\RefundFeesUpdater;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundMetaTrait;
|
use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundMetaTrait;
|
||||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\TransactionIdHandlingTrait;
|
use WooCommerce\PayPalCommerce\WcGateway\Processor\TransactionIdHandlingTrait;
|
||||||
use WP_Error;
|
use WP_Error;
|
||||||
|
@ -30,13 +31,22 @@ class PaymentSaleRefunded implements RequestHandler {
|
||||||
*/
|
*/
|
||||||
private $logger;
|
private $logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The refund fees updater.
|
||||||
|
*
|
||||||
|
* @var RefundFeesUpdater
|
||||||
|
*/
|
||||||
|
private $refund_fees_updater;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PaymentSaleRefunded constructor.
|
* PaymentSaleRefunded constructor.
|
||||||
*
|
*
|
||||||
* @param LoggerInterface $logger The logger.
|
* @param LoggerInterface $logger The logger.
|
||||||
|
* @param RefundFeesUpdater $refund_fees_updater The refund fees updater.
|
||||||
*/
|
*/
|
||||||
public function __construct( LoggerInterface $logger ) {
|
public function __construct( LoggerInterface $logger, RefundFeesUpdater $refund_fees_updater ) {
|
||||||
$this->logger = $logger;
|
$this->logger = $logger;
|
||||||
|
$this->refund_fees_updater = $refund_fees_updater;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -120,6 +130,7 @@ class PaymentSaleRefunded implements RequestHandler {
|
||||||
|
|
||||||
$this->update_transaction_id( $refund_id, $wc_order, $this->logger );
|
$this->update_transaction_id( $refund_id, $wc_order, $this->logger );
|
||||||
$this->add_refund_to_meta( $wc_order, $refund_id );
|
$this->add_refund_to_meta( $wc_order, $refund_id );
|
||||||
|
$this->refund_fees_updater->update( $wc_order );
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->success_response();
|
return $this->success_response();
|
||||||
|
|
|
@ -208,6 +208,15 @@ class IncomingWebhookEndpoint {
|
||||||
public function handle_request( \WP_REST_Request $request ): \WP_REST_Response {
|
public function handle_request( \WP_REST_Request $request ): \WP_REST_Response {
|
||||||
$event = $this->event_from_request( $request );
|
$event = $this->event_from_request( $request );
|
||||||
|
|
||||||
|
$this->logger->debug(
|
||||||
|
sprintf(
|
||||||
|
'Webhook %s received of type %s and by resource "%s"',
|
||||||
|
$event->id(),
|
||||||
|
$event->event_type(),
|
||||||
|
$event->resource_type()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
$this->last_webhook_event_storage->save( $event );
|
$this->last_webhook_event_storage->save( $event );
|
||||||
|
|
||||||
if ( $this->simulation->is_simulation_event( $event ) ) {
|
if ( $this->simulation->is_simulation_event( $event ) ) {
|
||||||
|
@ -218,11 +227,21 @@ class IncomingWebhookEndpoint {
|
||||||
|
|
||||||
foreach ( $this->handlers as $handler ) {
|
foreach ( $this->handlers as $handler ) {
|
||||||
if ( $handler->responsible_for_request( $request ) ) {
|
if ( $handler->responsible_for_request( $request ) ) {
|
||||||
|
$event_type = ( $handler->event_types() ? current( $handler->event_types() ) : '' ) ?: '';
|
||||||
|
|
||||||
|
$this->logger->debug(
|
||||||
|
sprintf(
|
||||||
|
'Webhook is going to be handled by %s on %s',
|
||||||
|
$event_type,
|
||||||
|
get_class( $handler )
|
||||||
|
)
|
||||||
|
);
|
||||||
$response = $handler->handle_request( $request );
|
$response = $handler->handle_request( $request );
|
||||||
$this->logger->info(
|
$this->logger->info(
|
||||||
sprintf(
|
sprintf(
|
||||||
'Webhook has been handled by %s',
|
'Webhook has been handled by %s on %s',
|
||||||
( $handler->event_types() ) ? current( $handler->event_types() ) : ''
|
$event_type,
|
||||||
|
get_class( $handler )
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
return $response;
|
return $response;
|
||||||
|
|
130
tests/PHPUnit/Api/OrderRefundFeesUpdateTest.php
Normal file
130
tests/PHPUnit/Api/OrderRefundFeesUpdateTest.php
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace WooCommerce\PayPalCommerce\Api;
|
||||||
|
|
||||||
|
use Mockery;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Money;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
||||||
|
use WooCommerce\PayPalCommerce\ModularTestCase;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||||
|
use WooCommerce\PayPalCommerce\WcGateway\Helper\RefundFeesUpdater;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
use WC_Order;
|
||||||
|
use function Brain\Monkey\Functions\when;
|
||||||
|
|
||||||
|
class OrderRefundFeesUpdateTest extends ModularTestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
private $order_endpoint;
|
||||||
|
private $logger;
|
||||||
|
private $refundFeesUpdater;
|
||||||
|
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
$this->order_endpoint = $this->createMock(OrderEndpoint::class);
|
||||||
|
$this->logger = $this->createMock(LoggerInterface::class);
|
||||||
|
$this->refundFeesUpdater = new RefundFeesUpdater($this->order_endpoint, $this->logger);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUpdateWithoutPaypalOrderId(): void
|
||||||
|
{
|
||||||
|
$wc_order_id = 123;
|
||||||
|
|
||||||
|
$wc_order = Mockery::mock(WC_Order::class);
|
||||||
|
$wc_order->expects('get_meta')
|
||||||
|
->with(PayPalGateway::ORDER_ID_META_KEY)
|
||||||
|
->andReturn(null);
|
||||||
|
|
||||||
|
$wc_order->expects('get_id')->andReturn($wc_order_id);
|
||||||
|
|
||||||
|
$this->logger->expects($this->once())
|
||||||
|
->method('error');
|
||||||
|
|
||||||
|
$this->refundFeesUpdater->update($wc_order);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testUpdateWithValidData(): void
|
||||||
|
{
|
||||||
|
$wc_order_id = 123;
|
||||||
|
$paypal_order_id = 'test_order_id';
|
||||||
|
$refund_id = 'XYZ123';
|
||||||
|
$meta_data = [
|
||||||
|
'gross_amount' => ['value' => 10.0, 'currency_code' => 'USD'],
|
||||||
|
'paypal_fee' => ['value' => 7.0, 'currency_code' => 'USD'],
|
||||||
|
'net_amount' => ['value' => 3.0, 'currency_code' => 'USD'],
|
||||||
|
];
|
||||||
|
|
||||||
|
when('get_comments')->justReturn([]);
|
||||||
|
|
||||||
|
$wc_order = Mockery::mock(WC_Order::class);
|
||||||
|
$wc_order->expects('get_meta')
|
||||||
|
->with(PayPalGateway::ORDER_ID_META_KEY)
|
||||||
|
->andReturn($paypal_order_id);
|
||||||
|
|
||||||
|
$wc_order->expects('get_id')
|
||||||
|
->times(3)
|
||||||
|
->andReturn($wc_order_id);
|
||||||
|
|
||||||
|
$wc_order->expects('update_meta_data')
|
||||||
|
->once()
|
||||||
|
->with('_ppcp_paypal_refund_fees', $meta_data);
|
||||||
|
|
||||||
|
$wc_order->expects('add_order_note')
|
||||||
|
->once()
|
||||||
|
->withArgs(function ($arg) use ($refund_id) {
|
||||||
|
return strpos($arg, $refund_id) !== false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$wc_order->expects('save')->once();
|
||||||
|
|
||||||
|
$moneyGross = Mockery::mock(Money::class);
|
||||||
|
$moneyGross->expects('value')->once()->andReturn($meta_data['gross_amount']['value']);
|
||||||
|
$moneyGross->expects('currency_code')->once()->andReturn($meta_data['gross_amount']['currency_code']);
|
||||||
|
|
||||||
|
$moneyFee = Mockery::mock(Money::class);
|
||||||
|
$moneyFee->expects('value')->once()->andReturn($meta_data['paypal_fee']['value']);
|
||||||
|
$moneyFee->expects('currency_code')->once()->andReturn($meta_data['paypal_fee']['currency_code']);
|
||||||
|
|
||||||
|
$moneyNet = Mockery::mock(Money::class);
|
||||||
|
$moneyNet->expects('value')->once()->andReturn($meta_data['net_amount']['value']);
|
||||||
|
$moneyNet->expects('currency_code')->once()->andReturn($meta_data['net_amount']['currency_code']);
|
||||||
|
|
||||||
|
$breakdown = $this->getMockBuilder(\stdClass::class)
|
||||||
|
->addMethods(['gross_amount', 'paypal_fee', 'net_amount'])
|
||||||
|
->getMock();
|
||||||
|
$breakdown->method('gross_amount')->willReturn($moneyGross);
|
||||||
|
$breakdown->method('paypal_fee')->willReturn($moneyFee);
|
||||||
|
$breakdown->method('net_amount')->willReturn($moneyNet);
|
||||||
|
|
||||||
|
$refund = $this->getMockBuilder(\stdClass::class)
|
||||||
|
->addMethods(['id', 'seller_payable_breakdown'])
|
||||||
|
->getMock();
|
||||||
|
$refund->method('id')->willReturn($refund_id);
|
||||||
|
$refund->method('seller_payable_breakdown')->willReturn($breakdown);
|
||||||
|
|
||||||
|
$payments = $this->getMockBuilder(\stdClass::class)
|
||||||
|
->addMethods(['refunds'])
|
||||||
|
->getMock();
|
||||||
|
$payments->method('refunds')->willReturn([$refund]);
|
||||||
|
|
||||||
|
$purchase_unit = $this->getMockBuilder(\stdClass::class)
|
||||||
|
->addMethods(['payments'])
|
||||||
|
->getMock();
|
||||||
|
$purchase_unit->method('payments')->willReturn($payments);
|
||||||
|
|
||||||
|
$paypal_order = Mockery::mock(Order::class);
|
||||||
|
$paypal_order->expects('purchase_units')->andReturn([$purchase_unit]);
|
||||||
|
|
||||||
|
$this->order_endpoint->method('order')->with($paypal_order_id)->willReturn($paypal_order);
|
||||||
|
|
||||||
|
$this->logger->expects($this->exactly(2))
|
||||||
|
->method('debug')
|
||||||
|
->withConsecutive(
|
||||||
|
[$this->stringContains('Updating order paypal refund fees.')],
|
||||||
|
[$this->stringContains('Updated order paypal refund fees.')]
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->refundFeesUpdater->update($wc_order);
|
||||||
|
}
|
||||||
|
}
|
|
@ -43,10 +43,19 @@ class PaymentsTest extends TestCase
|
||||||
'status' => 'CREATED',
|
'status' => 'CREATED',
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
$captures = [$capture];
|
$refund = \Mockery::mock(Refund::class);
|
||||||
$authorizations = [$authorization];
|
$refund->shouldReceive('to_array')->andReturn(
|
||||||
|
[
|
||||||
|
'id' => 'refund',
|
||||||
|
'status' => 'CREATED',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
$testee = new Payments($authorizations, $captures);
|
$authorizations = [$authorization];
|
||||||
|
$captures = [$capture];
|
||||||
|
$refunds = [$refund];
|
||||||
|
|
||||||
|
$testee = new Payments($authorizations, $captures, $refunds);
|
||||||
|
|
||||||
$this->assertEquals(
|
$this->assertEquals(
|
||||||
[
|
[
|
||||||
|
@ -62,6 +71,12 @@ class PaymentsTest extends TestCase
|
||||||
'status' => 'CREATED',
|
'status' => 'CREATED',
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
'refunds' => [
|
||||||
|
[
|
||||||
|
'id' => 'refund',
|
||||||
|
'status' => 'CREATED',
|
||||||
|
],
|
||||||
|
],
|
||||||
],
|
],
|
||||||
$testee->to_array()
|
$testee->to_array()
|
||||||
);
|
);
|
||||||
|
|
|
@ -7,6 +7,7 @@ namespace WooCommerce\PayPalCommerce\ApiClient\Factory;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Authorization;
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Authorization;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Capture;
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Capture;
|
||||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Payments;
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Payments;
|
||||||
|
use WooCommerce\PayPalCommerce\ApiClient\Entity\Refund;
|
||||||
use WooCommerce\PayPalCommerce\TestCase;
|
use WooCommerce\PayPalCommerce\TestCase;
|
||||||
use Mockery;
|
use Mockery;
|
||||||
|
|
||||||
|
@ -18,11 +19,15 @@ class PaymentsFactoryTest extends TestCase
|
||||||
$authorization->shouldReceive('to_array')->andReturn(['id' => 'foo', 'status' => 'CREATED']);
|
$authorization->shouldReceive('to_array')->andReturn(['id' => 'foo', 'status' => 'CREATED']);
|
||||||
$capture = Mockery::mock(Capture::class);
|
$capture = Mockery::mock(Capture::class);
|
||||||
$capture->shouldReceive('to_array')->andReturn(['id' => 'capture', 'status' => 'CREATED']);
|
$capture->shouldReceive('to_array')->andReturn(['id' => 'capture', 'status' => 'CREATED']);
|
||||||
|
$refund = Mockery::mock(Refund::class);
|
||||||
|
$refund->shouldReceive('to_array')->andReturn(['id' => 'refund', 'status' => 'CREATED']);
|
||||||
|
|
||||||
$authorizationsFactory = Mockery::mock(AuthorizationFactory::class);
|
$authorizationsFactory = Mockery::mock(AuthorizationFactory::class);
|
||||||
$authorizationsFactory->shouldReceive('from_paypal_response')->andReturn($authorization);
|
$authorizationsFactory->shouldReceive('from_paypal_response')->andReturn($authorization);
|
||||||
$captureFactory = Mockery::mock(CaptureFactory::class);
|
$captureFactory = Mockery::mock(CaptureFactory::class);
|
||||||
$captureFactory->shouldReceive('from_paypal_response')->andReturn($capture);
|
$captureFactory->shouldReceive('from_paypal_response')->andReturn($capture);
|
||||||
|
$refundFactory = Mockery::mock(RefundFactory::class);
|
||||||
|
$refundFactory->shouldReceive('from_paypal_response')->andReturn($refund);
|
||||||
$response = (object)[
|
$response = (object)[
|
||||||
'authorizations' => [
|
'authorizations' => [
|
||||||
(object)['id' => 'foo', 'status' => 'CREATED'],
|
(object)['id' => 'foo', 'status' => 'CREATED'],
|
||||||
|
@ -30,9 +35,12 @@ class PaymentsFactoryTest extends TestCase
|
||||||
'captures' => [
|
'captures' => [
|
||||||
(object)['id' => 'capture', 'status' => 'CREATED'],
|
(object)['id' => 'capture', 'status' => 'CREATED'],
|
||||||
],
|
],
|
||||||
|
'refunds' => [
|
||||||
|
(object)['id' => 'refund', 'status' => 'CREATED'],
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
$testee = new PaymentsFactory($authorizationsFactory, $captureFactory);
|
$testee = new PaymentsFactory($authorizationsFactory, $captureFactory, $refundFactory);
|
||||||
$result = $testee->from_paypal_response($response);
|
$result = $testee->from_paypal_response($response);
|
||||||
|
|
||||||
$this->assertInstanceOf(Payments::class, $result);
|
$this->assertInstanceOf(Payments::class, $result);
|
||||||
|
@ -44,6 +52,9 @@ class PaymentsFactoryTest extends TestCase
|
||||||
'captures' => [
|
'captures' => [
|
||||||
['id' => 'capture', 'status' => 'CREATED'],
|
['id' => 'capture', 'status' => 'CREATED'],
|
||||||
],
|
],
|
||||||
|
'refunds' => [
|
||||||
|
['id' => 'refund', 'status' => 'CREATED'],
|
||||||
|
],
|
||||||
];
|
];
|
||||||
$this->assertEquals($expectedToArray, $result->to_array());
|
$this->assertEquals($expectedToArray, $result->to_array());
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,11 +43,32 @@ class FeesRendererTest extends TestCase
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$wcOrder->expects('get_meta')
|
||||||
|
->with(PayPalGateway::REFUND_FEES_META_KEY)
|
||||||
|
->andReturn([
|
||||||
|
'gross_amount' => [
|
||||||
|
'currency_code' => 'USD',
|
||||||
|
'value' => '20.52',
|
||||||
|
],
|
||||||
|
'paypal_fee' => [
|
||||||
|
'currency_code' => 'USD',
|
||||||
|
'value' => '0.51',
|
||||||
|
],
|
||||||
|
'net_amount' => [
|
||||||
|
'currency_code' => 'USD',
|
||||||
|
'value' => '50.01',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
$result = $this->renderer->render($wcOrder);
|
$result = $this->renderer->render($wcOrder);
|
||||||
$this->assertStringContainsString('Fee', $result);
|
$this->assertStringContainsString('Fee', $result);
|
||||||
$this->assertStringContainsString('0.41', $result);
|
$this->assertStringContainsString('0.41', $result);
|
||||||
$this->assertStringContainsString('Payout', $result);
|
$this->assertStringContainsString('Payout', $result);
|
||||||
$this->assertStringContainsString('10.01', $result);
|
$this->assertStringContainsString('10.01', $result);
|
||||||
|
$this->assertStringContainsString('PayPal Refund Fee', $result);
|
||||||
|
$this->assertStringContainsString('0.51', $result);
|
||||||
|
$this->assertStringContainsString('PayPal Refund', $result);
|
||||||
|
$this->assertStringContainsString('50.01', $result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testRenderWithoutNet() {
|
public function testRenderWithoutNet() {
|
||||||
|
@ -62,6 +83,10 @@ class FeesRendererTest extends TestCase
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
$wcOrder->expects('get_meta')
|
||||||
|
->with(PayPalGateway::REFUND_FEES_META_KEY)
|
||||||
|
->andReturn([]);
|
||||||
|
|
||||||
$result = $this->renderer->render($wcOrder);
|
$result = $this->renderer->render($wcOrder);
|
||||||
$this->assertStringContainsString('Fee', $result);
|
$this->assertStringContainsString('Fee', $result);
|
||||||
$this->assertStringContainsString('0.41', $result);
|
$this->assertStringContainsString('0.41', $result);
|
||||||
|
@ -78,6 +103,10 @@ class FeesRendererTest extends TestCase
|
||||||
->with(PayPalGateway::FEES_META_KEY)
|
->with(PayPalGateway::FEES_META_KEY)
|
||||||
->andReturn($meta);
|
->andReturn($meta);
|
||||||
|
|
||||||
|
$wcOrder->expects('get_meta')
|
||||||
|
->with(PayPalGateway::REFUND_FEES_META_KEY)
|
||||||
|
->andReturn([]);
|
||||||
|
|
||||||
$this->assertSame('', $this->renderer->render($wcOrder));
|
$this->assertSame('', $this->renderer->render($wcOrder));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue