Skip to content

Commit

Permalink
+Tax arg in PaymentRedirect
Browse files Browse the repository at this point in the history
  • Loading branch information
hakito committed Jul 16, 2020
1 parent d5ce1be commit 280d811
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 120 deletions.
30 changes: 23 additions & 7 deletions src/Controller/Component/PayPalComponent.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@

use Cake\Core\Configure;
use Cake\Controller\Component;
use Cake\ORM\TableRegistry;
use Cake\Datasource\Exception\MissingDatasourceConfigException;
use Cake\Database\Exception\NestedTransactionRollbackException;
use Cake\Datasource\FactoryLocator;
use InvalidArgumentException;
use Exception;
use PayPal\Api\Amount;
use PayPal\Api\Payer;
use PayPal\Api\Payment;
use PayPal\Api\Transaction;
use PayPal\Api\ItemList;
use PayPal\Api\Item;
use PayPal\Model\Table\PayPalPaymentsTable;
use Throwable;

class PayPalComponent extends Component
{
Expand All @@ -30,7 +35,7 @@ public function initialize(array $config): void
parent::initialize($config);
$this->config = Configure::read('PayPal');
$this->items = [];
$this->PayPalPayments = TableRegistry::getTableLocator()->get('PayPal.PayPalPayments');
$this->PayPalPayments = FactoryLocator::get('Table')->get('PayPal.PayPalPayments');
}

public function startup($event)
Expand Down Expand Up @@ -67,10 +72,18 @@ public function AddArticle($name, $quantity, $price, $id = null)
/**
*
* @param string $remittanceIdentifier id to be used for the callback function
* @param string Description text for the transaction
* @throws \Cake\ORM\Exception\PersistenceFailedException when creation of database entry failed
* @param string $okUrl Redirect URL on successful payment
* @param string $cancelUrl Redirect URL on user abort
* @param string|null $description Optional transaction description
* @param int|null $tax Optional tax in cents. Will be calculated based on tax from config if not specified.
* @return void
* @throws InvalidArgumentException
* @throws MissingDatasourceConfigException
* @throws Exception
* @throws Throwable
* @throws NestedTransactionRollbackException
*/
public function PaymentRedirect($remittanceIdentifier, $okUrl, $cancelUrl, $description = null)
public function PaymentRedirect(string $remittanceIdentifier, string $okUrl, string $cancelUrl, string $description = null, int $tax = null)
{
$payer = new Payer();

Expand All @@ -85,10 +98,13 @@ public function PaymentRedirect($remittanceIdentifier, $okUrl, $cancelUrl, $desc
$itemArray[] = $item;
}

$taxPercent = $this->config['tax'];
$amountDetails = new \PayPal\Api\Details();
$amountDetails->setSubtotal($this->FormatMonetaryDecimal($itemSum));
$tax = (int) round($itemSum * $taxPercent);
if ($tax == null)
{
$taxPercent = $this->config['tax'];
$tax = (int) round($itemSum * $taxPercent);
}
$amountDetails->setTax($this->FormatMonetaryDecimal($tax));
$amountDetails->setShipping($this->FormatMonetaryDecimal($this->Shipping));

Expand Down
253 changes: 141 additions & 112 deletions tests/TestCase/Controller/Component/PayPalComponentTest.php
Original file line number Diff line number Diff line change
@@ -1,113 +1,142 @@
<?php

namespace PayPal\Test\TestCase\Controller\Component;

use Cake\Controller\ComponentRegistry;
use Cake\Core\Configure;
use Cake\Event\Event;
use Cake\TestSuite\TestCase;


use PayPal\Controller\Component\PayPalComponent;
use PayPal\Model\Table\PayPalPaymentsTable;

/**
* @var PayPalComponent PayPal
*/
class PayPalComponentTest extends TestCase
{

public function setUp(): void
{
parent::setUp();

$this->Controller = $this->getMockBuilder('\Cake\Controller\Controller')
->setMethods(['redirect'])
->getMock();

$registry = new ComponentRegistry($this->Controller);
$this->PayPal = new PayPalComponent($registry);

$event = new Event('Controller.startup', $this->Controller);
$this->PayPal->startup($event);

$this->items = new \ReflectionProperty(PayPalComponent::class, 'items');
$this->items->setAccessible(true);
}

public function testInitialized()
{
$this->assertEquals(Configure::read('PayPal'), $this->PayPal->config);
$this->assertInstanceOf(PayPalPaymentsTable::class, $this->PayPal->PayPalPayments);
}

public function testAddArticle()
{
$this->PayPal->AddArticle('foo', 3, 1234);
$items = $this->items->getValue($this->PayPal);
$this->assertEquals(1, count($items));
$this->assertEquals('foo', $items[0]->getName());
$this->assertEquals(3, $items[0]->getQuantity());
$this->assertEquals(12.34, $items[0]->getPrice());
$this->assertEquals('EUR', $items[0]->getCurrency());
$this->assertEquals(null, $items[0]->getSku());
}

public function testAddArticleWithId()
{
$this->PayPal->AddArticle('foo', 3, 1234, 'id');
$items = $this->items->getValue($this->PayPal);
$this->assertEquals(1, count($items));
$this->assertEquals('foo', $items['id']->getName());
$this->assertEquals(3, $items['id']->getQuantity());
$this->assertEquals(12.34, $items['id']->getPrice());
$this->assertEquals('EUR', $items['id']->getCurrency());
$this->assertEquals('id', $items['id']->getSku());
}

public function testPaymentRedirectCreatePaymentFails()
{
$this->PayPal->PayPalPayments = $this->getMockForModel('PayPal.PayPalPayments', ['createPayment']);
$this->PayPal->PayPalPayments->expects($this->once())
->method('createPayment')
->with('ri', $this->anything(), 'https://ok', 'https://cancel')
->will($this->throwException(new \Exception('dummy')));
$this->expectException(\Exception::class, 'dummy');
$this->PayPal->PaymentRedirect('ri', 'https://ok', 'https://cancel', 'descr');
}

public function testPaymentRedirect()
{
$this->PayPal->AddArticle('foo', 2, 1234, 'bar');
$this->PayPal->Shipping = 100;

$this->PayPal->PayPalPayments = $this->getMockForModel('PayPal.PayPalPayments', ['createPayment']);

$this->PayPal->PayPalPayments->expects($this->once())
->method('createPayment')
->with('ri', $this->callback(function($payment) {
$this->assertEquals(29.62 + 1, $payment->getTransactions()[0]->getAmount()->getTotal());
return true;
}), 'https://ok', 'https://cancel')
->will($this->returnCallback(function($remittanceIdentifier, $payment, $okUrl, $cancelUrl){
$links = new \PayPal\Api\Links();
$links
->setRel('approval_url')
->setHref('https://pay');
$payment->setLinks([$links]);
return true;
}));

$this->Controller->expects($this->once())
->method('redirect')
->with('https://pay');

$this->PayPal->PaymentRedirect('ri', 'https://ok', 'https://cancel', 'descr');
}

public function testNeutralizeFee()
{
$actual = PayPalComponent::NeutralizeFee(1234);
$this->assertEquals(1314, $actual);
}
<?php

namespace PayPal\Test\TestCase\Controller\Component;

use Cake\Controller\ComponentRegistry;
use Cake\Core\Configure;
use Cake\Event\Event;
use Cake\TestSuite\TestCase;


use PayPal\Controller\Component\PayPalComponent;
use PayPal\Model\Table\PayPalPaymentsTable;

/**
* @var PayPalComponent PayPal
*/
class PayPalComponentTest extends TestCase
{

public function setUp(): void
{
parent::setUp();

$this->Controller = $this->getMockBuilder('\Cake\Controller\Controller')
->setMethods(['redirect'])
->getMock();

$registry = new ComponentRegistry($this->Controller);
$this->PayPal = new PayPalComponent($registry);

$event = new Event('Controller.startup', $this->Controller);
$this->PayPal->startup($event);

$this->items = new \ReflectionProperty(PayPalComponent::class, 'items');
$this->items->setAccessible(true);
}

public function testInitialized()
{
$this->assertEquals(Configure::read('PayPal'), $this->PayPal->config);
$this->assertInstanceOf(PayPalPaymentsTable::class, $this->PayPal->PayPalPayments);
}

public function testAddArticle()
{
$this->PayPal->AddArticle('foo', 3, 1234);
$items = $this->items->getValue($this->PayPal);
$this->assertEquals(1, count($items));
$this->assertEquals('foo', $items[0]->getName());
$this->assertEquals(3, $items[0]->getQuantity());
$this->assertEquals(12.34, $items[0]->getPrice());
$this->assertEquals('EUR', $items[0]->getCurrency());
$this->assertEquals(null, $items[0]->getSku());
}

public function testAddArticleWithId()
{
$this->PayPal->AddArticle('foo', 3, 1234, 'id');
$items = $this->items->getValue($this->PayPal);
$this->assertEquals(1, count($items));
$this->assertEquals('foo', $items['id']->getName());
$this->assertEquals(3, $items['id']->getQuantity());
$this->assertEquals(12.34, $items['id']->getPrice());
$this->assertEquals('EUR', $items['id']->getCurrency());
$this->assertEquals('id', $items['id']->getSku());
}

public function testPaymentRedirectCreatePaymentFails()
{
$this->PayPal->PayPalPayments = $this->getMockForModel('PayPal.PayPalPayments', ['createPayment']);
$this->PayPal->PayPalPayments->expects($this->once())
->method('createPayment')
->with('ri', $this->anything(), 'https://ok', 'https://cancel')
->will($this->throwException(new \Exception('dummy')));
$this->expectException(\Exception::class, 'dummy');
$this->PayPal->PaymentRedirect('ri', 'https://ok', 'https://cancel', 'descr');
}

public function testPaymentRedirect()
{
$this->PayPal->AddArticle('foo', 2, 1234, 'bar');
$this->PayPal->Shipping = 100;

$this->PayPal->PayPalPayments = $this->getMockForModel('PayPal.PayPalPayments', ['createPayment']);

$this->PayPal->PayPalPayments->expects($this->once())
->method('createPayment')
->with('ri', $this->callback(function($payment) {
$this->assertEquals(29.62 + 1, $payment->getTransactions()[0]->getAmount()->getTotal());
return true;
}), 'https://ok', 'https://cancel')
->will($this->returnCallback(function($remittanceIdentifier, $payment, $okUrl, $cancelUrl){
$links = new \PayPal\Api\Links();
$links
->setRel('approval_url')
->setHref('https://pay');
$payment->setLinks([$links]);
return true;
}));

$this->Controller->expects($this->once())
->method('redirect')
->with('https://pay');

$this->PayPal->PaymentRedirect('ri', 'https://ok', 'https://cancel', 'descr');
}

public function testPaymentRedirectWithTax()
{
$this->PayPal->AddArticle('foo', 2, 1234, 'bar');
$this->PayPal->Shipping = 100;

$this->PayPal->PayPalPayments = $this->getMockForModel('PayPal.PayPalPayments', ['createPayment']);

$this->PayPal->PayPalPayments->expects($this->once())
->method('createPayment')
->with('ri', $this->callback(function($payment) {
$this->assertEquals(12.34 * 2 + 3.21 + 1, $payment->getTransactions()[0]->getAmount()->getTotal());
return true;
}), 'https://ok', 'https://cancel')
->will($this->returnCallback(function($remittanceIdentifier, $payment, $okUrl, $cancelUrl){
$links = new \PayPal\Api\Links();
$links
->setRel('approval_url')
->setHref('https://pay');
$payment->setLinks([$links]);
return true;
}));

$this->Controller->expects($this->once())
->method('redirect')
->with('https://pay');

$this->PayPal->PaymentRedirect('ri', 'https://ok', 'https://cancel', 'descr', 321);
}

public function testNeutralizeFee()
{
$actual = PayPalComponent::NeutralizeFee(1234);
$this->assertEquals(1314, $actual);
}
}
2 changes: 1 addition & 1 deletion tests/TestCase/Model/Table/PayPalPaymentsTableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class PayPalPaymentsTableTest extends TestCase
public function setUp(): void
{
parent::setUp();
$this->PayPalPayments = TableRegistry::getTableLocator()->get('PayPal.PayPalPayments');
$this->PayPalPayments = $this->getTableLocator()->get('PayPal.PayPalPayments');
$this->PayPalPayments->getEventManager()->setEventList(new EventList());
}

Expand Down

0 comments on commit 280d811

Please sign in to comment.