mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-05 08:59:14 +08:00
Add API for refunding and voiding orders
This commit is contained in:
parent
70d9cfbea0
commit
5dce62fa78
4 changed files with 300 additions and 41 deletions
|
@ -11,12 +11,14 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Processor;
|
|||
|
||||
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\Amount;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Authorization;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\AuthorizationStatus;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Money;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Order;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Payments;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Refund;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
|
@ -70,7 +72,7 @@ class RefundProcessor {
|
|||
/**
|
||||
* Processes a refund.
|
||||
*
|
||||
* @param \WC_Order $wc_order The WooCommerce order.
|
||||
* @param WC_Order $wc_order The WooCommerce order.
|
||||
* @param float|null $amount The refund amount.
|
||||
* @param string $reason The reason for the refund.
|
||||
*
|
||||
|
@ -78,7 +80,7 @@ class RefundProcessor {
|
|||
*
|
||||
* @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.Missing
|
||||
*/
|
||||
public function process( \WC_Order $wc_order, float $amount = null, string $reason = '' ) : bool {
|
||||
public function process( WC_Order $wc_order, float $amount = null, string $reason = '' ) : bool {
|
||||
try {
|
||||
$order_id = $wc_order->get_meta( PayPalGateway::ORDER_ID_META_KEY );
|
||||
if ( ! $order_id ) {
|
||||
|
@ -87,15 +89,7 @@ class RefundProcessor {
|
|||
|
||||
$order = $this->order_endpoint->order( $order_id );
|
||||
|
||||
$purchase_units = $order->purchase_units();
|
||||
if ( ! $purchase_units ) {
|
||||
throw new RuntimeException( 'No purchase units.' );
|
||||
}
|
||||
|
||||
$payments = $purchase_units[0]->payments();
|
||||
if ( ! $payments ) {
|
||||
throw new RuntimeException( 'No payments.' );
|
||||
}
|
||||
$payments = $this->get_payments( $order );
|
||||
|
||||
$this->logger->debug(
|
||||
sprintf(
|
||||
|
@ -109,39 +103,11 @@ class RefundProcessor {
|
|||
|
||||
switch ( $mode ) {
|
||||
case self::REFUND_MODE_REFUND:
|
||||
$captures = $payments->captures();
|
||||
if ( ! $captures ) {
|
||||
throw new RuntimeException( 'No capture.' );
|
||||
}
|
||||
|
||||
$capture = $captures[0];
|
||||
$refund = new Refund(
|
||||
$capture,
|
||||
$capture->invoice_id(),
|
||||
$reason,
|
||||
new Amount(
|
||||
new Money( $amount, $wc_order->get_currency() )
|
||||
)
|
||||
);
|
||||
$refund_id = $this->payments_endpoint->refund( $refund );
|
||||
|
||||
$this->add_refund_to_meta( $wc_order, $refund_id );
|
||||
$this->refund( $order, $wc_order, $amount, $reason );
|
||||
|
||||
break;
|
||||
case self::REFUND_MODE_VOID:
|
||||
$voidable_authorizations = array_filter(
|
||||
$payments->authorizations(),
|
||||
function ( Authorization $authorization ): bool {
|
||||
return $authorization->is_voidable();
|
||||
}
|
||||
);
|
||||
if ( ! $voidable_authorizations ) {
|
||||
throw new RuntimeException( 'No voidable authorizations.' );
|
||||
}
|
||||
|
||||
foreach ( $voidable_authorizations as $authorization ) {
|
||||
$this->payments_endpoint->void( $authorization );
|
||||
}
|
||||
$this->void( $order );
|
||||
|
||||
$wc_order->set_status( 'refunded' );
|
||||
$wc_order->save();
|
||||
|
@ -158,6 +124,68 @@ class RefundProcessor {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a refund to the PayPal order.
|
||||
*
|
||||
* @param Order $order The PayPal order.
|
||||
* @param WC_Order $wc_order The WooCommerce order.
|
||||
* @param float $amount The refund amount.
|
||||
* @param string $reason The reason for the refund.
|
||||
*
|
||||
* @throws RuntimeException When operation fails.
|
||||
*/
|
||||
public function refund(
|
||||
Order $order,
|
||||
WC_Order $wc_order,
|
||||
float $amount,
|
||||
string $reason = ''
|
||||
): void {
|
||||
$payments = $this->get_payments( $order );
|
||||
|
||||
$captures = $payments->captures();
|
||||
if ( ! $captures ) {
|
||||
throw new RuntimeException( 'No capture.' );
|
||||
}
|
||||
|
||||
$capture = $captures[0];
|
||||
$refund = new Refund(
|
||||
$capture,
|
||||
$capture->invoice_id(),
|
||||
$reason,
|
||||
new Amount(
|
||||
new Money( $amount, $wc_order->get_currency() )
|
||||
)
|
||||
);
|
||||
|
||||
$refund_id = $this->payments_endpoint->refund( $refund );
|
||||
|
||||
$this->add_refund_to_meta( $wc_order, $refund_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Voids the authorization.
|
||||
*
|
||||
* @param Order $order The PayPal order.
|
||||
* @throws RuntimeException When operation fails.
|
||||
*/
|
||||
public function void( Order $order ): void {
|
||||
$payments = $this->get_payments( $order );
|
||||
|
||||
$voidable_authorizations = array_filter(
|
||||
$payments->authorizations(),
|
||||
function ( Authorization $authorization ): bool {
|
||||
return $authorization->is_voidable();
|
||||
}
|
||||
);
|
||||
if ( ! $voidable_authorizations ) {
|
||||
throw new RuntimeException( 'No voidable authorizations.' );
|
||||
}
|
||||
|
||||
foreach ( $voidable_authorizations as $authorization ) {
|
||||
$this->payments_endpoint->void( $authorization );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the refunding mode.
|
||||
*
|
||||
|
@ -181,4 +209,24 @@ class RefundProcessor {
|
|||
|
||||
return self::REFUND_MODE_UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the payments object or throws.
|
||||
*
|
||||
* @param Order $order The order.
|
||||
* @throws RuntimeException When payment not available.
|
||||
*/
|
||||
protected function get_payments( Order $order ): Payments {
|
||||
$purchase_units = $order->purchase_units();
|
||||
if ( ! $purchase_units ) {
|
||||
throw new RuntimeException( 'No purchase units.' );
|
||||
}
|
||||
|
||||
$payments = $purchase_units[0]->payments();
|
||||
if ( ! $payments ) {
|
||||
throw new RuntimeException( 'No payments.' );
|
||||
}
|
||||
|
||||
return $payments;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue