From 01f2e46d188f9f3d45bcbc4edd60e22ea8a96cbe Mon Sep 17 00:00:00 2001 From: Tom Harnasz Date: Sun, 16 Sep 2018 12:01:53 +0100 Subject: [PATCH] Issue #107 fixes character stripping allowed chars and adds tests around non-XML basket integration --- src/Extend/Item.php | 20 +++++ src/Message/AbstractRequest.php | 34 ++++++-- tests/Message/DirectAuthorizeRequestTest.php | 87 ++++++++++++++++++-- 3 files changed, 131 insertions(+), 10 deletions(-) diff --git a/src/Extend/Item.php b/src/Extend/Item.php index 597ee77..e089354 100644 --- a/src/Extend/Item.php +++ b/src/Extend/Item.php @@ -25,4 +25,24 @@ public function setVat($value) { return $this->setParameter('vat', $value); } + + /** + * Product Code is used for the Product Sage 50 Accounts Software Integration + * It allows reconcile the transactions on your account within the financial software + * by linking the product record to a specific transaction. + * This is not available for BasketXML and only Basket Integration. See docs for more info. + * {@inheritDoc} + */ + public function getProductRecord() + { + return $this->getParameter('product_code'); + } + + /** + * {@inheritDoc} + */ + public function setProductCode($value) + { + return $this->setParameter('product_code', $value); + } } diff --git a/src/Message/AbstractRequest.php b/src/Message/AbstractRequest.php index 160d6af..f0cfc98 100644 --- a/src/Message/AbstractRequest.php +++ b/src/Message/AbstractRequest.php @@ -499,6 +499,23 @@ protected function filterItemName($name) return $name; } + /** + * Filters out any characters that SagePay does not support from the item name for + * the non-xml basket integration + * + * @param string $name + * @return string + */ + protected function filterNonXmlItemName($name) + { + $standardChars = '0-9a-zA-Z'; + $allowedSpecialChars = " +'/\\,.-{};_@()^\"~$=!#?|[]"; + $pattern = '`[^'.$standardChars.preg_quote($allowedSpecialChars, '/').']`'; + $name = trim(substr(preg_replace($pattern, '', $name), 0, 100)); + + return $name; + } + /** * Filters out any characters that SagePay does not support from the discount name. * @@ -591,18 +608,25 @@ protected function getItemDataNonXML() $count = 0; foreach ($items as $basketItem) { + $description = $this->filterNonXmlItemName($basketItem->getName()); $vat = '0.00'; + if ($basketItem instanceof ExtendItem) { $vat = $basketItem->getVat(); + + /** + * Product Code is used for the Product Sage 50 Accounts Software Integration + * It allows reconcile the transactions on your account within the financial software + * by linking the product record to a specific transaction. + * This is not available for BasketXML and only Basket Integration. See docs for more info. + */ + if (!is_null($basketItem->getProductRecord())) { + $description = '[' . $basketItem->getProductRecord() . ']' . $description; + } } $lineTotal = ($basketItem->getQuantity() * ($basketItem->getPrice() + $vat)); - $description = $this->filterItemName($basketItem->getName()); - - // Make sure there aren't any colons in the name - // Perhaps ":" should be replaced with '-' or other symbol? - $description = str_replace(':', ' ', $description); $result .= ':' . $description . // Item name ':' . $basketItem->getQuantity() . // Quantity ':' . number_format($basketItem->getPrice(), 2, '.', '') . // Unit cost (without tax) diff --git a/tests/Message/DirectAuthorizeRequestTest.php b/tests/Message/DirectAuthorizeRequestTest.php index 20e6662..10d597b 100644 --- a/tests/Message/DirectAuthorizeRequestTest.php +++ b/tests/Message/DirectAuthorizeRequestTest.php @@ -3,7 +3,6 @@ namespace Omnipay\SagePay\Message; use Omnipay\Tests\TestCase; -//use Money\Money; class DirectAuthorizeRequestTest extends TestCase { @@ -13,7 +12,7 @@ class DirectAuthorizeRequestTest extends TestCase . ''; /** - * @var \Omnipay\Common\Message\AbstractRequest $request + * @var DirectAuthorizeRequest */ protected $request; @@ -325,9 +324,87 @@ public function testMixedBasketWithSpecialChars() $this->assertContains($expected, $data['BasketXML'], 'Basket XML does not match the expected output'); } - /** - * - */ + public function testNonXmlBasket() + { + $this->request->setUseOldBasketFormat(true); + + $items = new \Omnipay\Common\ItemBag(array( + new \Omnipay\SagePay\Extend\Item(array( + 'name' => "Pioneer NSDV99 DVD-Surround Sound System", + 'quantity' => 3, + 'price' => 4.35, + )), + )); + + $this->request->setItems($items); + $data = $this->request->getData(); + + $this->assertArrayNotHasKey('BasketXML', $data); + $this->assertSame('1:Pioneer NSDV99 DVD-Surround Sound System:3:4.35::4.35:13.05', $data['Basket']); + } + + public function testNonXmlBasketWithVat() + { + $this->request->setUseOldBasketFormat(true); + + $items = new \Omnipay\Common\ItemBag(array( + new \Omnipay\SagePay\Extend\Item(array( + 'name' => "Pioneer NSDV99 DVD-Surround Sound System", + 'quantity' => 3, + 'price' => 4.35, + 'vat' => 2 + )), + )); + + $this->request->setItems($items); + $data = $this->request->getData(); + + $this->assertArrayHasKey('Basket', $data); + $this->assertArrayNotHasKey('BasketXML', $data); + + $this->assertSame('1:Pioneer NSDV99 DVD-Surround Sound System:3:4.35:2:6.35:19.05', $data['Basket']); + } + + public function testNonXmlBasketWithProductCode() + { + $this->request->setUseOldBasketFormat(true); + + $items = new \Omnipay\Common\ItemBag(array( + new \Omnipay\SagePay\Extend\Item(array( + 'name' => "Pioneer NSDV99 DVD-Surround Sound System", + 'quantity' => 3, + 'price' => 4.35, + 'vat' => 2, + 'product_code' => 'DVD-123' + )), + )); + + $this->request->setItems($items); + $data = $this->request->getData(); + + $this->assertSame('1:[DVD-123]Pioneer NSDV99 DVD-Surround Sound System:3:4.35:2:6.35:19.05', $data['Basket']); + } + + public function testNonXmlBasketWithSpecialAndNonSpecialCharacters() + { + $this->request->setUseOldBasketFormat(true); + + $items = new \Omnipay\Common\ItemBag(array( + new \Omnipay\SagePay\Extend\Item(array( + // [] and ::: are reserved + 'name' => "[SKU-ABC]Pioneer::: NSDV99 DVD-Surround Sound System .-{};_@()", + 'quantity' => 3, + 'price' => 4.35, + 'vat' => 2, + )), + )); + + $this->request->setItems($items); + $data = $this->request->getData(); + + $this->assertSame('1:[SKU-ABC]Pioneer NSDV99 DVD-Surround Sound System .-{};_@():3:4.35:2:6.35:19.05', $data['Basket']); + } + public function testCreateTokenCanBeSetInRequest() { $this->request->setCreateToken(true);