diff --git a/src/OrderBuilder.php b/src/OrderBuilder.php index 119c8e0..f63aead 100644 --- a/src/OrderBuilder.php +++ b/src/OrderBuilder.php @@ -9,6 +9,7 @@ class OrderBuilder private string $externalId = ''; private string $currency = ''; private float $amount = 0; + private float $discount = 0; private string $description = ''; private string $brandName = ''; private string $locale = 'es-AR'; @@ -48,6 +49,12 @@ public function amount(float $amount): OrderBuilder return $this; } + public function discount(float $discount): OrderBuilder + { + $this->discount = $discount; + return $this; + } + /** * @param string $description * @return OrderBuilder @@ -100,32 +107,60 @@ public function cancelUrl(string $cancelUrl): OrderBuilder public function make(): array { - return [ + $arr = [ 'intent' => 'CAPTURE', 'purchase_units' => [ [ 'custom_id' => $this->externalId, + 'description' => $this->description, 'amount' => [ 'currency_code' => $this->currency, - 'value' => round($this->amount, 2), + 'value' => round($this->amount - $this->discount, 2), + 'breakdown' => [ + 'item_total' => [ + 'currency_code' => $this->currency, + 'value' => round($this->amount, 2), + ], + ], + ], + 'items' => [ + [ + 'name' => $this->description, + 'quantity' => '1', + 'custom_id' => $this->externalId, + 'unit_amount' => [ + 'currency_code' => $this->currency, + 'value' => round($this->amount, 2), + ], + 'category' => 'DIGITAL_GOODS' + ] ], - 'description' => $this->description, 'payment_options' => [ 'allowed_payment_method' => 'INSTANT_FUNDING_SOURCE' ], ] ], - 'application_context' => [ - 'brand_name' => $this->brandName, - 'locale' => $this->locale, - 'user_action' => 'PAY_NOW', - 'payment_method' => [ - 'payee_preferred' => 'IMMEDIATE_PAYMENT_REQUIRED', - ], - 'shipping_preference' => 'NO_SHIPPING', - 'return_url' => $this->returnUrl, - 'cancel_url' => $this->cancelUrl + 'payment_source' => [ + 'paypal' => [ + 'experience_context' => [ + 'brand_name' => $this->brandName, + 'shipping_preference' => 'NO_SHIPPING', + 'user_action' => 'PAY_NOW', + 'payment_method_preference' => 'IMMEDIATE_PAYMENT_REQUIRED', + 'locale' => $this->locale, + 'return_url' => $this->returnUrl, + 'cancel_url' => $this->cancelUrl + ] + ] ], ]; + + if ($this->discount > 0) { + $arr['purchase_units'][0]['amount']['breakdown']['discount'] = [ + 'currency_code' => $this->currency, + 'value' => round($this->discount, 2), + ]; + } + return $arr; } } diff --git a/tests/OrderBuilderTest.php b/tests/OrderBuilderTest.php index cea6f00..10f186a 100644 --- a/tests/OrderBuilderTest.php +++ b/tests/OrderBuilderTest.php @@ -29,23 +29,110 @@ public function create_order_with_int_amount() 'amount' => [ 'currency_code' => 'USD', 'value' => 23.21, + 'breakdown' => [ + 'item_total' => [ + 'currency_code' => 'USD', + 'value' => 23.21, + ], + ] ], 'description' => 'My custom product', 'payment_options' => [ 'allowed_payment_method' => 'INSTANT_FUNDING_SOURCE' ], + 'items' => [ + [ + 'name' => 'My custom product', + 'quantity' => '1', + 'custom_id' => '31fe5538-8589-437d-8823-3b0574186a5f', + 'unit_amount' => [ + 'currency_code' => 'USD', + 'value' => 23.21, + ], + 'category' => 'DIGITAL_GOODS', + ] + ] ] ], - 'application_context' => [ - 'brand_name' => 'My brand name', - 'locale' => 'es-AR', - 'user_action' => 'PAY_NOW', - 'payment_method' => [ - 'payee_preferred' => 'IMMEDIATE_PAYMENT_REQUIRED', + 'payment_source' => [ + 'paypal' => [ + 'experience_context' => [ + 'brand_name' => 'My brand name', + 'locale' => 'es-AR', + 'user_action' => 'PAY_NOW', + 'payment_method_preference' => 'IMMEDIATE_PAYMENT_REQUIRED', + 'shipping_preference' => 'NO_SHIPPING', + 'return_url' => 'http://localhost:8080/return', + 'cancel_url' => 'http://localhost:8080/cancel' + ], + ], + ], + ], $order); + } + + #[Test] + public function create_order_with_discount() + { + $order = (new OrderBuilder()) + ->externalId('31fe5538-8589-437d-8823-3b0574186a5f') + ->currency('USD') + ->amount(23.99) + ->discount(3.98) + ->description('My custom product') + ->brandName('My brand name') + ->returnUrl('http://localhost:8080/return') + ->cancelUrl('http://localhost:8080/cancel') + ->make(); + + $this->assertEquals([ + 'intent' => 'CAPTURE', + 'purchase_units' => [ + [ + 'custom_id' => '31fe5538-8589-437d-8823-3b0574186a5f', + 'amount' => [ + 'currency_code' => 'USD', + 'value' => 20.01, + 'breakdown' => [ + 'item_total' => [ + 'currency_code' => 'USD', + 'value' => 23.99, + ], + 'discount' => [ + 'currency_code' => 'USD', + 'value' => 3.98, + ], + ] + ], + 'description' => 'My custom product', + 'payment_options' => [ + 'allowed_payment_method' => 'INSTANT_FUNDING_SOURCE' + ], + 'items' => [ + [ + 'name' => 'My custom product', + 'quantity' => '1', + 'custom_id' => '31fe5538-8589-437d-8823-3b0574186a5f', + 'unit_amount' => [ + 'currency_code' => 'USD', + 'value' => 23.99, + ], + 'category' => 'DIGITAL_GOODS', + ] + ] + ] + ], + 'payment_source' => [ + 'paypal' => [ + 'experience_context' => [ + 'brand_name' => 'My brand name', + 'locale' => 'es-AR', + 'user_action' => 'PAY_NOW', + 'payment_method_preference' => 'IMMEDIATE_PAYMENT_REQUIRED', + 'shipping_preference' => 'NO_SHIPPING', + 'return_url' => 'http://localhost:8080/return', + 'cancel_url' => 'http://localhost:8080/cancel' + ], ], - 'shipping_preference' => 'NO_SHIPPING', - 'return_url' => 'http://localhost:8080/return', - 'cancel_url' => 'http://localhost:8080/cancel' ], ], $order); } diff --git a/tests/PayPalApiTest.php b/tests/PayPalApiTest.php index f1c2fa7..9569773 100644 --- a/tests/PayPalApiTest.php +++ b/tests/PayPalApiTest.php @@ -5,7 +5,6 @@ use Exception; use Illuminate\Foundation\Testing\WithFaker; use Illuminate\Http\Client\RequestException; -use Illuminate\Support\Facades\Log; use PHPUnit\Framework\Attributes\Test; use Puntodev\Payments\OrderBuilder; use Puntodev\Payments\PayPalApi; @@ -26,13 +25,6 @@ public function setUp(): void ); } - protected function getEnvironmentSetUp($app) - { - $app['config']->set('paypal.client_id', env('PAYPAL_API_CLIENT_ID')); - $app['config']->set('paypal.client_secret', env('PAYPAL_API_CLIENT_SECRET')); - $app['config']->set('paypal.use_sandbox', env('SANDBOX_GATEWAYS')); - } - #[Test] public function verify_ipn() { @@ -50,6 +42,7 @@ public function create_order() ->externalId($this->faker->uuid) ->currency('USD') ->amount(23.20) + ->discount(2.19999) ->description('My custom product') ->brandName('My brand name') ->returnUrl('http://localhost:8080/return') @@ -57,19 +50,17 @@ public function create_order() ->make(); $createdOrder = $this->paypalApi->createOrder($order); - Log::debug('Created Order: ', ['createdOrder' => $createdOrder]); - $this->assertEquals('CREATED', $createdOrder['status']); - $this->assertCount(4, $createdOrder['links']); + $this->assertEquals('PAYER_ACTION_REQUIRED', $createdOrder['status']); + $this->assertCount(2, $createdOrder['links']); $link = collect($createdOrder['links']) ->filter(function ($link) { - return $link['method'] === 'GET' && $link['rel'] === 'approve'; + return $link['method'] === 'GET' && $link['rel'] === 'payer-action'; }) ->first(); $this->assertStringStartsWith('https://www.sandbox.paypal.com/checkoutnow', $link['href']); } - /** * @return void * @throws Exception