mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-05 08:59:14 +08:00
Merge pull request #490 from woocommerce/pcp-307-fee
Add fees to meta and show on the order
This commit is contained in:
commit
df98a7d017
21 changed files with 1152 additions and 59 deletions
|
@ -16,6 +16,8 @@
|
|||
* Enhancement - Add transaction ID to WC order and order note when refund is received #473
|
||||
* Enhancement - Asset caching may cause bugs on upgrades #501
|
||||
* Enhancement - Allow partial capture #483
|
||||
* Enhancement - PayPal Payments doesn't set transaction fee metadata #467
|
||||
* Enhancement - Show PayPal fee information in order #489
|
||||
|
||||
= 1.6.5 - 2022-01-31 =
|
||||
* Fix - Allow guest users to purchase subscription products from checkout page #422
|
||||
|
|
|
@ -26,7 +26,9 @@ use WooCommerce\PayPalCommerce\ApiClient\Factory\AmountFactory;
|
|||
use WooCommerce\PayPalCommerce\ApiClient\Factory\ApplicationContextFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\AuthorizationFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\CaptureFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\ExchangeRateFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\ItemFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\MoneyFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\OrderFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PatchCollectionFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PayeeFactory;
|
||||
|
@ -34,7 +36,9 @@ use WooCommerce\PayPalCommerce\ApiClient\Factory\PayerFactory;
|
|||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentsFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentSourceFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentTokenFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PlatformFeeFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\PurchaseUnitFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\SellerReceivableBreakdownFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\SellerStatusFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\ShippingFactory;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\WebhookEventFactory;
|
||||
|
@ -239,7 +243,10 @@ return array(
|
|||
'api.factory.capture' => static function ( ContainerInterface $container ): CaptureFactory {
|
||||
|
||||
$amount_factory = $container->get( 'api.factory.amount' );
|
||||
return new CaptureFactory( $amount_factory );
|
||||
return new CaptureFactory(
|
||||
$amount_factory,
|
||||
$container->get( 'api.factory.seller-receivable-breakdown' )
|
||||
);
|
||||
},
|
||||
'api.factory.purchase-unit' => static function ( ContainerInterface $container ): PurchaseUnitFactory {
|
||||
|
||||
|
@ -280,9 +287,13 @@ return array(
|
|||
$item_factory = $container->get( 'api.factory.item' );
|
||||
return new AmountFactory(
|
||||
$item_factory,
|
||||
$container->get( 'api.factory.money' ),
|
||||
$container->get( 'api.shop.currency' )
|
||||
);
|
||||
},
|
||||
'api.factory.money' => static function ( ContainerInterface $container ): MoneyFactory {
|
||||
return new MoneyFactory();
|
||||
},
|
||||
'api.factory.payer' => static function ( ContainerInterface $container ): PayerFactory {
|
||||
$address_factory = $container->get( 'api.factory.address' );
|
||||
return new PayerFactory( $address_factory );
|
||||
|
@ -315,6 +326,22 @@ return array(
|
|||
'api.factory.authorization' => static function ( ContainerInterface $container ): AuthorizationFactory {
|
||||
return new AuthorizationFactory();
|
||||
},
|
||||
'api.factory.exchange-rate' => static function ( ContainerInterface $container ): ExchangeRateFactory {
|
||||
return new ExchangeRateFactory();
|
||||
},
|
||||
'api.factory.platform-fee' => static function ( ContainerInterface $container ): PlatformFeeFactory {
|
||||
return new PlatformFeeFactory(
|
||||
$container->get( 'api.factory.money' ),
|
||||
$container->get( 'api.factory.payee' )
|
||||
);
|
||||
},
|
||||
'api.factory.seller-receivable-breakdown' => static function ( ContainerInterface $container ): SellerReceivableBreakdownFactory {
|
||||
return new SellerReceivableBreakdownFactory(
|
||||
$container->get( 'api.factory.money' ),
|
||||
$container->get( 'api.factory.exchange-rate' ),
|
||||
$container->get( 'api.factory.platform-fee' )
|
||||
);
|
||||
},
|
||||
'api.helpers.dccapplies' => static function ( ContainerInterface $container ) : DccApplies {
|
||||
return new DccApplies(
|
||||
$container->get( 'api.dcc-supported-country-currency-matrix' ),
|
||||
|
|
|
@ -51,6 +51,13 @@ class Capture {
|
|||
*/
|
||||
private $seller_protection;
|
||||
|
||||
/**
|
||||
* The detailed breakdown of the capture activity (fees, ...).
|
||||
*
|
||||
* @var SellerReceivableBreakdown|null
|
||||
*/
|
||||
private $seller_receivable_breakdown;
|
||||
|
||||
/**
|
||||
* The invoice id.
|
||||
*
|
||||
|
@ -68,13 +75,14 @@ class Capture {
|
|||
/**
|
||||
* Capture constructor.
|
||||
*
|
||||
* @param string $id The ID.
|
||||
* @param CaptureStatus $status The status.
|
||||
* @param Amount $amount The amount.
|
||||
* @param bool $final_capture The final capture.
|
||||
* @param string $seller_protection The seller protection.
|
||||
* @param string $invoice_id The invoice id.
|
||||
* @param string $custom_id The custom id.
|
||||
* @param string $id The ID.
|
||||
* @param CaptureStatus $status The status.
|
||||
* @param Amount $amount The amount.
|
||||
* @param bool $final_capture The final capture.
|
||||
* @param string $seller_protection The seller protection.
|
||||
* @param string $invoice_id The invoice id.
|
||||
* @param string $custom_id The custom id.
|
||||
* @param SellerReceivableBreakdown|null $seller_receivable_breakdown The detailed breakdown of the capture activity (fees, ...).
|
||||
*/
|
||||
public function __construct(
|
||||
string $id,
|
||||
|
@ -83,16 +91,18 @@ class Capture {
|
|||
bool $final_capture,
|
||||
string $seller_protection,
|
||||
string $invoice_id,
|
||||
string $custom_id
|
||||
string $custom_id,
|
||||
?SellerReceivableBreakdown $seller_receivable_breakdown
|
||||
) {
|
||||
|
||||
$this->id = $id;
|
||||
$this->status = $status;
|
||||
$this->amount = $amount;
|
||||
$this->final_capture = $final_capture;
|
||||
$this->seller_protection = $seller_protection;
|
||||
$this->invoice_id = $invoice_id;
|
||||
$this->custom_id = $custom_id;
|
||||
$this->id = $id;
|
||||
$this->status = $status;
|
||||
$this->amount = $amount;
|
||||
$this->final_capture = $final_capture;
|
||||
$this->seller_protection = $seller_protection;
|
||||
$this->invoice_id = $invoice_id;
|
||||
$this->custom_id = $custom_id;
|
||||
$this->seller_receivable_breakdown = $seller_receivable_breakdown;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -158,6 +168,15 @@ class Capture {
|
|||
return $this->custom_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the detailed breakdown of the capture activity (fees, ...).
|
||||
*
|
||||
* @return SellerReceivableBreakdown|null
|
||||
*/
|
||||
public function seller_receivable_breakdown() : ?SellerReceivableBreakdown {
|
||||
return $this->seller_receivable_breakdown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the entity as array.
|
||||
*
|
||||
|
@ -177,6 +196,9 @@ class Capture {
|
|||
if ( $details ) {
|
||||
$data['status_details'] = array( 'reason' => $details->reason() );
|
||||
}
|
||||
if ( $this->seller_receivable_breakdown ) {
|
||||
$data['seller_receivable_breakdown'] = $this->seller_receivable_breakdown->to_array();
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
|
90
modules/ppcp-api-client/src/Entity/ExchangeRate.php
Normal file
90
modules/ppcp-api-client/src/Entity/ExchangeRate.php
Normal file
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
/**
|
||||
* The exchange rate object.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\ApiClient\Entity
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\ApiClient\Entity;
|
||||
|
||||
/**
|
||||
* Class ExchangeRate.
|
||||
*/
|
||||
class ExchangeRate {
|
||||
|
||||
/**
|
||||
* The source currency from which to convert an amount.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $source_currency;
|
||||
|
||||
/**
|
||||
* The target currency to which to convert an amount.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $target_currency;
|
||||
|
||||
/**
|
||||
* The target currency amount. Equivalent to one unit of the source currency.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* ExchangeRate constructor.
|
||||
*
|
||||
* @param string $source_currency The source currency from which to convert an amount.
|
||||
* @param string $target_currency The target currency to which to convert an amount.
|
||||
* @param string $value The target currency amount. Equivalent to one unit of the source currency.
|
||||
*/
|
||||
public function __construct( string $source_currency, string $target_currency, string $value ) {
|
||||
$this->source_currency = $source_currency;
|
||||
$this->target_currency = $target_currency;
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The source currency from which to convert an amount.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function source_currency(): string {
|
||||
return $this->source_currency;
|
||||
}
|
||||
|
||||
/**
|
||||
* The target currency to which to convert an amount.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function target_currency(): string {
|
||||
return $this->target_currency;
|
||||
}
|
||||
|
||||
/**
|
||||
* The target currency amount. Equivalent to one unit of the source currency.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function value(): string {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object as array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function to_array(): array {
|
||||
return array(
|
||||
'source_currency' => $this->source_currency,
|
||||
'target_currency' => $this->target_currency,
|
||||
'value' => $this->value,
|
||||
);
|
||||
}
|
||||
}
|
74
modules/ppcp-api-client/src/Entity/PlatformFee.php
Normal file
74
modules/ppcp-api-client/src/Entity/PlatformFee.php
Normal file
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
/**
|
||||
* The platform fee object.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\ApiClient\Entity
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\ApiClient\Entity;
|
||||
|
||||
/**
|
||||
* Class PlatformFee.
|
||||
*/
|
||||
class PlatformFee {
|
||||
|
||||
/**
|
||||
* The fee.
|
||||
*
|
||||
* @var Money
|
||||
*/
|
||||
private $amount;
|
||||
|
||||
/**
|
||||
* The recipient of the fee.
|
||||
*
|
||||
* @var Payee|null
|
||||
*/
|
||||
private $payee;
|
||||
|
||||
/**
|
||||
* PlatformFee constructor.
|
||||
*
|
||||
* @param Money $amount The fee.
|
||||
* @param Payee|null $payee The recipient of the fee.
|
||||
*/
|
||||
public function __construct( Money $amount, ?Payee $payee ) {
|
||||
$this->amount = $amount;
|
||||
$this->payee = $payee;
|
||||
}
|
||||
|
||||
/**
|
||||
* The fee.
|
||||
*
|
||||
* @return Money
|
||||
*/
|
||||
public function amount(): Money {
|
||||
return $this->amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* The recipient of the fee.
|
||||
*
|
||||
* @return Payee|null
|
||||
*/
|
||||
public function payee(): ?Payee {
|
||||
return $this->payee;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object as array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function to_array(): array {
|
||||
$data = array(
|
||||
'amount' => $this->amount->to_array(),
|
||||
);
|
||||
if ( $this->payee ) {
|
||||
$data['payee'] = $this->payee->to_array();
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
211
modules/ppcp-api-client/src/Entity/SellerReceivableBreakdown.php
Normal file
211
modules/ppcp-api-client/src/Entity/SellerReceivableBreakdown.php
Normal file
|
@ -0,0 +1,211 @@
|
|||
<?php
|
||||
/**
|
||||
* The info about fees and amount that will be received by the seller.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\ApiClient\Entity
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\ApiClient\Entity;
|
||||
|
||||
/**
|
||||
* Class SellerReceivableBreakdown
|
||||
*/
|
||||
class SellerReceivableBreakdown {
|
||||
|
||||
/**
|
||||
* The amount for this captured payment in the currency of the transaction.
|
||||
*
|
||||
* @var Money
|
||||
*/
|
||||
private $gross_amount;
|
||||
|
||||
/**
|
||||
* The applicable fee for this captured 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 captured 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 that is credited to the payee's PayPal account.
|
||||
*
|
||||
* Present only when the currency of the captured payment is different from the currency
|
||||
* of the PayPal account where the payee wants to credit the funds. Computed as net_amount times exchange_rate.
|
||||
*
|
||||
* @var Money|null
|
||||
*/
|
||||
private $receivable_amount;
|
||||
|
||||
/**
|
||||
* The exchange rate that determines the amount that is credited to the payee's PayPal account.
|
||||
*
|
||||
* Present when the currency of the captured payment is different from the currency of the PayPal account where the payee wants to credit the funds.
|
||||
*
|
||||
* @var ExchangeRate|null
|
||||
*/
|
||||
private $exchange_rate;
|
||||
|
||||
/**
|
||||
* An array of platform or partner fees, commissions, or brokerage fees that associated with the captured payment.
|
||||
*
|
||||
* @var PlatformFee[]
|
||||
*/
|
||||
private $platform_fees;
|
||||
|
||||
/**
|
||||
* SellerReceivableBreakdown constructor.
|
||||
*
|
||||
* @param Money $gross_amount The amount for this captured payment in the currency of the transaction.
|
||||
* @param Money|null $paypal_fee The applicable fee for this captured payment in the currency of the transaction.
|
||||
* @param Money|null $paypal_fee_in_receivable_currency The applicable fee for this captured payment in the receivable currency.
|
||||
* @param Money|null $net_amount The net amount that the payee receives for this captured payment in their PayPal account.
|
||||
* @param Money|null $receivable_amount The net amount that is credited to the payee's PayPal account.
|
||||
* @param ExchangeRate|null $exchange_rate The exchange rate that determines the amount that is credited to the payee's PayPal account.
|
||||
* @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 $receivable_amount,
|
||||
?ExchangeRate $exchange_rate,
|
||||
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->receivable_amount = $receivable_amount;
|
||||
$this->exchange_rate = $exchange_rate;
|
||||
$this->platform_fees = $platform_fees;
|
||||
}
|
||||
|
||||
/**
|
||||
* The amount for this captured payment in the currency of the transaction.
|
||||
*
|
||||
* @return Money
|
||||
*/
|
||||
public function gross_amount(): ?Money {
|
||||
return $this->gross_amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* The applicable fee for this captured payment in the currency of the transaction.
|
||||
*
|
||||
* @return Money|null
|
||||
*/
|
||||
public function paypal_fee(): ?Money {
|
||||
return $this->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.
|
||||
*
|
||||
* @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 captured 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 that is credited to the payee's PayPal account.
|
||||
*
|
||||
* Present only when the currency of the captured payment is different from the currency
|
||||
* of the PayPal account where the payee wants to credit the funds. Computed as net_amount times exchange_rate.
|
||||
*
|
||||
* @return Money|null
|
||||
*/
|
||||
public function receivable_amount(): ?Money {
|
||||
return $this->receivable_amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* The exchange rate that determines the amount that is credited to the payee's PayPal account.
|
||||
*
|
||||
* Present when the currency of the captured payment is different from the currency of the PayPal account where the payee wants to credit the funds.
|
||||
*
|
||||
* @return ExchangeRate|null
|
||||
*/
|
||||
public function exchange_rate(): ?ExchangeRate {
|
||||
return $this->exchange_rate;
|
||||
}
|
||||
|
||||
/**
|
||||
* An array of platform or partner fees, commissions, or brokerage fees that associated with the captured 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(
|
||||
'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->receivable_amount ) {
|
||||
$data['receivable_amount'] = $this->receivable_amount->to_array();
|
||||
}
|
||||
if ( $this->exchange_rate ) {
|
||||
$data['exchange_rate'] = $this->exchange_rate->to_array();
|
||||
}
|
||||
if ( $this->platform_fees ) {
|
||||
$data['platform_fees'] = array_map(
|
||||
function ( PlatformFee $fee ) {
|
||||
return $fee->to_array();
|
||||
},
|
||||
$this->platform_fees
|
||||
);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
|
@ -28,6 +28,13 @@ class AmountFactory {
|
|||
*/
|
||||
private $item_factory;
|
||||
|
||||
/**
|
||||
* The Money factory.
|
||||
*
|
||||
* @var MoneyFactory
|
||||
*/
|
||||
private $money_factory;
|
||||
|
||||
/**
|
||||
* 3-letter currency code of the shop.
|
||||
*
|
||||
|
@ -38,12 +45,14 @@ class AmountFactory {
|
|||
/**
|
||||
* AmountFactory constructor.
|
||||
*
|
||||
* @param ItemFactory $item_factory The Item factory.
|
||||
* @param string $currency 3-letter currency code of the shop.
|
||||
* @param ItemFactory $item_factory The Item factory.
|
||||
* @param MoneyFactory $money_factory The Money factory.
|
||||
* @param string $currency 3-letter currency code of the shop.
|
||||
*/
|
||||
public function __construct( ItemFactory $item_factory, string $currency ) {
|
||||
$this->item_factory = $item_factory;
|
||||
$this->currency = $currency;
|
||||
public function __construct( ItemFactory $item_factory, MoneyFactory $money_factory, string $currency ) {
|
||||
$this->item_factory = $item_factory;
|
||||
$this->money_factory = $money_factory;
|
||||
$this->currency = $currency;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -169,16 +178,7 @@ class AmountFactory {
|
|||
* @throws RuntimeException When JSON object is malformed.
|
||||
*/
|
||||
public function from_paypal_response( \stdClass $data ): Amount {
|
||||
if ( ! isset( $data->value ) || ! is_numeric( $data->value ) ) {
|
||||
throw new RuntimeException( __( 'No value given', 'woocommerce-paypal-payments' ) );
|
||||
}
|
||||
if ( ! isset( $data->currency_code ) ) {
|
||||
throw new RuntimeException(
|
||||
__( 'No currency given', 'woocommerce-paypal-payments' )
|
||||
);
|
||||
}
|
||||
|
||||
$money = new Money( (float) $data->value, $data->currency_code );
|
||||
$money = $this->money_factory->from_paypal_response( $data );
|
||||
$breakdown = ( isset( $data->breakdown ) ) ? $this->break_down( $data->breakdown ) : null;
|
||||
return new Amount( $money, $breakdown );
|
||||
}
|
||||
|
|
|
@ -25,14 +25,26 @@ class CaptureFactory {
|
|||
*/
|
||||
private $amount_factory;
|
||||
|
||||
/**
|
||||
* The SellerReceivableBreakdown factory.
|
||||
*
|
||||
* @var SellerReceivableBreakdownFactory
|
||||
*/
|
||||
private $seller_receivable_breakdown_factory;
|
||||
|
||||
/**
|
||||
* CaptureFactory constructor.
|
||||
*
|
||||
* @param AmountFactory $amount_factory The amount factory.
|
||||
* @param AmountFactory $amount_factory The amount factory.
|
||||
* @param SellerReceivableBreakdownFactory $seller_receivable_breakdown_factory The SellerReceivableBreakdown factory.
|
||||
*/
|
||||
public function __construct( AmountFactory $amount_factory ) {
|
||||
public function __construct(
|
||||
AmountFactory $amount_factory,
|
||||
SellerReceivableBreakdownFactory $seller_receivable_breakdown_factory
|
||||
) {
|
||||
|
||||
$this->amount_factory = $amount_factory;
|
||||
$this->amount_factory = $amount_factory;
|
||||
$this->seller_receivable_breakdown_factory = $seller_receivable_breakdown_factory;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -44,7 +56,10 @@ class CaptureFactory {
|
|||
*/
|
||||
public function from_paypal_response( \stdClass $data ) : Capture {
|
||||
|
||||
$reason = $data->status_details->reason ?? null;
|
||||
$reason = $data->status_details->reason ?? null;
|
||||
$seller_receivable_breakdown = isset( $data->seller_receivable_breakdown ) ?
|
||||
$this->seller_receivable_breakdown_factory->from_paypal_response( $data->seller_receivable_breakdown )
|
||||
: null;
|
||||
|
||||
return new Capture(
|
||||
(string) $data->id,
|
||||
|
@ -56,7 +71,8 @@ class CaptureFactory {
|
|||
(bool) $data->final_capture,
|
||||
(string) $data->seller_protection->status,
|
||||
(string) $data->invoice_id,
|
||||
(string) $data->custom_id
|
||||
(string) $data->custom_id,
|
||||
$seller_receivable_breakdown
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
41
modules/ppcp-api-client/src/Factory/ExchangeRateFactory.php
Normal file
41
modules/ppcp-api-client/src/Factory/ExchangeRateFactory.php
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
/**
|
||||
* The ExchangeRateFactory Factory.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\ApiClient\Factory
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\ApiClient\Factory;
|
||||
|
||||
use stdClass;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\ExchangeRate;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
|
||||
/**
|
||||
* Class ExchangeRateFactory
|
||||
*/
|
||||
class ExchangeRateFactory {
|
||||
/**
|
||||
* Returns an ExchangeRate object based off a PayPal Response.
|
||||
*
|
||||
* @param stdClass $data The JSON object.
|
||||
*
|
||||
* @return ExchangeRate|null
|
||||
* @throws RuntimeException When JSON object is malformed.
|
||||
*/
|
||||
public function from_paypal_response( stdClass $data ): ?ExchangeRate {
|
||||
// Looks like all fields in this object are optional, according to the docs,
|
||||
// and sometimes we get an empty object.
|
||||
$source_currency = $data->source_currency ?? '';
|
||||
$target_currency = $data->target_currency ?? '';
|
||||
$value = $data->value ?? '';
|
||||
if ( ! $source_currency && ! $target_currency && ! $value ) {
|
||||
// Do not return empty object.
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ExchangeRate( $source_currency, $target_currency, $value );
|
||||
}
|
||||
}
|
39
modules/ppcp-api-client/src/Factory/MoneyFactory.php
Normal file
39
modules/ppcp-api-client/src/Factory/MoneyFactory.php
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
/**
|
||||
* The Money factory.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\ApiClient\Factory
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\ApiClient\Factory;
|
||||
|
||||
use stdClass;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Money;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
|
||||
/**
|
||||
* Class MoneyFactory
|
||||
*/
|
||||
class MoneyFactory {
|
||||
|
||||
/**
|
||||
* Returns a Money object based off a PayPal Response.
|
||||
*
|
||||
* @param stdClass $data The JSON object.
|
||||
*
|
||||
* @return Money
|
||||
* @throws RuntimeException When JSON object is malformed.
|
||||
*/
|
||||
public function from_paypal_response( stdClass $data ): Money {
|
||||
if ( ! isset( $data->value ) || ! is_numeric( $data->value ) ) {
|
||||
throw new RuntimeException( 'No money value given' );
|
||||
}
|
||||
if ( ! isset( $data->currency_code ) ) {
|
||||
throw new RuntimeException( 'No currency given' );
|
||||
}
|
||||
|
||||
return new Money( (float) $data->value, $data->currency_code );
|
||||
}
|
||||
}
|
64
modules/ppcp-api-client/src/Factory/PlatformFeeFactory.php
Normal file
64
modules/ppcp-api-client/src/Factory/PlatformFeeFactory.php
Normal file
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
/**
|
||||
* The PlatformFee 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\Exception\RuntimeException;
|
||||
|
||||
/**
|
||||
* Class PayeeFactory
|
||||
*/
|
||||
class PlatformFeeFactory {
|
||||
|
||||
/**
|
||||
* The Money factory.
|
||||
*
|
||||
* @var MoneyFactory
|
||||
*/
|
||||
private $money_factory;
|
||||
|
||||
/**
|
||||
* The Payee factory.
|
||||
*
|
||||
* @var PayeeFactory
|
||||
*/
|
||||
private $payee_factory;
|
||||
|
||||
/**
|
||||
* PlatformFeeFactory constructor.
|
||||
*
|
||||
* @param MoneyFactory $money_factory The Money factory.
|
||||
* @param PayeeFactory $payee_factory The Payee factory.
|
||||
*/
|
||||
public function __construct( MoneyFactory $money_factory, PayeeFactory $payee_factory ) {
|
||||
|
||||
$this->money_factory = $money_factory;
|
||||
$this->payee_factory = $payee_factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Payee object based off a PayPal Response.
|
||||
*
|
||||
* @param stdClass $data The JSON object.
|
||||
*
|
||||
* @return PlatformFee
|
||||
* @throws RuntimeException When JSON object is malformed.
|
||||
*/
|
||||
public function from_paypal_response( stdClass $data ): PlatformFee {
|
||||
if ( ! isset( $data->amount ) ) {
|
||||
throw new RuntimeException( 'Platform fee amount not found' );
|
||||
}
|
||||
|
||||
$amount = $this->money_factory->from_paypal_response( $data->amount );
|
||||
$payee = ( isset( $data->payee ) ) ? $this->payee_factory->from_paypal_response( $data->payee ) : null;
|
||||
return new PlatformFee( $amount, $payee );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
<?php
|
||||
/**
|
||||
* The SellerReceivableBreakdown 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\SellerReceivableBreakdown;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
|
||||
/**
|
||||
* Class SellerReceivableBreakdownFactory
|
||||
*/
|
||||
class SellerReceivableBreakdownFactory {
|
||||
|
||||
/**
|
||||
* The Money factory.
|
||||
*
|
||||
* @var MoneyFactory
|
||||
*/
|
||||
private $money_factory;
|
||||
|
||||
/**
|
||||
* The ExchangeRate factory.
|
||||
*
|
||||
* @var ExchangeRateFactory
|
||||
*/
|
||||
private $exchange_rate_factory;
|
||||
|
||||
/**
|
||||
* The PlatformFee factory.
|
||||
*
|
||||
* @var PlatformFeeFactory
|
||||
*/
|
||||
private $platform_fee_factory;
|
||||
|
||||
/**
|
||||
* SellerReceivableBreakdownFactory constructor.
|
||||
*
|
||||
* @param MoneyFactory $money_factory The Money factory.
|
||||
* @param ExchangeRateFactory $exchange_rate_factory The ExchangeRate factory.
|
||||
* @param PlatformFeeFactory $platform_fee_factory The PlatformFee factory.
|
||||
*/
|
||||
public function __construct(
|
||||
MoneyFactory $money_factory,
|
||||
ExchangeRateFactory $exchange_rate_factory,
|
||||
PlatformFeeFactory $platform_fee_factory
|
||||
) {
|
||||
|
||||
$this->money_factory = $money_factory;
|
||||
$this->exchange_rate_factory = $exchange_rate_factory;
|
||||
$this->platform_fee_factory = $platform_fee_factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a SellerReceivableBreakdown object based off a PayPal Response.
|
||||
*
|
||||
* @param stdClass $data The JSON object.
|
||||
*
|
||||
* @return SellerReceivableBreakdown
|
||||
* @throws RuntimeException When JSON object is malformed.
|
||||
*/
|
||||
public function from_paypal_response( stdClass $data ): SellerReceivableBreakdown {
|
||||
if ( ! isset( $data->gross_amount ) ) {
|
||||
throw new RuntimeException( 'Seller breakdown gross amount not found' );
|
||||
}
|
||||
|
||||
$gross_amount = $this->money_factory->from_paypal_response( $data->gross_amount );
|
||||
$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;
|
||||
$receivable_amount = ( isset( $data->receivable_amount ) ) ? $this->money_factory->from_paypal_response( $data->receivable_amount ) : null;
|
||||
$exchange_rate = ( isset( $data->exchange_rate ) ) ? $this->exchange_rate_factory->from_paypal_response( $data->exchange_rate ) : 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 SellerReceivableBreakdown(
|
||||
$gross_amount,
|
||||
$paypal_fee,
|
||||
$paypal_fee_in_receivable_currency,
|
||||
$net_amount,
|
||||
$receivable_amount,
|
||||
$exchange_rate,
|
||||
$platform_fees
|
||||
);
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@ use WooCommerce\PayPalCommerce\Button\Helper\MessagesDisclaimers;
|
|||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingOptionsRenderer;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Admin\FeesRenderer;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Admin\OrderTablePaymentStatusColumn;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Admin\PaymentStatusOrderDetail;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Admin\RenderAuthorizeAction;
|
||||
|
@ -251,6 +252,9 @@ return array(
|
|||
$settings = $container->get( 'wcgateway.settings' );
|
||||
return new OrderTablePaymentStatusColumn( $settings );
|
||||
},
|
||||
'wcgateway.admin.fees-renderer' => static function ( ContainerInterface $container ): FeesRenderer {
|
||||
return new FeesRenderer();
|
||||
},
|
||||
|
||||
'wcgateway.settings.fields' => static function ( ContainerInterface $container ): array {
|
||||
|
||||
|
|
86
modules/ppcp-wc-gateway/src/Admin/FeesRenderer.php
Normal file
86
modules/ppcp-wc-gateway/src/Admin/FeesRenderer.php
Normal file
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
/**
|
||||
* Renders the PayPal fees in the order details.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\WcGateway\Admin
|
||||
*/
|
||||
|
||||
declare( strict_types=1 );
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\WcGateway\Admin;
|
||||
|
||||
use WC_Order;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
|
||||
/**
|
||||
* Class FeesRenderer
|
||||
*/
|
||||
class FeesRenderer {
|
||||
/**
|
||||
* Renders the PayPal fees in the order details.
|
||||
*
|
||||
* @param WC_Order $wc_order The order for which to render the fees.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function render( WC_Order $wc_order ) : string {
|
||||
$breakdown = $wc_order->get_meta( PayPalGateway::FEES_META_KEY );
|
||||
if ( ! is_array( $breakdown ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$html = '';
|
||||
|
||||
$fee = $breakdown['paypal_fee'] ?? null;
|
||||
if ( is_array( $fee ) ) {
|
||||
$html .= $this->render_money_row(
|
||||
__( 'PayPal Fee:', 'woocommerce-paypal-payments' ),
|
||||
__( 'The fee PayPal collects for the transaction.', 'woocommerce-paypal-payments' ),
|
||||
$fee['value'],
|
||||
$fee['currency_code'],
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
$net = $breakdown['net_amount'] ?? null;
|
||||
if ( is_array( $net ) ) {
|
||||
$html .= $this->render_money_row(
|
||||
__( 'PayPal Payout:', 'woocommerce-paypal-payments' ),
|
||||
__( 'The net total that will be credited to your PayPal account.', 'woocommerce-paypal-payments' ),
|
||||
$net['value'],
|
||||
$net['currency_code']
|
||||
);
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a row in the order price breakdown table.
|
||||
*
|
||||
* @param string $title The row title.
|
||||
* @param string $tooltip The title tooltip.
|
||||
* @param string|float $value The money value.
|
||||
* @param string $currency The currency code.
|
||||
* @param bool $negative Whether to add the minus sign.
|
||||
* @return string
|
||||
*/
|
||||
private function render_money_row( string $title, string $tooltip, $value, string $currency, bool $negative = false ): string {
|
||||
/**
|
||||
* Bad type hint in WC phpdoc.
|
||||
*
|
||||
* @psalm-suppress InvalidScalarArgument
|
||||
*/
|
||||
return '
|
||||
<tr>
|
||||
<td class="label">' . wc_help_tip( $tooltip ) . ' ' . esc_html( $title ) . '
|
||||
</td>
|
||||
<td width="1%"></td>
|
||||
<td class="total">
|
||||
' .
|
||||
( $negative ? ' - ' : '' ) .
|
||||
wc_price( $value, array( 'currency' => $currency ) ) . '
|
||||
</td>
|
||||
</tr>';
|
||||
}
|
||||
}
|
|
@ -37,6 +37,7 @@ class PayPalGateway extends \WC_Payment_Gateway {
|
|||
const INTENT_META_KEY = '_ppcp_paypal_intent';
|
||||
const ORDER_ID_META_KEY = '_ppcp_paypal_order_id';
|
||||
const ORDER_PAYMENT_MODE_META_KEY = '_ppcp_paypal_payment_mode';
|
||||
const FEES_META_KEY = '_ppcp_paypal_fees';
|
||||
|
||||
/**
|
||||
* The Settings Renderer.
|
||||
|
|
|
@ -63,6 +63,7 @@ trait PaymentsStatusHandlingTrait {
|
|||
switch ( $status->name() ) {
|
||||
case CaptureStatus::COMPLETED:
|
||||
$wc_order->payment_complete();
|
||||
do_action( 'woocommerce_paypal_payments_order_captured', $wc_order, $capture );
|
||||
break;
|
||||
// It is checked in the capture endpoint already, but there are other ways to capture,
|
||||
// such as when paid via saved card.
|
||||
|
|
|
@ -11,9 +11,12 @@ namespace WooCommerce\PayPalCommerce\WcGateway;
|
|||
|
||||
use Dhii\Container\ServiceProvider;
|
||||
use Dhii\Modular\Module\ModuleInterface;
|
||||
use WC_Order;
|
||||
use WooCommerce\PayPalCommerce\AdminNotices\Repository\Repository;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Entity\Capture;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Repository\PayPalRequestIdRepository;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Admin\FeesRenderer;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Admin\OrderTablePaymentStatusColumn;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Admin\PaymentStatusOrderDetail;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Admin\RenderAuthorizeAction;
|
||||
|
@ -71,6 +74,35 @@ class WCGatewayModule implements ModuleInterface {
|
|||
}
|
||||
);
|
||||
|
||||
add_action(
|
||||
'woocommerce_paypal_payments_order_captured',
|
||||
function ( WC_Order $wc_order, Capture $capture ) {
|
||||
$breakdown = $capture->seller_receivable_breakdown();
|
||||
if ( $breakdown ) {
|
||||
$wc_order->update_meta_data( PayPalGateway::FEES_META_KEY, $breakdown->to_array() );
|
||||
$wc_order->save_meta_data();
|
||||
}
|
||||
},
|
||||
10,
|
||||
2
|
||||
);
|
||||
|
||||
$fees_renderer = $c->get( 'wcgateway.admin.fees-renderer' );
|
||||
assert( $fees_renderer instanceof FeesRenderer );
|
||||
|
||||
add_action(
|
||||
'woocommerce_admin_order_totals_after_total',
|
||||
function ( int $order_id ) use ( $fees_renderer ) {
|
||||
$wc_order = wc_get_order( $order_id );
|
||||
if ( ! $wc_order instanceof WC_Order ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
echo $fees_renderer->render( $wc_order );
|
||||
}
|
||||
);
|
||||
|
||||
if ( $c->has( 'wcgateway.url' ) ) {
|
||||
$assets = new SettingsPageAssets(
|
||||
$c->get( 'wcgateway.url' ),
|
||||
|
@ -249,7 +281,7 @@ class WCGatewayModule implements ModuleInterface {
|
|||
static function ( $order_actions ) use ( $container ): array {
|
||||
global $theorder;
|
||||
|
||||
if ( ! is_a( $theorder, \WC_Order::class ) ) {
|
||||
if ( ! is_a( $theorder, WC_Order::class ) ) {
|
||||
return $order_actions;
|
||||
}
|
||||
|
||||
|
@ -265,7 +297,7 @@ class WCGatewayModule implements ModuleInterface {
|
|||
|
||||
add_action(
|
||||
'woocommerce_order_action_ppcp_authorize_order',
|
||||
static function ( \WC_Order $wc_order ) use ( $container ) {
|
||||
static function ( WC_Order $wc_order ) use ( $container ) {
|
||||
|
||||
/**
|
||||
* The authorized payments processor.
|
||||
|
|
|
@ -97,6 +97,8 @@ Follow the steps below to connect the plugin to your PayPal account:
|
|||
* Enhancement - Add transaction ID to WC order and order note when refund is received #473
|
||||
* Enhancement - Asset caching may cause bugs on upgrades #501
|
||||
* Enhancement - Allow partial capture #483
|
||||
* Enhancement - PayPal Payments doesn't set transaction fee metadata #467
|
||||
* Enhancement - Show PayPal fee information in order #489
|
||||
|
||||
= 1.6.5 =
|
||||
* Fix - Allow guest users to purchase subscription products from checkout page #422
|
||||
|
|
|
@ -15,11 +15,21 @@ class AmountFactoryTest extends TestCase
|
|||
{
|
||||
private $currency = 'EUR';
|
||||
|
||||
public function testFromWcCartDefault()
|
||||
{
|
||||
$itemFactory = Mockery::mock(ItemFactory::class);
|
||||
$testee = new AmountFactory($itemFactory, $this->currency);
|
||||
private $itemFactory;
|
||||
private $moneyFactory;
|
||||
private $testee;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->itemFactory = Mockery::mock(ItemFactory::class);
|
||||
$this->moneyFactory = new MoneyFactory();
|
||||
$this->testee = new AmountFactory($this->itemFactory, $this->moneyFactory, $this->currency);
|
||||
}
|
||||
|
||||
public function testFromWcCartDefault()
|
||||
{
|
||||
$cart = Mockery::mock(\WC_Cart::class);
|
||||
$cart
|
||||
->shouldReceive('get_total')
|
||||
|
@ -53,7 +63,7 @@ class AmountFactoryTest extends TestCase
|
|||
$woocommerce->session = $session;
|
||||
$session->shouldReceive('get')->andReturn([]);
|
||||
|
||||
$result = $testee->from_wc_cart($cart);
|
||||
$result = $this->testee->from_wc_cart($cart);
|
||||
$this->assertEquals($this->currency, $result->currency_code());
|
||||
$this->assertEquals((float) 1, $result->value());
|
||||
$this->assertEquals((float) 10, $result->breakdown()->discount()->value());
|
||||
|
@ -68,10 +78,6 @@ class AmountFactoryTest extends TestCase
|
|||
|
||||
public function testFromWcCartNoDiscount()
|
||||
{
|
||||
$itemFactory = Mockery::mock(ItemFactory::class);
|
||||
$testee = new AmountFactory($itemFactory, $this->currency);
|
||||
|
||||
$expectedCurrency = 'EUR';
|
||||
$expectedTotal = 1;
|
||||
$cart = Mockery::mock(\WC_Cart::class);
|
||||
$cart
|
||||
|
@ -105,13 +111,12 @@ class AmountFactoryTest extends TestCase
|
|||
when('WC')->justReturn($woocommerce);
|
||||
$woocommerce->session = $session;
|
||||
$session->shouldReceive('get')->andReturn([]);
|
||||
$result = $testee->from_wc_cart($cart);
|
||||
$result = $this->testee->from_wc_cart($cart);
|
||||
$this->assertNull($result->breakdown()->discount());
|
||||
}
|
||||
|
||||
public function testFromWcOrderDefault()
|
||||
{
|
||||
$itemFactory = Mockery::mock(ItemFactory::class);
|
||||
$order = Mockery::mock(\WC_Order::class);
|
||||
$unitAmount = Mockery::mock(Money::class);
|
||||
$unitAmount
|
||||
|
@ -131,11 +136,10 @@ class AmountFactoryTest extends TestCase
|
|||
$item
|
||||
->shouldReceive('tax')
|
||||
->andReturn($tax);
|
||||
$itemFactory
|
||||
$this->itemFactory
|
||||
->expects('from_wc_order')
|
||||
->with($order)
|
||||
->andReturn([$item]);
|
||||
$testee = new AmountFactory($itemFactory, $this->currency);
|
||||
|
||||
$order
|
||||
->shouldReceive('get_total')
|
||||
|
@ -154,7 +158,7 @@ class AmountFactoryTest extends TestCase
|
|||
->with(false)
|
||||
->andReturn(3);
|
||||
|
||||
$result = $testee->from_wc_order($order);
|
||||
$result = $this->testee->from_wc_order($order);
|
||||
$this->assertEquals((float) 3, $result->breakdown()->discount()->value());
|
||||
$this->assertEquals((float) 6, $result->breakdown()->item_total()->value());
|
||||
$this->assertEquals((float) 1.5, $result->breakdown()->shipping()->value());
|
||||
|
@ -169,7 +173,6 @@ class AmountFactoryTest extends TestCase
|
|||
|
||||
public function testFromWcOrderDiscountIsNull()
|
||||
{
|
||||
$itemFactory = Mockery::mock(ItemFactory::class);
|
||||
$order = Mockery::mock(\WC_Order::class);
|
||||
$unitAmount = Mockery::mock(Money::class);
|
||||
$unitAmount
|
||||
|
@ -189,11 +192,10 @@ class AmountFactoryTest extends TestCase
|
|||
$item
|
||||
->shouldReceive('tax')
|
||||
->andReturn($tax);
|
||||
$itemFactory
|
||||
$this->itemFactory
|
||||
->expects('from_wc_order')
|
||||
->with($order)
|
||||
->andReturn([$item]);
|
||||
$testee = new AmountFactory($itemFactory, $this->currency);
|
||||
|
||||
$order
|
||||
->shouldReceive('get_total')
|
||||
|
@ -212,7 +214,7 @@ class AmountFactoryTest extends TestCase
|
|||
->with(false)
|
||||
->andReturn(0);
|
||||
|
||||
$result = $testee->from_wc_order($order);
|
||||
$result = $this->testee->from_wc_order($order);
|
||||
$this->assertNull($result->breakdown()->discount());
|
||||
}
|
||||
|
||||
|
@ -222,12 +224,10 @@ class AmountFactoryTest extends TestCase
|
|||
*/
|
||||
public function testFromPayPalResponse($response, $expectsException)
|
||||
{
|
||||
$itemFactory = Mockery::mock(ItemFactory::class);
|
||||
$testee = new AmountFactory($itemFactory, $this->currency);
|
||||
if ($expectsException) {
|
||||
$this->expectException(RuntimeException::class);
|
||||
}
|
||||
$result = $testee->from_paypal_response($response);
|
||||
$result = $this->testee->from_paypal_response($response);
|
||||
if ($expectsException) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,192 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\ApiClient\Factory;
|
||||
|
||||
use WooCommerce\PayPalCommerce\TestCase;
|
||||
|
||||
class SellerReceivableBreakdownFactoryTest extends TestCase
|
||||
{
|
||||
private $testee;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->testee = new SellerReceivableBreakdownFactory(
|
||||
new MoneyFactory(),
|
||||
new ExchangeRateFactory(),
|
||||
new PlatformFeeFactory(new MoneyFactory(), new PayeeFactory())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataForTestFromPayPalResponse
|
||||
*/
|
||||
public function testFromPayPalResponse(string $json, array $expected_result)
|
||||
{
|
||||
$obj = json_decode($json);
|
||||
|
||||
$result = $this->testee->from_paypal_response($obj);
|
||||
|
||||
self::assertEquals($expected_result, $result->to_array());
|
||||
}
|
||||
|
||||
public function dataForTestFromPayPalResponse() : array
|
||||
{
|
||||
return [
|
||||
'fee' => [
|
||||
'
|
||||
{
|
||||
"gross_amount": {
|
||||
"currency_code": "USD",
|
||||
"value": "10.42"
|
||||
},
|
||||
"paypal_fee": {
|
||||
"currency_code": "USD",
|
||||
"value": "0.41"
|
||||
},
|
||||
"net_amount": {
|
||||
"currency_code": "USD",
|
||||
"value": "10.01"
|
||||
}
|
||||
}',
|
||||
[
|
||||
'gross_amount' => [
|
||||
'currency_code' => 'USD',
|
||||
'value' => '10.42',
|
||||
],
|
||||
'paypal_fee' => [
|
||||
'currency_code' => 'USD',
|
||||
'value' => '0.41',
|
||||
],
|
||||
'net_amount' => [
|
||||
'currency_code' => 'USD',
|
||||
'value' => '10.01',
|
||||
],
|
||||
],
|
||||
],
|
||||
'min' => [
|
||||
'
|
||||
{
|
||||
"gross_amount": {
|
||||
"currency_code": "USD",
|
||||
"value": "10.42"
|
||||
}
|
||||
}',
|
||||
[
|
||||
'gross_amount' => [
|
||||
'currency_code' => 'USD',
|
||||
'value' => '10.42',
|
||||
],
|
||||
],
|
||||
],
|
||||
'exchange' => [
|
||||
'
|
||||
{
|
||||
"gross_amount": {
|
||||
"value": "10.99",
|
||||
"currency_code": "USD"
|
||||
},
|
||||
"paypal_fee": {
|
||||
"value": "0.33",
|
||||
"currency_code": "USD"
|
||||
},
|
||||
"net_amount": {
|
||||
"value": "10.66",
|
||||
"currency_code": "USD"
|
||||
},
|
||||
"receivable_amount": {
|
||||
"currency_code": "CNY",
|
||||
"value": "59.26"
|
||||
},
|
||||
"paypal_fee_in_receivable_currency": {
|
||||
"currency_code": "CNY",
|
||||
"value": "1.13"
|
||||
},
|
||||
"exchange_rate": {
|
||||
"source_currency": "USD",
|
||||
"target_currency": "CNY",
|
||||
"value": "5.9483297432325"
|
||||
}
|
||||
}',
|
||||
[
|
||||
'gross_amount' => [
|
||||
'currency_code' => 'USD',
|
||||
'value' => '10.99',
|
||||
],
|
||||
'paypal_fee' => [
|
||||
'currency_code' => 'USD',
|
||||
'value' => '0.33',
|
||||
],
|
||||
'net_amount' => [
|
||||
'currency_code' => 'USD',
|
||||
'value' => '10.66',
|
||||
],
|
||||
'receivable_amount' => [
|
||||
'currency_code' => 'CNY',
|
||||
'value' => '59.26',
|
||||
],
|
||||
'paypal_fee_in_receivable_currency' => [
|
||||
'currency_code' => 'CNY',
|
||||
'value' => '1.13',
|
||||
],
|
||||
'exchange_rate' => [
|
||||
'source_currency' => 'USD',
|
||||
'target_currency' => 'CNY',
|
||||
'value' => '5.9483297432325',
|
||||
],
|
||||
],
|
||||
],
|
||||
'platform_fees' => [
|
||||
'
|
||||
{
|
||||
"gross_amount": {
|
||||
"currency_code": "USD",
|
||||
"value": "10.42"
|
||||
},
|
||||
"platform_fees": [
|
||||
{
|
||||
"amount": {
|
||||
"currency_code": "USD",
|
||||
"value": "0.06"
|
||||
}
|
||||
},
|
||||
{
|
||||
"amount": {
|
||||
"currency_code": "USD",
|
||||
"value": "0.08"
|
||||
},
|
||||
"payee": {
|
||||
"email_address": "example@gmail.com"
|
||||
}
|
||||
}
|
||||
]
|
||||
}',
|
||||
[
|
||||
'gross_amount' => [
|
||||
'currency_code' => 'USD',
|
||||
'value' => '10.42',
|
||||
],
|
||||
'platform_fees' => [
|
||||
[
|
||||
'amount' => [
|
||||
'currency_code' => 'USD',
|
||||
'value' => '0.06',
|
||||
],
|
||||
],
|
||||
[
|
||||
'amount' => [
|
||||
'currency_code' => 'USD',
|
||||
'value' => '0.08',
|
||||
],
|
||||
'payee' => [
|
||||
'email_address' => 'example@gmail.com',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
92
tests/PHPUnit/WcGateway/Admin/FeesRendererTest.php
Normal file
92
tests/PHPUnit/WcGateway/Admin/FeesRendererTest.php
Normal file
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\WcGateway\Gateway;
|
||||
|
||||
use Mockery;
|
||||
use WC_Order;
|
||||
use WooCommerce\PayPalCommerce\TestCase;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Admin\FeesRenderer;
|
||||
use function Brain\Monkey\Functions\when;
|
||||
|
||||
class FeesRendererTest extends TestCase
|
||||
{
|
||||
private $renderer;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->renderer = new FeesRenderer();
|
||||
|
||||
when('wc_help_tip')->returnArg();
|
||||
when('wc_price')->returnArg();
|
||||
}
|
||||
|
||||
public function testRender() {
|
||||
$wcOrder = Mockery::mock(WC_Order::class);
|
||||
|
||||
$wcOrder->expects('get_meta')
|
||||
->with(PayPalGateway::FEES_META_KEY)
|
||||
->andReturn([
|
||||
'gross_amount' => [
|
||||
'currency_code' => 'USD',
|
||||
'value' => '10.42',
|
||||
],
|
||||
'paypal_fee' => [
|
||||
'currency_code' => 'USD',
|
||||
'value' => '0.41',
|
||||
],
|
||||
'net_amount' => [
|
||||
'currency_code' => 'USD',
|
||||
'value' => '10.01',
|
||||
],
|
||||
]);
|
||||
|
||||
$result = $this->renderer->render($wcOrder);
|
||||
$this->assertStringContainsString('Fee', $result);
|
||||
$this->assertStringContainsString('0.41', $result);
|
||||
$this->assertStringContainsString('Payout', $result);
|
||||
$this->assertStringContainsString('10.01', $result);
|
||||
}
|
||||
|
||||
public function testRenderWithoutNet() {
|
||||
$wcOrder = Mockery::mock(WC_Order::class);
|
||||
|
||||
$wcOrder->expects('get_meta')
|
||||
->with(PayPalGateway::FEES_META_KEY)
|
||||
->andReturn([
|
||||
'paypal_fee' => [
|
||||
'currency_code' => 'USD',
|
||||
'value' => '0.41',
|
||||
],
|
||||
]);
|
||||
|
||||
$result = $this->renderer->render($wcOrder);
|
||||
$this->assertStringContainsString('Fee', $result);
|
||||
$this->assertStringContainsString('0.41', $result);
|
||||
$this->assertStringNotContainsString('Payout', $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider noFeesDataProvider
|
||||
*/
|
||||
public function testNoFees($meta) {
|
||||
$wcOrder = Mockery::mock(WC_Order::class);
|
||||
|
||||
$wcOrder->expects('get_meta')
|
||||
->with(PayPalGateway::FEES_META_KEY)
|
||||
->andReturn($meta);
|
||||
|
||||
$this->assertSame('', $this->renderer->render($wcOrder));
|
||||
}
|
||||
|
||||
function noFeesDataProvider(): array
|
||||
{
|
||||
return [
|
||||
['hello'],
|
||||
[[]],
|
||||
[['paypal_fee' => 'hello']],
|
||||
];
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue