Skip to content
This repository has been archived by the owner on Mar 29, 2022. It is now read-only.

Commit

Permalink
Merge pull request #140 from heidelpay/change/PHPLIB-200/add-effectiv…
Browse files Browse the repository at this point in the history
…e-interest-to-paypage

change/PHPLIB-200/add-effective-interest-to-paypage
  • Loading branch information
Simon Gabriel authored Nov 19, 2019
2 parents e7c621b + 3affe6c commit da1c735
Show file tree
Hide file tree
Showing 11 changed files with 274 additions and 67 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) a
* Added card details to `Card` payment type.
* Property `card3ds` to `Paypage`.
* Geolocation to `Customer` resource.
* Property `effectiveInterestRate` to `PayPage` to enable `HirePurchase` payment types.

### Changed
* Refactor invoice guaranteed tests to make them independent from each other.
Expand Down
16 changes: 13 additions & 3 deletions examples/EmbeddedPayPage/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@
use heidelpayPHP\examples\ExampleDebugHandler;
use heidelpayPHP\Exceptions\HeidelpayApiException;
use heidelpayPHP\Heidelpay;
use heidelpayPHP\Resources\Basket;
use heidelpayPHP\Resources\CustomerFactory;
use heidelpayPHP\Resources\EmbeddedResources\BasketItem;
use heidelpayPHP\Resources\PaymentTypes\Paypage;

// start new session for this example and remove all parameters
Expand All @@ -59,7 +61,7 @@
$customer = CustomerFactory::createCustomer('Max', 'Mustermann');

// These are the mandatory parameters for the payment page ...
$paypage = new Paypage(12.99, 'EUR', RETURN_CONTROLLER_URL);
$paypage = new Paypage(119.00, 'EUR', RETURN_CONTROLLER_URL);

// ... however you can customize the Payment Page using additional parameters.
$paypage->setLogoImage('https://dev.heidelpay.com/devHeidelpay_400_180.jpg')
Expand All @@ -68,10 +70,18 @@
->setOrderId('OrderNr' . microtime(true))
->setInvoiceId('InvoiceNr' . microtime(true));

// ... in order to enable FlexiPay Rate (Hire Purchase) you will need to set the effectiveInterestRate as well.
$paypage->setEffectiveInterestRate(4.99);

// ... a Basket is mandatory for HirePurchase
$orderId = str_replace(['0.', ' '], '', microtime(false));
$basketItem = new BasketItem('Hat', 100.0, 119.0, 1);
$basket = new Basket($orderId, 119.0, 'EUR', [$basketItem]);

if ($transactionType === 'charge') {
$heidelpay->initPayPageCharge($paypage, $customer);
$heidelpay->initPayPageCharge($paypage, $customer, $basket);
} else {
$heidelpay->initPayPageAuthorize($paypage, $customer);
$heidelpay->initPayPageAuthorize($paypage, $customer, $basket);
}

$_SESSION['PaymentId'] = $paypage->getPaymentId();
Expand Down
19 changes: 15 additions & 4 deletions examples/HostedPayPage/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@
use heidelpayPHP\examples\ExampleDebugHandler;
use heidelpayPHP\Exceptions\HeidelpayApiException;
use heidelpayPHP\Heidelpay;
use heidelpayPHP\Resources\Basket;
use heidelpayPHP\Resources\CustomerFactory;
use heidelpayPHP\Resources\EmbeddedResources\BasketItem;
use heidelpayPHP\Resources\PaymentTypes\Paypage;

session_start();
Expand Down Expand Up @@ -64,26 +66,35 @@ function redirect($url, $merchantMessage = '', $clientMessage = '')
$customer = CustomerFactory::createCustomer('Max', 'Mustermann');

// These are the mandatory parameters for the payment page ...
$paypage = new Paypage(12.99, 'EUR', RETURN_CONTROLLER_URL);
$paypage = new Paypage(119.0, 'EUR', RETURN_CONTROLLER_URL);

$orderId = str_replace(['0.', ' '], '', microtime(false));

// ... however you can customize the Payment Page using additional parameters.
$paypage->setLogoImage('https://dev.heidelpay.com/devHeidelpay_400_180.jpg')
->setFullPageImage('https://www.heidelpay.com/fileadmin/content/header-Imges-neu/Header_Phone_12.jpg')
->setShopName('My Test Shop')
->setShopDescription('Best shop in the whole world!')
->setTagline('Try and stop us from being awesome!')
->setOrderId('OrderNr' . microtime(true))
->setOrderId('OrderNr' . $orderId)
->setTermsAndConditionUrl('https://www.heidelpay.com/en/')
->setPrivacyPolicyUrl('https://www.heidelpay.com/de/')
->setImprintUrl('https://www.heidelpay.com/it/')
->setHelpUrl('https://www.heidelpay.com/at/')
->setContactUrl('https://www.heidelpay.com/en/about-us/about-heidelpay/')
->setInvoiceId('InvoiceNr' . microtime(true));

// ... in order to enable FlexiPay Rate (Hire Purchase) you will need to set the effectiveInterestRate as well.
$paypage->setEffectiveInterestRate(4.99);

// ... a Basket is mandatory for HirePurchase
$basketItem = new BasketItem('Hat', 100.0, 119.0, 1);
$basket = new Basket($orderId, 119.0, 'EUR', [$basketItem]);

if ($transactionType === 'charge') {
$heidelpay->initPayPageCharge($paypage, $customer);
$heidelpay->initPayPageCharge($paypage, $customer, $basket);
} else {
$heidelpay->initPayPageAuthorize($paypage, $customer);
$heidelpay->initPayPageAuthorize($paypage, $customer, $basket);
}

$_SESSION['PaymentId'] = $paypage->getPaymentId();
Expand Down
12 changes: 9 additions & 3 deletions examples/HostedPayPage/ReturnController.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
use heidelpayPHP\Heidelpay;
use heidelpayPHP\Resources\AbstractHeidelpayResource;
use heidelpayPHP\Resources\Payment;
use heidelpayPHP\Resources\TransactionTypes\AbstractTransactionType;
use heidelpayPHP\Resources\TransactionTypes\Authorization;
use heidelpayPHP\Resources\TransactionTypes\Charge;

Expand Down Expand Up @@ -84,7 +85,10 @@ function getTransaction(Payment $payment)

// You'll need to remember the shortId to show it on the success or failure page
$transaction = getTransaction($payment);
$_SESSION['ShortId'] = $transaction->getShortId();

if ($transaction instanceof AbstractTransactionType) {
$_SESSION['ShortId'] = $transaction->getShortId();
}

if ($payment->isCompleted()) {
// The payment process has been successful.
Expand All @@ -106,8 +110,10 @@ function getTransaction(Payment $payment)
// In this case do not create the order.
// Redirect to an error page in your shop and show an message if you want.

// For better debugging log the error message in your error log
$merchantMessage = $transaction->getMessage()->getCustomer();
if ($transaction instanceof AbstractTransactionType) {
// For better debugging log the error message in your error log
$merchantMessage = $transaction->getMessage()->getCustomer();
}

} catch (HeidelpayApiException $e) {
$merchantMessage = $e->getMerchantMessage();
Expand Down
180 changes: 128 additions & 52 deletions src/Resources/AbstractHeidelpayResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
*
* @author Simon Gabriel <[email protected]>
*
* @package heidelpayPHP/resources
* @package heidelpayPHP/Resources
*/
namespace heidelpayPHP\Resources;

Expand All @@ -31,6 +31,7 @@
use heidelpayPHP\Interfaces\HeidelpayParentInterface;
use heidelpayPHP\Services\ResourceNameService;
use heidelpayPHP\Services\ResourceService;
use heidelpayPHP\Services\ValueService;
use ReflectionException;
use ReflectionProperty;
use RuntimeException;
Expand All @@ -55,6 +56,9 @@ abstract class AbstractHeidelpayResource implements HeidelpayParentInterface
/** @var array $specialParams */
private $specialParams = [];

/** @var array $additionalAttributes */
protected $additionalAttributes = [];

//<editor-fold desc="Getters/Setters">

/**
Expand Down Expand Up @@ -156,6 +160,52 @@ public function setSpecialParams(array $specialParams): self
return $this;
}

/**
* @return array
*/
protected function getAdditionalAttributes(): array
{
return $this->additionalAttributes;
}

/**
* @param array $additionalAttributes
*
* @return AbstractHeidelpayResource
*/
protected function setAdditionalAttributes(array $additionalAttributes): AbstractHeidelpayResource
{
$this->additionalAttributes = $additionalAttributes;
return $this;
}

/**
* Adds the given value to the additionalAttributes array if it is not set yet.
* Overwrites the given value if it already exists.
*
* @param string $attribute
* @param mixed $value
*
* @return AbstractHeidelpayResource
*/
protected function setAdditionalAttribute(string $attribute, $value): AbstractHeidelpayResource
{
$this->additionalAttributes[$attribute] = $value;
return $this;
}

/**
* Returns the value of the given attribute or null if it is not set.
*
* @param string $attribute
*
* @return mixed
*/
protected function getAdditionalAttribute(string $attribute)
{
return $this->additionalAttributes[$attribute] ?? null;
}

//</editor-fold>

//<editor-fold desc="Helpers">
Expand Down Expand Up @@ -228,49 +278,6 @@ private static function updateValues($object, stdClass $response)
}
}

/**
* @param $item
* @param $key
* @param $value
*/
private static function setItemProperty($item, $key, $value)
{
$setter = 'set' . ucfirst($key);
if (!is_callable([$item, $setter])) {
$setter = 'add' . ucfirst($key);
}
if (is_callable([$item, $setter])) {
$item->$setter($value);
}
}

/**
* Returns true if the given property should be skipped.
*
* @param $property
* @param $value
*
* @return bool
*/
private static function propertyShouldBeSkipped($property, $value): bool
{
$skipProperty = false;

try {
$reflection = new ReflectionProperty(static::class, $property);
if ($value === null || // do not send properties that are set to null
($property === 'id' && empty($value)) || // do not send id property if it is empty
!$reflection->isProtected()) { // only send protected properties
$skipProperty = true;
}
} /** @noinspection BadExceptionsProcessingInspection */
catch (ReflectionException $e) {
$skipProperty = true;
}

return $skipProperty;
}

//</editor-fold>

//<editor-fold desc="Resource service facade">
Expand Down Expand Up @@ -350,10 +357,19 @@ public function expose()
$value = $value->expose();
}

// reduce floats to 4 decimal places
// reduce floats to 4 decimal places and update the property in object
if (is_float($value)) {
$value = round($value, 4);
$this->$property = $value;
$value = ValueService::limitFloats($value);
self::setItemProperty($this, $property, $value);
}

// handle additional values
if ($property === 'additionalAttributes') {
if (!is_array($value) || empty($value)) {
unset($properties[$property]);
continue;
}
$value = $this->exposeAdditionalAttributes($value);
}

$properties[$property] = $value;
Expand All @@ -363,11 +379,11 @@ public function expose()
// Add linked resources if any
$resources = [];
/**
* @var string $key
* @var string $attributeName
* @var AbstractHeidelpayResource $linkedResource
*/
foreach ($this->getLinkedResources() as $key => $linkedResource) {
$resources[$key . 'Id'] = $linkedResource ? $linkedResource->getId() : '';
foreach ($this->getLinkedResources() as $attributeName => $linkedResource) {
$resources[$attributeName . 'Id'] = $linkedResource ? $linkedResource->getId() : '';
}

if (count($resources) > 0) {
Expand All @@ -377,15 +393,75 @@ public function expose()
//---------------------

// Add special params if any
foreach ($this->getSpecialParams() as $key => $specialParam) {
$properties[$key] = $specialParam;
foreach ($this->getSpecialParams() as $attributeName => $specialParam) {
$properties[$attributeName] = $specialParam;
}
//---------------------

ksort($properties);
return count($properties) > 0 ? $properties : new stdClass();
}

/**
* @param $value
*
* @return array
*/
private function exposeAdditionalAttributes($value): array
{
foreach ($value as $attributeName => $attributeValue) {
$attributeValue = ValueService::limitFloats($attributeValue);
$value[$attributeName] = $attributeValue;
$this->setAdditionalAttribute($attributeName, $attributeValue);
}
return $value;
}

/**
* Returns true if the given property should be skipped.
*
* @param $property
* @param $value
*
* @return bool
*/
private static function propertyShouldBeSkipped($property, $value): bool
{
$skipProperty = false;

try {
$reflection = new ReflectionProperty(static::class, $property);
if ($value === null || // do not send properties that are set to null
($property === 'id' && empty($value)) || // do not send id property if it is empty
!$reflection->isProtected()) { // only send protected properties
$skipProperty = true;
}
} /** @noinspection BadExceptionsProcessingInspection */
catch (ReflectionException $e) {
$skipProperty = true;
}

return $skipProperty;
}

/**
* Can not be moved to service since setters and getters are most likely private.
*
* @param $item
* @param $key
* @param $value
*/
private static function setItemProperty($item, $key, $value)
{
$setter = 'set' . ucfirst($key);
if (!is_callable([$item, $setter])) {
$setter = 'add' . ucfirst($key);
}
if (is_callable([$item, $setter])) {
$item->$setter($value);
}
}

//</editor-fold>

//<editor-fold desc="Overridable Methods">
Expand Down
Loading

0 comments on commit da1c735

Please sign in to comment.