diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 68cb599e..5083a01d 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -193,9 +193,10 @@ jobs:
-
name: Upload Behat logs
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
if: failure()
with:
name: Behat logs
path: etc/build/
if-no-files-found: ignore
+ overwrite: true
diff --git a/UPGRADE.md b/UPGRADE.md
index 9dfd6fc6..9ce27408 100644
--- a/UPGRADE.md
+++ b/UPGRADE.md
@@ -1,4 +1,74 @@
-### UPGRADE FROM 1.5.1 to 1.6
+### UPGRADE FROM 1.6.1 to 1.6.2
+
+1. The following constructor signatures have been changed:
+
+ `Sylius\PayPalPlugin\Controller\CreatePayPalOrderFromCartAction`:
+ ```diff
+ public function __construct(
+ private readonly ?Payum $payum,
+ private readonly ?OrderRepositoryInterface $orderRepository,
+ private readonly ?FactoryInterface $stateMachineFactory,
+ private readonly ObjectManager $paymentManager,
+ private readonly OrderProviderInterface $orderProvider,
+ private readonly CapturePaymentResolverInterface $capturePaymentResolver,
+ + private readonly ?OrderPaymentsRemoverInterface $orderPaymentsRemover = null,
+ + private readonly ?OrderProcessorInterface $orderProcessor = null,
+ )
+ ```
+
+### UPGRADE FROM 1.6.0 to 1.6.1
+
+1. The following constructor signatures have been changed:
+
+ `Sylius\PayPalPlugin\Controller\UpdatePayPalOrderAction`:
+ ```diff
+ public function __construct(
+ private readonly PaymentProviderInterface $paymentProvider,
+ private readonly CacheAuthorizeClientApiInterface $authorizeClientApi,
+ - private readonly OrderDetailsApiInterface $orderDetailsApi,
+ private readonly UpdateOrderApiInterface $updateOrderApi,
+ private readonly AddressFactoryInterface $addressFactory,
+ private readonly OrderProcessorInterface $orderProcessor,
+ )
+ ```
+
+ `Sylius\PayPalPlugin\Model\PayPalPurchaseUnit`:
+ ```diff
+ public function __construct(
+ private readonly string $referenceId,
+ private readonly string $invoiceNumber,
+ private readonly string $currencyCode,
+ private readonly int $totalAmount,
+ private readonly int $shippingValue,
+ private readonly float $itemTotalValue,
+ private readonly float $taxTotalValue,
+ private readonly int $discountValue,
+ private readonly string $merchantId,
+ private readonly array $items,
+ private readonly bool $shippingRequired,
+ private readonly ?AddressInterface $shippingAddress = null,
+ private readonly string $softDescriptor = 'Sylius PayPal Payment',
+ + private readonly int $shippingDiscountValue = 0,
+ )
+ ```
+
+ `Sylius\PayPalPlugin\Controller\ProcessPayPalOrderAction`:
+ ```diff
+ public function __construct(
+ - private readonly OrderRepositoryInterface $orderRepository,
+ private readonly CustomerRepositoryInterface $customerRepository,
+ private readonly FactoryInterface $customerFactory,
+ private readonly AddressFactoryInterface $addressFactory,
+ private readonly ObjectManager $orderManager,
+ private readonly StateMachineFactoryInterface|StateMachineInterface $stateMachineFactory,
+ private readonly PaymentStateManagerInterface $paymentStateManager,
+ private readonly CacheAuthorizeClientApiInterface $authorizeClientApi,
+ private readonly OrderDetailsApiInterface $orderDetailsApi,
+ private readonly OrderProviderInterface $orderProvider,
+ )
+ ```
+
+### UPGRADE FROM 1.5.1 to 1.6.0
1. Support for Sylius 1.13 has been added, it is now the recommended Sylius version to use.
@@ -12,9 +82,9 @@
use GuzzleHttp\ClientInterface as GuzzleClientInterface;
use Psr\Http\Message\RequestFactoryInterface;
use Psr\Http\Message\StreamFactoryInterface;
-
+
public function __construct(
- - private readonly GuzzleClientInterface $client,
+ - private readonly GuzzleClientInterface $client,
+ private readonly GuzzleClientInterface|ClientInterface $client,
private readonly LoggerInterface $logger,
private readonly UuidProviderInterface $uuidProvider,
@@ -33,7 +103,7 @@
use Psr\Http\Client\ClientInterface;
use GuzzleHttp\ClientInterface as GuzzleClientInterface;
use Psr\Http\Message\RequestFactoryInterface;
-
+
public function __construct(
- private readonly GuzzleClientInterface $client,
+ private readonly GuzzleClientInterface|ClientInterface $client,
@@ -47,7 +117,7 @@
use GuzzleHttp\ClientInterface as GuzzleClientInterface;
use Psr\Http\Message\RequestFactoryInterface;
use Psr\Http\Message\StreamFactoryInterface;
-
+
public function __construct(
- private readonly GuzzleClientInterface $client,
+ private readonly GuzzleClientInterface|ClientInterface $client,
@@ -62,7 +132,7 @@
use Psr\Http\Client\ClientInterface;
use GuzzleHttp\ClientInterface as GuzzleClientInterface;
use Psr\Http\Message\RequestFactoryInterface;
-
+
public function __construct(
- private readonly GuzzleClientInterface $client,
+ private readonly GuzzleClientInterface|ClientInterface $client,
@@ -71,7 +141,7 @@
+ private readonly ?RequestFactoryInterface $requestFactory = null,
)
```
-
+
1. Added doctrine migration for PostgreSQL. For more information, please refer to the [Sylius 1.13 UPGRADE.md](https://github.com/Sylius/Sylius/blob/1.13/UPGRADE-1.13.md)
### UPGRADE FROM 1.3.0 to 1.3.1
diff --git a/spec/Api/CreateOrderApiSpec.php b/spec/Api/CreateOrderApiSpec.php
index d78e47a3..042e312f 100644
--- a/spec/Api/CreateOrderApiSpec.php
+++ b/spec/Api/CreateOrderApiSpec.php
@@ -17,6 +17,7 @@
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Sylius\Component\Core\Model\AddressInterface;
+use Sylius\Component\Core\Model\AdjustmentInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\PaymentInterface;
use Sylius\Component\Core\Model\PaymentMethodInterface;
@@ -57,6 +58,7 @@ function it_creates_pay_pal_order_based_on_given_payment(
$order->getShippingTotal()->willReturn(1000);
$order->isShippingRequired()->willReturn(true);
$order->getOrderPromotionTotal()->willReturn(0);
+ $order->getAdjustmentsTotalRecursively(AdjustmentInterface::ORDER_SHIPPING_PROMOTION_ADJUSTMENT)->willReturn(0);
$payPalItemDataProvider->provide($order)->willReturn([
'items' => [
@@ -92,7 +94,7 @@ function it_creates_pay_pal_order_based_on_given_payment(
Argument::that(function (array $data): bool {
return
$data['intent'] === 'CAPTURE' &&
- $data['purchase_units'][0]['invoice_number'] === 'REFERENCE-NUMBER' &&
+ $data['purchase_units'][0]['invoice_id'] === 'REFERENCE-NUMBER' &&
$data['purchase_units'][0]['amount']['value'] === '100.00' &&
$data['purchase_units'][0]['amount']['currency_code'] === 'PLN' &&
$data['purchase_units'][0]['amount']['breakdown']['shipping']['currency_code'] === 'PLN' &&
@@ -126,6 +128,7 @@ function it_creates_pay_pal_order_with_shipping_address_based_on_given_payment(
$order->getShippingTotal()->willReturn(1000);
$order->isShippingRequired()->willReturn(true);
$order->getOrderPromotionTotal()->willReturn(0);
+ $order->getAdjustmentsTotalRecursively(AdjustmentInterface::ORDER_SHIPPING_PROMOTION_ADJUSTMENT)->willReturn(0);
$shippingAddress->getFullName()->willReturn('Gandalf The Grey');
$shippingAddress->getStreet()->willReturn('Hobbit St. 123');
@@ -167,7 +170,7 @@ function it_creates_pay_pal_order_with_shipping_address_based_on_given_payment(
Argument::that(function (array $data): bool {
return
$data['intent'] === 'CAPTURE' &&
- $data['purchase_units'][0]['invoice_number'] === 'REFERENCE-NUMBER' &&
+ $data['purchase_units'][0]['invoice_id'] === 'REFERENCE-NUMBER' &&
$data['purchase_units'][0]['amount']['value'] === '100.00' &&
$data['purchase_units'][0]['amount']['currency_code'] === 'PLN' &&
$data['purchase_units'][0]['shipping']['name']['full_name'] === 'Gandalf The Grey' &&
@@ -204,6 +207,7 @@ function it_creates_pay_pal_order_with_more_than_one_product(
$order->getShippingTotal()->willReturn(3000);
$order->isShippingRequired()->willReturn(true);
$order->getOrderPromotionTotal()->willReturn(0);
+ $order->getAdjustmentsTotalRecursively(AdjustmentInterface::ORDER_SHIPPING_PROMOTION_ADJUSTMENT)->willReturn(0);
$shippingAddress->getFullName()->willReturn('Gandalf The Grey');
$shippingAddress->getStreet()->willReturn('Hobbit St. 123');
@@ -297,6 +301,7 @@ function it_creates_pay_pal_order_with_non_neutral_tax_and_changed_quantity(
$order->getShippingTotal()->willReturn(1000);
$order->isShippingRequired()->willReturn(true);
$order->getOrderPromotionTotal()->willReturn(0);
+ $order->getAdjustmentsTotalRecursively(AdjustmentInterface::ORDER_SHIPPING_PROMOTION_ADJUSTMENT)->willReturn(0);
$shippingAddress->getFullName()->willReturn('Gandalf The Grey');
$shippingAddress->getStreet()->willReturn('Hobbit St. 123');
@@ -394,6 +399,7 @@ function it_creates_pay_pal_order_with_more_than_one_product_with_different_tax_
$order->getShippingTotal()->willReturn(3000);
$order->isShippingRequired()->willReturn(true);
$order->getOrderPromotionTotal()->willReturn(0);
+ $order->getAdjustmentsTotalRecursively(AdjustmentInterface::ORDER_SHIPPING_PROMOTION_ADJUSTMENT)->willReturn(0);
$shippingAddress->getFullName()->willReturn('Gandalf The Grey');
$shippingAddress->getStreet()->willReturn('Hobbit St. 123');
@@ -509,6 +515,7 @@ function it_allows_to_create_digital_order(
$order->getShippingTotal()->willReturn(0);
$order->isShippingRequired()->willReturn(false);
$order->getOrderPromotionTotal()->willReturn(0);
+ $order->getAdjustmentsTotalRecursively(AdjustmentInterface::ORDER_SHIPPING_PROMOTION_ADJUSTMENT)->willReturn(0);
$payPalItemDataProvider->provide($order)->willReturn([
'items' => [
@@ -573,6 +580,7 @@ function it_creates_pay_pal_order_with_promotion(
$order->getShippingTotal()->willReturn(749);
$order->isShippingRequired()->willReturn(true);
$order->getOrderPromotionTotal()->willReturn(-250);
+ $order->getAdjustmentsTotalRecursively(AdjustmentInterface::ORDER_SHIPPING_PROMOTION_ADJUSTMENT)->willReturn(0);
$payPalItemDataProvider->provide($order)->willReturn([
'items' => [
@@ -608,7 +616,7 @@ function it_creates_pay_pal_order_with_promotion(
Argument::that(function (array $data): bool {
return
$data['intent'] === 'CAPTURE' &&
- $data['purchase_units'][0]['invoice_number'] === 'REFERENCE-NUMBER' &&
+ $data['purchase_units'][0]['invoice_id'] === 'REFERENCE-NUMBER' &&
$data['purchase_units'][0]['amount']['value'] === '29.99' &&
$data['purchase_units'][0]['amount']['currency_code'] === 'PLN' &&
$data['purchase_units'][0]['amount']['breakdown']['shipping']['currency_code'] === 'PLN' &&
@@ -627,4 +635,80 @@ function it_creates_pay_pal_order_with_promotion(
$this->create('TOKEN', $payment, 'REFERENCE_ID')->shouldReturn(['status' => 'CREATED', 'id' => 123]);
}
+
+ function it_creates_pay_pal_order_with_shipping_promotion(
+ PayPalClientInterface $client,
+ PaymentReferenceNumberProviderInterface $paymentReferenceNumberProvider,
+ PaymentInterface $payment,
+ OrderInterface $order,
+ PaymentMethodInterface $paymentMethod,
+ GatewayConfigInterface $gatewayConfig,
+ PayPalItemDataProviderInterface $payPalItemDataProvider,
+ ): void {
+ $payment->getOrder()->willReturn($order);
+ $payment->getAmount()->willReturn(3000);
+ $order->getCurrencyCode()->willReturn('PLN');
+ $order->getShippingAddress()->willReturn(null);
+ $order->getItemsTotal()->willReturn(2500);
+ $order->getShippingTotal()->willReturn(500);
+ $order->isShippingRequired()->willReturn(true);
+ $order->getOrderPromotionTotal()->willReturn(0);
+ $order
+ ->getAdjustmentsTotalRecursively(AdjustmentInterface::ORDER_SHIPPING_PROMOTION_ADJUSTMENT)
+ ->willReturn(-249)
+ ;
+
+ $payPalItemDataProvider->provide($order)->willReturn([
+ 'items' => [
+ [
+ 'name' => 'PRODUCT_ONE',
+ 'unit_amount' => [
+ 'value' => '25.00',
+ 'currency_code' => 'PLN',
+ ],
+ 'quantity' => 1,
+ 'tax' => [
+ 'value' => '0.00',
+ 'currency_code' => 'PLN',
+ ],
+ ],
+ ],
+ 'total_item_value' => '25.00',
+ 'total_tax' => '0.00',
+ ]);
+
+ $payment->getMethod()->willReturn($paymentMethod);
+ $paymentMethod->getGatewayConfig()->willReturn($gatewayConfig);
+
+ $paymentReferenceNumberProvider->provide($payment)->willReturn('REFERENCE-NUMBER');
+
+ $gatewayConfig->getConfig()->willReturn(
+ ['merchant_id' => 'merchant-id', 'sylius_merchant_id' => 'sylius-merchant-id'],
+ );
+
+ $client->post(
+ 'v2/checkout/orders',
+ 'TOKEN',
+ Argument::that(function (array $data): bool {
+ return
+ $data['intent'] === 'CAPTURE' &&
+ $data['purchase_units'][0]['invoice_id'] === 'REFERENCE-NUMBER' &&
+ $data['purchase_units'][0]['amount']['value'] === '30.00' &&
+ $data['purchase_units'][0]['amount']['currency_code'] === 'PLN' &&
+ $data['purchase_units'][0]['amount']['breakdown']['shipping']['currency_code'] === 'PLN' &&
+ $data['purchase_units'][0]['amount']['breakdown']['shipping']['value'] === '7.49' &&
+ $data['purchase_units'][0]['amount']['breakdown']['item_total']['currency_code'] === 'PLN' &&
+ $data['purchase_units'][0]['amount']['breakdown']['item_total']['value'] === '25.00' &&
+ $data['purchase_units'][0]['amount']['breakdown']['shipping_discount']['currency_code'] === 'PLN' &&
+ $data['purchase_units'][0]['amount']['breakdown']['shipping_discount']['value'] === '2.49' &&
+ $data['purchase_units'][0]['items'][0]['name'] === 'PRODUCT_ONE' &&
+ $data['purchase_units'][0]['items'][0]['quantity'] === 1 &&
+ $data['purchase_units'][0]['items'][0]['unit_amount']['value'] === '25.00' &&
+ $data['purchase_units'][0]['items'][0]['unit_amount']['currency_code'] === 'PLN'
+ ;
+ }),
+ )->willReturn(['status' => 'CREATED', 'id' => 123]);
+
+ $this->create('TOKEN', $payment, 'REFERENCE_ID')->shouldReturn(['status' => 'CREATED', 'id' => 123]);
+ }
}
diff --git a/spec/Api/RefundPaymentApiSpec.php b/spec/Api/RefundPaymentApiSpec.php
index e7383965..5bd13146 100644
--- a/spec/Api/RefundPaymentApiSpec.php
+++ b/spec/Api/RefundPaymentApiSpec.php
@@ -35,7 +35,7 @@ function it_refunds_pay_pal_payment_with_given_id(PayPalClientInterface $client)
->post(
'v2/payments/captures/123123/refund',
'TOKEN',
- ['amount' => ['value' => '10.99', 'currency_code' => 'USD'], 'invoice_number' => '123-11-11-2010'],
+ ['amount' => ['value' => '10.99', 'currency_code' => 'USD'], 'invoice_id' => '123-11-11-2010'],
['PayPal-Auth-Assertion' => 'PAY-PAL-AUTH-ASSERTION'],
)
->willReturn(['status' => 'COMPLETED', 'id' => '123123'])
diff --git a/spec/Api/UpdateOrderApiSpec.php b/spec/Api/UpdateOrderApiSpec.php
index 0bbf97db..203820d1 100644
--- a/spec/Api/UpdateOrderApiSpec.php
+++ b/spec/Api/UpdateOrderApiSpec.php
@@ -16,6 +16,7 @@
use PhpSpec\ObjectBehavior;
use Prophecy\Argument;
use Sylius\Component\Core\Model\AddressInterface;
+use Sylius\Component\Core\Model\AdjustmentInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\PaymentInterface;
use Sylius\PayPalPlugin\Api\UpdateOrderApiInterface;
@@ -55,12 +56,13 @@ function it_updates_pay_pal_order_with_given_new_total(
->willReturn(['items' => ['data'], 'total_item_value' => '10.00', 'total_tax' => '1.00'])
;
- $paymentReferenceNumberProvider->provide($payment)->willReturn('INVOICE_NUMBER');
+ $paymentReferenceNumberProvider->provide($payment)->willReturn('INVOICE_ID');
$order->getTotal()->willReturn(1122);
$order->getCurrencyCode()->willReturn('USD');
$order->getShippingTotal()->willReturn(22);
$order->getOrderPromotionTotal()->willReturn(0);
+ $order->getAdjustmentsTotalRecursively(AdjustmentInterface::ORDER_SHIPPING_PROMOTION_ADJUSTMENT)->willReturn(0);
$shippingAddress->getFullName()->willReturn('John Doe');
$shippingAddress->getStreet()->willReturn('Main St. 123');
@@ -78,7 +80,7 @@ function it_updates_pay_pal_order_with_given_new_total(
$data[0]['op'] === 'replace' &&
$data[0]['path'] === '/purchase_units/@reference_id==\'REFERENCE-ID\'' &&
$data[0]['value']['reference_id'] === 'REFERENCE-ID' &&
- $data[0]['value']['invoice_number'] === 'INVOICE_NUMBER' &&
+ $data[0]['value']['invoice_id'] === 'INVOICE_ID' &&
$data[0]['value']['amount']['value'] === '11.22' &&
$data[0]['value']['amount']['currency_code'] === 'USD' &&
$data[0]['value']['amount']['breakdown']['shipping']['value'] === '0.22' &&
@@ -115,12 +117,13 @@ function it_updates_digital_order(
->willReturn(['items' => ['data'], 'total_item_value' => '10.00', 'total_tax' => '1.22'])
;
- $paymentReferenceNumberProvider->provide($payment)->willReturn('INVOICE_NUMBER');
+ $paymentReferenceNumberProvider->provide($payment)->willReturn('INVOICE_ID');
$order->getTotal()->willReturn(1122);
$order->getCurrencyCode()->willReturn('USD');
$order->getShippingTotal()->willReturn(0);
$order->getOrderPromotionTotal()->willReturn(0);
+ $order->getAdjustmentsTotalRecursively(AdjustmentInterface::ORDER_SHIPPING_PROMOTION_ADJUSTMENT)->willReturn(0);
$order->isShippingRequired()->willReturn(false);
@@ -132,7 +135,7 @@ function it_updates_digital_order(
$data[0]['op'] === 'replace' &&
$data[0]['path'] === '/purchase_units/@reference_id==\'REFERENCE-ID\'' &&
$data[0]['value']['reference_id'] === 'REFERENCE-ID' &&
- $data[0]['value']['invoice_number'] === 'INVOICE_NUMBER' &&
+ $data[0]['value']['invoice_id'] === 'INVOICE_ID' &&
$data[0]['value']['amount']['value'] === '11.22' &&
$data[0]['value']['amount']['currency_code'] === 'USD' &&
$data[0]['value']['amount']['breakdown']['shipping']['value'] === '0.00' &&
diff --git a/spec/Model/PayPalOrderSpec.php b/spec/Model/PayPalOrderSpec.php
index d08b1b9c..5698054e 100644
--- a/spec/Model/PayPalOrderSpec.php
+++ b/spec/Model/PayPalOrderSpec.php
@@ -36,7 +36,7 @@ public function it_returns_full_paypal_order_data(
$payPalPurchaseUnit->toArray()->willReturn(
[
'reference_id' => 'REFERENCE_ID',
- 'invoice_number' => 'INVOICE_NUMBER',
+ 'invoice_id' => 'INVOICE_ID',
'amount' => [
'currency_code' => 'CURRENCY_CODE',
'value' => 100,
@@ -86,7 +86,7 @@ public function it_returns_full_paypal_order_data(
'purchase_units' => [
[
'reference_id' => 'REFERENCE_ID',
- 'invoice_number' => 'INVOICE_NUMBER',
+ 'invoice_id' => 'INVOICE_ID',
'amount' => [
'currency_code' => 'CURRENCY_CODE',
'value' => 100,
@@ -146,7 +146,7 @@ public function it_returns_paypal_order_data_without_shipping_address(
$payPalPurchaseUnit->toArray()->willReturn(
[
'reference_id' => 'REFERENCE_ID',
- 'invoice_number' => 'INVOICE_NUMBER',
+ 'invoice_id' => 'INVOICE_ID',
'amount' => [
'currency_code' => 'CURRENCY_CODE',
'value' => 100,
@@ -185,7 +185,7 @@ public function it_returns_paypal_order_data_without_shipping_address(
'purchase_units' => [
[
'reference_id' => 'REFERENCE_ID',
- 'invoice_number' => 'INVOICE_NUMBER',
+ 'invoice_id' => 'INVOICE_ID',
'amount' => [
'currency_code' => 'CURRENCY_CODE',
'value' => 100,
@@ -234,7 +234,7 @@ public function it_returns_paypal_order_data_if_shipping_is_not_required(
$payPalPurchaseUnit->toArray()->willReturn(
[
'reference_id' => 'REFERENCE_ID',
- 'invoice_number' => 'INVOICE_NUMBER',
+ 'invoice_id' => 'INVOICE_ID',
'amount' => [
'currency_code' => 'CURRENCY_CODE',
'value' => 100,
@@ -273,7 +273,7 @@ public function it_returns_paypal_order_data_if_shipping_is_not_required(
'purchase_units' => [
[
'reference_id' => 'REFERENCE_ID',
- 'invoice_number' => 'INVOICE_NUMBER',
+ 'invoice_id' => 'INVOICE_ID',
'amount' => [
'currency_code' => 'CURRENCY_CODE',
'value' => 100,
diff --git a/spec/Model/PayPalPurchaseUnitSpec.php b/spec/Model/PayPalPurchaseUnitSpec.php
index 72656a81..d174f26f 100644
--- a/spec/Model/PayPalPurchaseUnitSpec.php
+++ b/spec/Model/PayPalPurchaseUnitSpec.php
@@ -22,7 +22,7 @@ function let(AddressInterface $shippingAddress): void
{
$this->beConstructedWith(
'REFERENCE_ID',
- 'INVOICE_NUMBER',
+ 'INVOICE_ID',
'CURRENCY_CODE',
10000,
1000,
@@ -48,7 +48,7 @@ function it_returns_proper_paypal_purchase_unit(AddressInterface $shippingAddres
$this->toArray()->shouldReturn(
[
'reference_id' => 'REFERENCE_ID',
- 'invoice_number' => 'INVOICE_NUMBER',
+ 'invoice_id' => 'INVOICE_ID',
'amount' => [
'currency_code' => 'CURRENCY_CODE',
'value' => '100.00',
@@ -69,6 +69,10 @@ function it_returns_proper_paypal_purchase_unit(AddressInterface $shippingAddres
'currency_code' => 'CURRENCY_CODE',
'value' => '0.00',
],
+ 'shipping_discount' => [
+ 'currency_code' => 'CURRENCY_CODE',
+ 'value' => '0.00',
+ ],
],
],
'payee' => [
@@ -97,7 +101,7 @@ function it_returns_proper_paypal_purchase_unit_if_shipping_is_not_required(Addr
{
$this->beConstructedWith(
'REFERENCE_ID',
- 'INVOICE_NUMBER',
+ 'INVOICE_ID',
'CURRENCY_CODE',
10000,
1000,
@@ -113,7 +117,7 @@ function it_returns_proper_paypal_purchase_unit_if_shipping_is_not_required(Addr
$this->toArray()->shouldReturn(
[
'reference_id' => 'REFERENCE_ID',
- 'invoice_number' => 'INVOICE_NUMBER',
+ 'invoice_id' => 'INVOICE_ID',
'amount' => [
'currency_code' => 'CURRENCY_CODE',
'value' => '100.00',
@@ -134,6 +138,10 @@ function it_returns_proper_paypal_purchase_unit_if_shipping_is_not_required(Addr
'currency_code' => 'CURRENCY_CODE',
'value' => '0.00',
],
+ 'shipping_discount' => [
+ 'currency_code' => 'CURRENCY_CODE',
+ 'value' => '0.00',
+ ],
],
],
'payee' => [
@@ -151,7 +159,7 @@ function it_returns_proper_paypal_purchase_unit_if_shipping_is_not_set(): void
{
$this->beConstructedWith(
'REFERENCE_ID',
- 'INVOICE_NUMBER',
+ 'INVOICE_ID',
'CURRENCY_CODE',
10000,
1000,
@@ -167,7 +175,7 @@ function it_returns_proper_paypal_purchase_unit_if_shipping_is_not_set(): void
$this->toArray()->shouldReturn(
[
'reference_id' => 'REFERENCE_ID',
- 'invoice_number' => 'INVOICE_NUMBER',
+ 'invoice_id' => 'INVOICE_ID',
'amount' => [
'currency_code' => 'CURRENCY_CODE',
'value' => '100.00',
@@ -188,6 +196,10 @@ function it_returns_proper_paypal_purchase_unit_if_shipping_is_not_set(): void
'currency_code' => 'CURRENCY_CODE',
'value' => '0.00',
],
+ 'shipping_discount' => [
+ 'currency_code' => 'CURRENCY_CODE',
+ 'value' => '0.00',
+ ],
],
],
'payee' => [
diff --git a/src/Api/CreateOrderApi.php b/src/Api/CreateOrderApi.php
index ac197631..b196e9af 100644
--- a/src/Api/CreateOrderApi.php
+++ b/src/Api/CreateOrderApi.php
@@ -14,6 +14,7 @@
namespace Sylius\PayPalPlugin\Api;
use Sylius\Bundle\PayumBundle\Model\GatewayConfigInterface;
+use Sylius\Component\Core\Model\AdjustmentInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\PaymentInterface;
use Sylius\Component\Core\Model\PaymentMethodInterface;
@@ -62,12 +63,16 @@ public function create(string $token, PaymentInterface $payment, string $referen
Assert::keyExists($config, 'merchant_id');
Assert::keyExists($config, 'sylius_merchant_id');
+ $shippingDiscount = $order->getAdjustmentsTotalRecursively(
+ AdjustmentInterface::ORDER_SHIPPING_PROMOTION_ADJUSTMENT,
+ );
+
$payPalPurchaseUnit = new PayPalPurchaseUnit(
$referenceId,
$this->paymentReferenceNumberProvider->provide($payment),
(string) $order->getCurrencyCode(),
(int) $payment->getAmount(),
- $order->getShippingTotal(),
+ $order->getShippingTotal() - $shippingDiscount,
(float) $payPalItemData['total_item_value'],
(float) $payPalItemData['total_tax'],
$order->getOrderPromotionTotal(),
@@ -75,6 +80,7 @@ public function create(string $token, PaymentInterface $payment, string $referen
(array) $payPalItemData['items'],
$order->isShippingRequired(),
$order->getShippingAddress(),
+ shippingDiscountValue: $shippingDiscount,
);
$payPalOrder = new PayPalOrder($order, $payPalPurchaseUnit, self::PAYPAL_INTENT_CAPTURE);
diff --git a/src/Api/RefundPaymentApi.php b/src/Api/RefundPaymentApi.php
index cb9e4ce2..aaa40d9a 100644
--- a/src/Api/RefundPaymentApi.php
+++ b/src/Api/RefundPaymentApi.php
@@ -35,7 +35,7 @@ public function refund(
return $this->client->post(
sprintf('v2/payments/captures/%s/refund', $paymentId),
$token,
- ['amount' => ['value' => $amount, 'currency_code' => $currencyCode], 'invoice_number' => $invoiceNumber],
+ ['amount' => ['value' => $amount, 'currency_code' => $currencyCode], 'invoice_id' => $invoiceNumber],
['PayPal-Auth-Assertion' => $payPalAuthAssertion],
);
}
diff --git a/src/Api/UpdateOrderApi.php b/src/Api/UpdateOrderApi.php
index 20b6ec7d..7989b371 100644
--- a/src/Api/UpdateOrderApi.php
+++ b/src/Api/UpdateOrderApi.php
@@ -13,6 +13,7 @@
namespace Sylius\PayPalPlugin\Api;
+use Sylius\Component\Core\Model\AdjustmentInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\PaymentInterface;
use Sylius\PayPalPlugin\Client\PayPalClientInterface;
@@ -50,12 +51,16 @@ public function update(
$payPalItemData = $this->payPalItemsDataProvider->provide($order);
+ $shippingDiscount = $order->getAdjustmentsTotalRecursively(
+ AdjustmentInterface::ORDER_SHIPPING_PROMOTION_ADJUSTMENT,
+ );
+
$data = new PayPalPurchaseUnit(
$referenceId,
$this->paymentReferenceNumberProvider->provide($payment),
(string) $order->getCurrencyCode(),
(int) $payment->getAmount(),
- $order->getShippingTotal(),
+ $order->getShippingTotal() - $shippingDiscount,
(float) $payPalItemData['total_item_value'],
(float) $payPalItemData['total_tax'],
$order->getOrderPromotionTotal(),
@@ -63,6 +68,7 @@ public function update(
(array) $payPalItemData['items'],
$order->isShippingRequired(),
$order->getShippingAddress(),
+ shippingDiscountValue: $shippingDiscount,
);
return $this->client->patch(
diff --git a/src/Controller/CreatePayPalOrderFromCartAction.php b/src/Controller/CreatePayPalOrderFromCartAction.php
index 6948a735..0a44e42a 100644
--- a/src/Controller/CreatePayPalOrderFromCartAction.php
+++ b/src/Controller/CreatePayPalOrderFromCartAction.php
@@ -17,8 +17,12 @@
use GuzzleHttp\Exception\GuzzleException;
use Payum\Core\Payum;
use SM\Factory\FactoryInterface;
+use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\PaymentInterface;
+use Sylius\Component\Core\Model\PaymentMethodInterface;
+use Sylius\Component\Core\Payment\Remover\OrderPaymentsRemoverInterface;
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
+use Sylius\Component\Order\Processor\OrderProcessorInterface;
use Sylius\PayPalPlugin\Provider\OrderProviderInterface;
use Sylius\PayPalPlugin\Resolver\CapturePaymentResolverInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
@@ -35,6 +39,8 @@ public function __construct(
private readonly ObjectManager $paymentManager,
private readonly OrderProviderInterface $orderProvider,
private readonly CapturePaymentResolverInterface $capturePaymentResolver,
+ private readonly ?OrderPaymentsRemoverInterface $orderPaymentsRemover = null,
+ private readonly ?OrderProcessorInterface $orderProcessor = null,
) {
if (null !== $this->payum) {
trigger_deprecation(
@@ -66,6 +72,22 @@ public function __construct(
),
);
}
+ if (null === $this->orderPaymentsRemover) {
+ trigger_deprecation(
+ 'sylius/paypal-plugin',
+ '1.6',
+ 'Not passing an $orderPaymentsRemover to %s constructor is deprecated and will be prohibited in 3.0',
+ self::class,
+ );
+ }
+ if (null === $this->orderProcessor) {
+ trigger_deprecation(
+ 'sylius/paypal-plugin',
+ '1.6',
+ 'Not passing an $orderProcessor to %s constructor is deprecated and will be prohibited in 3.0',
+ self::class,
+ );
+ }
}
public function __invoke(Request $request): Response
@@ -73,12 +95,10 @@ public function __invoke(Request $request): Response
$id = $request->attributes->getInt('id');
$order = $this->orderProvider->provideOrderById($id);
- /** @var PaymentInterface $payment */
- $payment = $order->getLastPayment(PaymentInterface::STATE_CART);
-
try {
+ $payment = $this->getPayment($order);
$this->capturePaymentResolver->resolve($payment);
- } catch (GuzzleException $exception) {
+ } catch (\DomainException|GuzzleException) {
/** @var FlashBagInterface $flashBag */
$flashBag = $request->getSession()->getBag('flashes');
$flashBag->add('error', 'sylius.pay_pal.something_went_wrong');
@@ -94,4 +114,26 @@ public function __invoke(Request $request): Response
'status' => $payment->getState(),
]);
}
+
+ private function getPayment(OrderInterface $order): PaymentInterface
+ {
+ /** @var PaymentInterface $payment */
+ $payment = $order->getLastPayment(PaymentInterface::STATE_CART);
+ /** @var PaymentMethodInterface|null $paymentMethod */
+ $paymentMethod = $payment->getMethod();
+ $factoryName = $paymentMethod?->getGatewayConfig()?->getFactoryName();
+
+ if ($factoryName === 'sylius.pay_pal') {
+ return $payment;
+ }
+
+ if ($this->orderPaymentsRemover === null || $this->orderProcessor === null) {
+ throw new \DomainException('OrderPaymentsRemover and OrderProcessor must be provided to create a new payment.');
+ }
+
+ $this->orderPaymentsRemover->removePayments($order);
+ $this->orderProcessor->process($order);
+
+ return $order->getLastPayment(PaymentInterface::STATE_CART);
+ }
}
diff --git a/src/Controller/ProcessPayPalOrderAction.php b/src/Controller/ProcessPayPalOrderAction.php
index 5b1475a8..228276b3 100644
--- a/src/Controller/ProcessPayPalOrderAction.php
+++ b/src/Controller/ProcessPayPalOrderAction.php
@@ -23,7 +23,6 @@
use Sylius\Component\Core\Model\PaymentMethodInterface;
use Sylius\Component\Core\OrderCheckoutTransitions;
use Sylius\Component\Core\Repository\CustomerRepositoryInterface;
-use Sylius\Component\Core\Repository\OrderRepositoryInterface;
use Sylius\Component\Resource\Factory\FactoryInterface;
use Sylius\PayPalPlugin\Api\CacheAuthorizeClientApiInterface;
use Sylius\PayPalPlugin\Api\OrderDetailsApiInterface;
@@ -36,7 +35,6 @@
final class ProcessPayPalOrderAction
{
public function __construct(
- private readonly OrderRepositoryInterface $orderRepository,
private readonly CustomerRepositoryInterface $customerRepository,
private readonly FactoryInterface $customerFactory,
private readonly AddressFactoryInterface $addressFactory,
@@ -78,12 +76,12 @@ public function __invoke(Request $request): Response
$purchaseUnit = (array) $data['purchase_units'][0];
- $address = $this->addressFactory->createForCustomer($customer);
+ $address = $this->addressFactory->createNew();
if ($order->isShippingRequired()) {
$name = explode(' ', $purchaseUnit['shipping']['name']['full_name']);
- $address->setFirstName($name[0]);
- $address->setLastName($name[1]);
+ $address->setLastName(array_pop($name) ?? '');
+ $address->setFirstName(implode(' ', $name));
$address->setStreet($purchaseUnit['shipping']['address']['address_line_1']);
$address->setCity($purchaseUnit['shipping']['address']['admin_area_2']);
$address->setPostcode($purchaseUnit['shipping']['address']['postal_code']);
diff --git a/src/Controller/UpdatePayPalOrderAction.php b/src/Controller/UpdatePayPalOrderAction.php
index 22adc9f1..d13c7fd2 100644
--- a/src/Controller/UpdatePayPalOrderAction.php
+++ b/src/Controller/UpdatePayPalOrderAction.php
@@ -20,7 +20,6 @@
use Sylius\Component\Core\Model\PaymentMethodInterface;
use Sylius\Component\Order\Processor\OrderProcessorInterface;
use Sylius\PayPalPlugin\Api\CacheAuthorizeClientApiInterface;
-use Sylius\PayPalPlugin\Api\OrderDetailsApiInterface;
use Sylius\PayPalPlugin\Api\UpdateOrderApiInterface;
use Sylius\PayPalPlugin\Provider\PaymentProviderInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
@@ -29,32 +28,13 @@
final class UpdatePayPalOrderAction
{
- private PaymentProviderInterface $paymentProvider;
-
- private CacheAuthorizeClientApiInterface $authorizeClientApi;
-
- private OrderDetailsApiInterface $orderDetailsApi;
-
- private UpdateOrderApiInterface $updateOrderApi;
-
- private AddressFactoryInterface $addressFactory;
-
- private OrderProcessorInterface $orderProcessor;
-
public function __construct(
- PaymentProviderInterface $paymentProvider,
- CacheAuthorizeClientApiInterface $authorizeClientApi,
- OrderDetailsApiInterface $orderDetailsApi,
- UpdateOrderApiInterface $updateOrderApi,
- AddressFactoryInterface $addressFactory,
- OrderProcessorInterface $orderProcessor,
+ private readonly PaymentProviderInterface $paymentProvider,
+ private readonly CacheAuthorizeClientApiInterface $authorizeClientApi,
+ private readonly UpdateOrderApiInterface $updateOrderApi,
+ private readonly AddressFactoryInterface $addressFactory,
+ private readonly OrderProcessorInterface $orderProcessor,
) {
- $this->paymentProvider = $paymentProvider;
- $this->authorizeClientApi = $authorizeClientApi;
- $this->orderDetailsApi = $orderDetailsApi;
- $this->updateOrderApi = $updateOrderApi;
- $this->addressFactory = $addressFactory;
- $this->orderProcessor = $orderProcessor;
}
public function __invoke(Request $request): Response
@@ -67,8 +47,7 @@ public function __invoke(Request $request): Response
$paymentMethod = $payment->getMethod();
$token = $this->authorizeClientApi->authorize($paymentMethod);
- /** @var array $shippingAddress */
- $shippingAddress = $request->request->get('shipping_address');
+ $shippingAddress = $request->request->all('shipping_address');
/** @var AddressInterface $address */
$address = $this->addressFactory->createNew();
diff --git a/src/Factory/PayPalPaymentMethodNewResourceFactory.php b/src/Factory/PayPalPaymentMethodNewResourceFactory.php
index ef0dea41..a54c2230 100644
--- a/src/Factory/PayPalPaymentMethodNewResourceFactory.php
+++ b/src/Factory/PayPalPaymentMethodNewResourceFactory.php
@@ -16,9 +16,9 @@
use Sylius\Bundle\ResourceBundle\Controller\NewResourceFactoryInterface;
use Sylius\Bundle\ResourceBundle\Controller\RequestConfiguration;
use Sylius\Component\Core\Model\PaymentMethodInterface;
-use Sylius\Component\Resource\Factory\FactoryInterface;
use Sylius\Component\Resource\Model\ResourceInterface;
use Sylius\PayPalPlugin\Onboarding\Processor\OnboardingProcessorInterface;
+use Sylius\Resource\Factory\FactoryInterface;
final class PayPalPaymentMethodNewResourceFactory implements NewResourceFactoryInterface
{
@@ -36,6 +36,7 @@ public function __construct(
public function create(RequestConfiguration $requestConfiguration, FactoryInterface $factory): ResourceInterface
{
+ /** @var ResourceInterface $resource */
$resource = $this->newResourceFactory->create($requestConfiguration, $factory);
if (!$resource instanceof PaymentMethodInterface) {
diff --git a/src/Model/PayPalPurchaseUnit.php b/src/Model/PayPalPurchaseUnit.php
index e28f76f8..d587fa7e 100644
--- a/src/Model/PayPalPurchaseUnit.php
+++ b/src/Model/PayPalPurchaseUnit.php
@@ -18,80 +18,29 @@
class PayPalPurchaseUnit
{
- /** @var string */
- private $referenceId;
-
- /** @var string */
- private $invoiceNumber;
-
- /** @var string */
- private $currencyCode;
-
- /** @var int */
- private $totalAmount;
-
- /** @var int */
- private $shippingValue;
-
- /** @var float */
- private $itemTotalValue;
-
- /** @var float */
- private $taxTotalValue;
-
- /** @var int */
- private $discountValue;
-
- /** @var string */
- private $softDescriptor;
-
- /** @var string */
- private $merchantId;
-
- /** @var ?AddressInterface */
- private $shippingAddress;
-
- /** @var bool */
- private $shippingRequired;
-
- /** @var array */
- private $items;
-
public function __construct(
- string $referenceId,
- string $invoiceNumber,
- string $currencyCode,
- int $totalAmount,
- int $shippingValue,
- float $itemTotalValue,
- float $taxTotalValue,
- int $discountValue,
- string $merchantId,
- array $items,
- bool $shippingRequired,
- ?AddressInterface $shippingAddress = null,
- string $softDescriptor = 'Sylius PayPal Payment',
+ private readonly string $referenceId,
+ private readonly string $invoiceNumber,
+ private readonly string $currencyCode,
+ private readonly int $totalAmount,
+ private readonly int $shippingValue,
+ private readonly float $itemTotalValue,
+ private readonly float $taxTotalValue,
+ private readonly int $discountValue,
+ private readonly string $merchantId,
+ private readonly array $items,
+ private readonly bool $shippingRequired,
+ private readonly ?AddressInterface $shippingAddress = null,
+ private readonly string $softDescriptor = 'Sylius PayPal Payment',
+ private readonly int $shippingDiscountValue = 0,
) {
- $this->referenceId = $referenceId;
- $this->invoiceNumber = $invoiceNumber;
- $this->currencyCode = $currencyCode;
- $this->totalAmount = $totalAmount;
- $this->shippingValue = $shippingValue;
- $this->itemTotalValue = $itemTotalValue;
- $this->taxTotalValue = $taxTotalValue;
- $this->discountValue = $discountValue;
- $this->merchantId = $merchantId;
- $this->items = $items;
- $this->shippingRequired = $shippingRequired;
- $this->shippingAddress = $shippingAddress;
- $this->softDescriptor = $softDescriptor;
}
public function toArray(): array
{
$paypalPurchaseUnit = [
'reference_id' => $this->referenceId,
- 'invoice_number' => $this->invoiceNumber,
+ 'invoice_id' => $this->invoiceNumber,
'amount' => [
'currency_code' => $this->currencyCode,
'value' => number_format($this->totalAmount / 100, 2, '.', ''),
@@ -112,6 +61,10 @@ public function toArray(): array
'currency_code' => $this->currencyCode,
'value' => number_format(abs($this->discountValue) / 100, 2, '.', ''),
],
+ 'shipping_discount' => [
+ 'currency_code' => $this->currencyCode,
+ 'value' => number_format(abs($this->shippingDiscountValue) / 100, 2, '.', ''),
+ ],
],
],
'payee' => [
diff --git a/src/Resources/config/services/controller.xml b/src/Resources/config/services/controller.xml
index d9ae9937..61b48f17 100644
--- a/src/Resources/config/services/controller.xml
+++ b/src/Resources/config/services/controller.xml
@@ -80,6 +80,8 @@
+
+
@@ -117,7 +119,6 @@
-
diff --git a/tests/DataFixtures/ORM/resources/new_cart_with_cash_on_delivery_method.yaml b/tests/DataFixtures/ORM/resources/new_cart_with_cash_on_delivery_method.yaml
new file mode 100644
index 00000000..3ec3c74c
--- /dev/null
+++ b/tests/DataFixtures/ORM/resources/new_cart_with_cash_on_delivery_method.yaml
@@ -0,0 +1,30 @@
+Sylius\Component\Core\Model\Order:
+ new_cart:
+ channel: "@channel_web"
+ items: ["@sw_mug_item"]
+ currencyCode: "USD"
+ localeCode: "en_US"
+ customer: "@customer_oliver"
+ state: "cart"
+ checkoutState: "shipping_selected"
+ tokenValue: "TOKEN"
+ payments: ["@paypal_payment"]
+
+Sylius\Component\Core\Model\OrderItem:
+ sw_mug_item:
+ units: ["@sw_mug_item_unit1", "@sw_mug_item_unit2"]
+ variant: "@mug_sw"
+ order: "@new_cart"
+
+Sylius\Component\Core\Model\OrderItemUnit:
+ sw_mug_item_unit1:
+ __construct: ["@sw_mug_item"]
+ sw_mug_item_unit2:
+ __construct: ["@sw_mug_item"]
+
+Sylius\Component\Core\Model\Payment:
+ paypal_payment:
+ method: "@cash_on_delivery"
+ currencyCode: "USD"
+ amount: 40
+ state: "cart"
diff --git a/tests/DataFixtures/ORM/resources/shop.yaml b/tests/DataFixtures/ORM/resources/shop.yaml
index 2c149940..aa7bf8bc 100644
--- a/tests/DataFixtures/ORM/resources/shop.yaml
+++ b/tests/DataFixtures/ORM/resources/shop.yaml
@@ -90,6 +90,14 @@ Sylius\Component\Core\Model\PaymentMethod:
translations:
- "@paypal_translation"
channels: ["@channel_web"]
+ cash_on_delivery:
+ code: CASH_ON_DELIVERY
+ enabled: true
+ gatewayConfig: "@cash_on_delivery_config"
+ currentLocale: en_US
+ translations:
+ - "@cash_on_delivery_translation"
+ channels: ["@channel_web"]
Sylius\Bundle\PayumBundle\Model\GatewayConfig:
paypal_config:
@@ -102,6 +110,10 @@ Sylius\Bundle\PayumBundle\Model\GatewayConfig:
sylius_merchant_id: "SYLIUS_MERCHANT_ID"
partner_attribution_id: "PARTNER_ATTRIBUTION_ID"
use_authorize: true
+ cash_on_delivery_config:
+ gatewayName: "offline"
+ factoryName: "sylius.offline"
+ config: []
Sylius\Component\Payment\Model\PaymentMethodTranslation:
paypal_translation:
@@ -109,3 +121,8 @@ Sylius\Component\Payment\Model\PaymentMethodTranslation:
locale: "en_US"
description:
translatable: "@paypal"
+ cash_on_delivery_translation:
+ name: "Cash on delivery"
+ locale: "en_US"
+ description:
+ translatable: "@cash_on_delivery"
diff --git a/tests/Functional/CreatePayPalOrderFromCartActionTest.php b/tests/Functional/CreatePayPalOrderFromCartActionTest.php
index 86821bf5..73fbc444 100644
--- a/tests/Functional/CreatePayPalOrderFromCartActionTest.php
+++ b/tests/Functional/CreatePayPalOrderFromCartActionTest.php
@@ -33,4 +33,21 @@ public function it_creates_pay_pal_order_from_cart_and_returns_its_data(): void
$this->assertSame($content['orderID'], 'PAYPAL_ORDER_ID');
$this->assertSame($content['status'], 'cart');
}
+
+ /** @test */
+ public function it_creates_pay_pal_order_from_cart_and_returns_its_data_if_payment_method_is_different_then_pay_pal(): void
+ {
+ $order = $this->loadFixturesFromFiles(['resources/shop.yaml', 'resources/new_cart_with_cash_on_delivery_method.yaml']);
+ /** @var int $orderId */
+ $orderId = $order['new_cart']->getId();
+
+ $this->client->request('POST', '/en_US/create-pay-pal-order-from-cart/' . $orderId);
+
+ $response = $this->client->getResponse();
+ $content = (array) json_decode($response->getContent(), true);
+
+ $this->assertSame($content['id'], $orderId);
+ $this->assertSame($content['orderID'], 'PAYPAL_ORDER_ID');
+ $this->assertSame($content['status'], 'cart');
+ }
}