diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 6b8448a..ebb0dd0 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,6 +1,7 @@
stages:
- setup
- test
+ - deploy
- package
cache:
@@ -64,6 +65,7 @@ sw-phpstan:
- cd ${CI_PROJECT_DIR}/sw_dir/custom/plugins/${CI_PROJECT_NAME} && vendor/bin/phpstan analyse -c phpstan_sw.neon -a vendor/autoload.php -a ../../../vendor/autoload.php .
shopware-validate:
+ allow_failure: true
image:
name: friendsofshopware/plugin-uploader:0.3.5
entrypoint: [ "/bin/sh", "-c" ]
@@ -81,9 +83,34 @@ shopware-validate:
- php /app/bin/pluginupload ext:zip . $CI_COMMIT_SHA
- php /app/bin/pluginupload ext:validate *$CI_COMMIT_SHA.zip
+staging:
+ image: "edbizarro/gitlab-ci-pipeline-php:7.2"
+ stage: deploy
+ environment:
+ name: staging
+ url: https://unzer-sw5.kellerkinder.io
+ only:
+ - master
+ before_script:
+ # Run ssh-agent (inside the build environment)
+ - eval $(ssh-agent -s)
+
+ # Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store
+ - ssh-add <(echo "$SSH_PRIVATE_KEY")
+
+ # For Docker builds disable host key checking. Be aware that by adding that
+ # you are suspectible to man-in-the-middle attacks.
+ # WARNING: Use this only with the Docker executor, if you use it with shell
+ # you will overwrite your user's SSH config.
+ - mkdir -p ~/.ssh
+ - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
+ script:
+ - ssh -A web-user@c-140.maxcluster.net 'cd /var/www/share/unzer-sw5.kellerkinder.io/htdocs/custom/plugins/HeidelPayment && git pull && /var/www/share/unzer-sw5.kellerkinder.io/htdocs/bin/console sw:cache:clear && /var/www/share/unzer-sw5.kellerkinder.io/htdocs/bin/console sw:plugin:refresh && /var/www/share/unzer-sw5.kellerkinder.io/htdocs/bin/console sw:plugin:uninstall HeidelPayment && /var/www/share/unzer-sw5.kellerkinder.io/htdocs/bin/console sw:plugin:install --activate HeidelPayment && /var/www/share/unzer-sw5.kellerkinder.io/htdocs/bin/console sw:theme:cache:generate'
+
package:
image: kellerkinder/shopware-package-plugin:latest
stage: package
+ needs: []
only:
- tags
- master
diff --git a/Components/HeidelpayDebugHandler.php b/Components/HeidelpayDebugHandler.php
new file mode 100644
index 0000000..76fcf1d
--- /dev/null
+++ b/Components/HeidelpayDebugHandler.php
@@ -0,0 +1,24 @@
+logger = $logger;
+ }
+
+ public function log(string $message): void
+ {
+ $this->logger->info($message);
+ }
+}
diff --git a/Components/Hydrator/ResourceHydrator/BasketHydrator.php b/Components/Hydrator/ResourceHydrator/BasketHydrator.php
index 38bb8b2..0157c4c 100644
--- a/Components/Hydrator/ResourceHydrator/BasketHydrator.php
+++ b/Components/Hydrator/ResourceHydrator/BasketHydrator.php
@@ -13,6 +13,8 @@
class BasketHydrator implements ResourceHydratorInterface
{
+ public const UNZER_DEFAULT_PRECISION = 4;
+
private const SW_VOUCHER_MODE = '2';
private const SW_DISCOUNT = '3';
private const SW_ABO_DISCOUNT_MODE = '10';
@@ -31,91 +33,99 @@ public function hydrateOrFetch(
return $heidelpayObj->fetchBasket($resourceId);
}
- $isAmountInNet = isset($data['sAmountWithTax']);
- $isTaxFree = $data['taxFree'];
- $amountTotalGrossTransaction = $isAmountInNet && !$isTaxFree ? $data['sAmountWithTax'] : $data['sAmount'];
+ $isAmountInNet = isset($data['sAmountWithTax']);
+ $isTaxFree = $data['taxFree'];
+ $amountTotalGross = $isAmountInNet && !$isTaxFree ? $data['sAmountWithTax'] : $data['sAmount'];
- $basketAmountTotalGross = 0;
- $basketAmountTotalVat = 0;
- $basketAmountTotalDiscount = 0;
+ $basket = new Basket(
+ $this->generateOrderId(),
+ round($amountTotalGross, self::UNZER_DEFAULT_PRECISION),
+ $data['sCurrencyName']
+ );
- $result = new Basket();
- $result->setCurrencyCode($data['sCurrencyName']);
- $result->setOrderId($this->generateOrderId());
+ $basket->setAmountTotalVat(round($data['sAmountTax'], self::UNZER_DEFAULT_PRECISION));
- //Actual line items
- foreach ($data['content'] as $lineItem) {
- $amountNet = abs($lineItem['amountnetNumeric']);
- $amountGross = $isAmountInNet ? abs($lineItem['amountWithTax']) : abs($lineItem['amountNumeric']);
- $amountPerUnit = $isAmountInNet
- ? $amountGross / $lineItem['quantity']
- : abs($lineItem['additional_details']['price_numeric']);
+ $this->hydrateBasketItems($basket, $data['content'], $isAmountInNet);
+ $this->hydrateDispatch($basket, $data);
+ $this->hydrateDiscount($basket);
- if (!$amountPerUnit) {
- $amountPerUnit = abs($lineItem['priceNumeric']);
- }
+ return $basket;
+ }
+ protected function hydrateBasketItems(Basket $basket, array $lineItems, bool $isAmountInNet): void
+ {
+ foreach ($lineItems as $lineItem) {
$basketItem = new BasketItem();
+ $basketItem->setType($this->getBasketItemType($lineItem));
+ $basketItem->setTitle($lineItem['articlename']);
+ $basketItem->setQuantity((int) $lineItem['quantity']);
- if ($this->isBasketItemVoucher($lineItem)) {
- $basketItem->setType($this->getBasketItemType($lineItem));
- $basketItem->setTitle($lineItem['articlename']);
- $basketItem->setAmountDiscount(round($amountGross, 4));
- $basketItem->setQuantity((int) $lineItem['quantity']);
+ $amountGross = round(abs(
+ $isAmountInNet ? $lineItem['amountWithTax'] : $lineItem['amountNumeric']
+ ), self::UNZER_DEFAULT_PRECISION);
- $basketAmountTotalDiscount += $basketItem->getAmountDiscount();
+ if ($this->isBasketItemVoucher($lineItem)) {
+ $basketItem->setAmountDiscount($amountGross);
} else {
- $basketItem->setType($this->getBasketItemType($lineItem));
- $basketItem->setTitle($lineItem['articlename']);
- $basketItem->setAmountPerUnit(round($amountPerUnit, 4));
- $basketItem->setAmountGross(round($amountGross, 4));
- $basketItem->setAmountNet(round($amountNet, 4));
- $basketItem->setAmountVat(round(abs(str_replace(',', '.', $lineItem['tax'])), 4));
- $basketItem->setQuantity((int) $lineItem['quantity']);
+ $amountPerUnit = $isAmountInNet
+ ? $amountGross / $lineItem['quantity']
+ : abs($lineItem['additional_details']['price_numeric']);
+
+ if (!$amountPerUnit) {
+ $amountPerUnit = abs($lineItem['priceNumeric']);
+ }
+
+ $basketItem->setAmountPerUnit(round($amountPerUnit, self::UNZER_DEFAULT_PRECISION));
+ $basketItem->setAmountGross($amountGross);
+ $basketItem->setAmountNet(round(abs($lineItem['amountnetNumeric']), self::UNZER_DEFAULT_PRECISION));
+ $basketItem->setAmountVat(round(abs(str_replace(',', '.', $lineItem['tax'])), self::UNZER_DEFAULT_PRECISION));
$basketItem->setVat((float) $lineItem['tax_rate']);
-
- $basketAmountTotalGross += $basketItem->getAmountGross();
- $basketAmountTotalVat += $basketItem->getAmountVat();
}
- if ($lineItem['abo_attributes']['isAboArticle']) {
- $result->setSpecialParams(array_merge($result->getSpecialParams(), ['isAbo' => true]));
+ if (array_key_exists('abo_attributes', $lineItem) && !empty($lineItem['abo_attributes'])
+ && array_key_exists('isAboArticle', $lineItem['abo_attributes']) && !empty($lineItem['abo_attributes']['isAboArticle'])) {
+ $basket->setSpecialParams(array_merge($basket->getSpecialParams(), ['isAbo' => true]));
$basketItem->setSpecialParams([
'aboCommerce' => $lineItem['aboCommerce'],
]);
}
- $result->addBasketItem($basketItem);
+ $basket->addBasketItem($basketItem);
}
+ }
- //No dispatch selected!
- if (empty($data['sDispatch'])) {
- return $result;
+ protected function hydrateDispatch(Basket $basket, array $data): void
+ {
+ if (!array_key_exists('sDispatch', $data) || empty($data['sDispatch'])) {
+ return;
}
//Shipping cost line item
$dispatchBasketItem = new BasketItem();
$dispatchBasketItem->setType(BasketItemTypes::SHIPMENT);
$dispatchBasketItem->setTitle($data['sDispatch']['name']);
- $dispatchBasketItem->setAmountGross(round($data['sShippingcostsWithTax'], 4));
- $dispatchBasketItem->setAmountPerUnit(round($data['sShippingcostsWithTax'], 4));
- $dispatchBasketItem->setAmountNet(round($data['sShippingcostsNet'], 4));
- $dispatchBasketItem->setAmountVat(round($data['sShippingcostsWithTax'] - $data['sShippingcostsNet'], 4));
- $dispatchBasketItem->setQuantity(1);
+ $dispatchBasketItem->setAmountGross(round($data['sShippingcostsWithTax'], self::UNZER_DEFAULT_PRECISION));
+ $dispatchBasketItem->setAmountPerUnit(round($data['sShippingcostsWithTax'], self::UNZER_DEFAULT_PRECISION));
+ $dispatchBasketItem->setAmountNet(round($data['sShippingcostsNet'], self::UNZER_DEFAULT_PRECISION));
+ $dispatchBasketItem->setAmountVat(round($data['sShippingcostsWithTax'] - $data['sShippingcostsNet'], self::UNZER_DEFAULT_PRECISION));
$dispatchBasketItem->setVat((float) $data['sShippingcostsTax']);
+ $dispatchBasketItem->setQuantity(1);
- $result->addBasketItem($dispatchBasketItem);
+ $basket->addBasketItem($dispatchBasketItem);
+ }
- $basketAmountTotalGross += $dispatchBasketItem->getAmountGross();
- $basketAmountTotalVat += $dispatchBasketItem->getAmountVat();
- $basketAmountTotalDiscount += $dispatchBasketItem->getAmountDiscount();
+ protected function hydrateDiscount(Basket $basket): void
+ {
+ $calculatedDiscount = 0;
- // setting of all totalAmounts
- $result->setAmountTotalGross(round((float) $basketAmountTotalGross, 4));
- $result->setAmountTotalVat(round((float) $basketAmountTotalVat, 4));
- $result->setAmountTotalDiscount(round((float) $basketAmountTotalDiscount, 4));
+ /** @var BasketItem $basketItem */
+ foreach ($basket->getBasketItems() as $basketItem) {
+ if ((int) round($basketItem->getAmountDiscount(), self::UNZER_DEFAULT_PRECISION) !== 0) {
+ $calculatedDiscount += round($basketItem->getAmountDiscount(), self::UNZER_DEFAULT_PRECISION);
+ }
+ }
- return $result;
+ $basket->setAmountTotalDiscount($calculatedDiscount);
}
private function generateOrderId(): string
diff --git a/Components/Hydrator/ResourceHydrator/CustomerHydrator/AbstractCustomerHydrator.php b/Components/Hydrator/ResourceHydrator/CustomerHydrator/AbstractCustomerHydrator.php
index bad0b4b..a2e65e3 100644
--- a/Components/Hydrator/ResourceHydrator/CustomerHydrator/AbstractCustomerHydrator.php
+++ b/Components/Hydrator/ResourceHydrator/CustomerHydrator/AbstractCustomerHydrator.php
@@ -10,6 +10,12 @@
abstract class AbstractCustomerHydrator
{
+ /*
+ * This regex is used to remove any non whitespace, plus or number parts,
+ * while also removing occurrences of more than one whitespace at a time.
+ */
+ public const PHONE_NUMBER_REGEX = '/([^0-9 +]|\s{2,})/';
+
/** @var Connection */
protected $connection;
diff --git a/Components/Hydrator/ResourceHydrator/CustomerHydrator/PrivateCustomerHydrator.php b/Components/Hydrator/ResourceHydrator/CustomerHydrator/PrivateCustomerHydrator.php
index a074da6..89fc836 100644
--- a/Components/Hydrator/ResourceHydrator/CustomerHydrator/PrivateCustomerHydrator.php
+++ b/Components/Hydrator/ResourceHydrator/CustomerHydrator/PrivateCustomerHydrator.php
@@ -27,6 +27,8 @@ public function hydrateOrFetch(
$shippingAddress = $data['shippingaddress'];
$billingAddress = $data['billingaddress'];
+ $phoneNumber = \preg_replace(self::PHONE_NUMBER_REGEX, '', $billingAddress['phone']);
+
try {
if ($heidelpayObj) {
$result = $heidelpayObj->fetchCustomerByExtCustomerId($resourceId);
@@ -43,7 +45,7 @@ public function hydrateOrFetch(
$result->setEmail($user['email']);
$result->setSalutation($this->getSalutation($billingAddress['salutation']));
$result->setCustomerId($user['customernumber']);
- $result->setPhone($billingAddress['phone']);
+ $result->setPhone($phoneNumber);
$result->setBillingAddress($this->getHeidelpayAddress($billingAddress));
$result->setShippingAddress($this->getHeidelpayAddress($shippingAddress));
diff --git a/Controllers/AbstractHeidelpayPaymentController.php b/Controllers/AbstractHeidelpayPaymentController.php
index 4ba9c20..674bc96 100644
--- a/Controllers/AbstractHeidelpayPaymentController.php
+++ b/Controllers/AbstractHeidelpayPaymentController.php
@@ -183,7 +183,7 @@ public function recurring(): void
}
$heidelBasket = $this->getRecurringBasket($recurringData['order']);
- $this->paymentDataStruct = new PaymentDataStruct($heidelBasket->getAmountTotalGross(), $recurringData['order']['currency'], $this->getChargeRecurringUrl());
+ $this->paymentDataStruct = new PaymentDataStruct($this->getAmount(), $recurringData['order']['currency'], $this->getChargeRecurringUrl());
$this->paymentDataStruct->fromArray([
'basket' => $heidelBasket,
diff --git a/Controllers/Widgets/HeidelpayCreditCard.php b/Controllers/Widgets/HeidelpayCreditCard.php
index 80fa1fb..069cc66 100644
--- a/Controllers/Widgets/HeidelpayCreditCard.php
+++ b/Controllers/Widgets/HeidelpayCreditCard.php
@@ -23,7 +23,7 @@ public function createPaymentAction(): void
{
parent::pay();
- if ($this->paymentDataStruct->isRecurring()) {
+ if (!$this->paymentType && $this->paymentDataStruct->isRecurring()) {
$activateRecurring = false;
try {
@@ -41,9 +41,19 @@ public function createPaymentAction(): void
return;
}
+
+ if ($this->recurring->getRedirectUrl() !== null) {
+ $this->view->assign('redirectUrl', $this->recurring->getRedirectUrl());
+
+ return;
+ }
}
- $this->handleNormalPayment();
+ if ($this->paymentType && $this->paymentType->isRecurring()) {
+ $this->recurringFinishedAction();
+ } else {
+ $this->handleNormalPayment();
+ }
}
public function chargeRecurringPaymentAction(): void
@@ -57,9 +67,8 @@ public function chargeRecurringPaymentAction(): void
return;
}
- $this->handleNormalPayment();
-
try {
+ $this->charge($this->paymentDataStruct->getReturnUrl());
$orderNumber = $this->createRecurringOrder();
} catch (HeidelpayApiException $ex) {
$this->getApiLogger()->logException($ex->getMessage(), $ex);
@@ -73,6 +82,47 @@ public function chargeRecurringPaymentAction(): void
}
}
+ protected function recurringFinishedAction(): void
+ {
+ try {
+ parent::pay();
+
+ if (!$this->paymentType) {
+ $session = $this->container->get('session');
+ $paymentTypeId = $session->offsetGet('PaymentTypeId');
+ $this->paymentType = $this->heidelpayClient->fetchPaymentType($paymentTypeId);
+ }
+
+ if (!$this->paymentType->isRecurring()) {
+ $this->getApiLogger()->getPluginLogger()->warning('Recurring could not be activated for basket', [$this->paymentDataStruct->getBasket()->jsonSerialize()]);
+ $redirectUrl = $this->getHeidelpayErrorUrlFromSnippet('recurringError');
+ }
+
+ $bookingMode = $this->container->get('heidel_payment.services.config_reader')->get('credit_card_bookingmode');
+
+ if (in_array($bookingMode, [BookingMode::CHARGE, BookingMode::CHARGE_REGISTER])) {
+ $redirectUrl = $this->charge($this->paymentDataStruct->getReturnUrl());
+ } elseif (in_array($bookingMode, [BookingMode::AUTHORIZE, BookingMode::AUTHORIZE_REGISTER])) {
+ $redirectUrl = $this->authorize($this->paymentDataStruct->getReturnUrl());
+ }
+
+ $this->saveToDeviceVault($bookingMode);
+ } catch (HeidelpayApiException $ex) {
+ $this->getApiLogger()->logException('Error while creating CreditCard recurring payment', $ex);
+ $redirectUrl = $this->getHeidelpayErrorUrl($ex->getClientMessage());
+ } catch (RuntimeException $ex) {
+ $redirectUrl = $this->getHeidelpayErrorUrlFromSnippet('communicationError');
+ } finally {
+ if (!$redirectUrl) {
+ $this->getApiLogger()->getPluginLogger()->warning('CreditCard is not chargeable for basket', [$this->paymentDataStruct->getBasket()->jsonSerialize()]);
+
+ $redirectUrl = $this->getHeidelpayErrorUrlFromSnippet('communicationError');
+ }
+
+ $this->view->assign('redirectUrl', $redirectUrl);
+ }
+ }
+
private function handleNormalPayment(): void
{
$bookingMode = $this->container->get('heidel_payment.services.config_reader')->get('credit_card_bookingmode');
diff --git a/Controllers/Widgets/HeidelpayPaypal.php b/Controllers/Widgets/HeidelpayPaypal.php
index 93b7300..1a08640 100644
--- a/Controllers/Widgets/HeidelpayPaypal.php
+++ b/Controllers/Widgets/HeidelpayPaypal.php
@@ -52,7 +52,35 @@ public function createPaymentAction(): void
}
}
- public function recurringFinishedAction(): void
+ public function chargeRecurringPaymentAction(): void
+ {
+ parent::recurring();
+
+ if (!$this->paymentDataStruct) {
+ $this->getApiLogger()->getPluginLogger()->error('The payment data struct could not be created');
+ $this->view->assign('success', false);
+
+ return;
+ }
+
+ try {
+ $this->charge($this->paymentDataStruct->getReturnUrl());
+ $orderNumber = $this->createRecurringOrder();
+ } catch (HeidelpayApiException $ex) {
+ $this->getApiLogger()->logException($ex->getMessage(), $ex);
+ } catch (RuntimeException $ex) {
+ $this->getApiLogger()->getPluginLogger()->error($ex->getMessage(), $ex);
+ } finally {
+ $this->view->assign([
+ 'success' => !empty($orderNumber),
+ 'data' => [
+ 'orderNumber' => $orderNumber ?: '',
+ ],
+ ]);
+ }
+ }
+
+ protected function recurringFinishedAction(): void
{
try {
parent::pay();
@@ -91,34 +119,6 @@ public function recurringFinishedAction(): void
}
}
- public function chargeRecurringPaymentAction(): void
- {
- parent::recurring();
-
- if (!$this->paymentDataStruct) {
- $this->getApiLogger()->getPluginLogger()->error('The payment data struct could not be created');
- $this->view->assign('success', false);
-
- return;
- }
-
- try {
- $this->charge($this->paymentDataStruct->getReturnUrl());
- $orderNumber = $this->createRecurringOrder();
- } catch (HeidelpayApiException $ex) {
- $this->getApiLogger()->logException($ex->getMessage(), $ex);
- } catch (RuntimeException $ex) {
- $this->getApiLogger()->getPluginLogger()->error($ex->getMessage(), $ex);
- } finally {
- $this->view->assign([
- 'success' => !empty($orderNumber),
- 'data' => [
- 'orderNumber' => $orderNumber ?: '',
- ],
- ]);
- }
- }
-
private function handleRecurringPayment(): void
{
$redirectUrl = $this->paymentDataStruct->getReturnUrl();
diff --git a/Resources/frontend/js/jquery.heidelpay-base.js b/Resources/frontend/js/jquery.heidelpay-base.js
index f408a4f..0b16eed 100644
--- a/Resources/frontend/js/jquery.heidelpay-base.js
+++ b/Resources/frontend/js/jquery.heidelpay-base.js
@@ -51,7 +51,7 @@
redirectToErrorPage: function (message) {
var encodedMessage = encodeURIComponent(message);
- window.location = `${this.opts.heidelpayErrorUrl}${encodedMessage}`;
+ window.location = this.opts.heidelpayErrorUrl + encodedMessage;
},
setSubmitButtonActive: function (active) {
@@ -117,11 +117,11 @@
return message;
},
- getFormattedBirthday(htmlTarget) {
+ getFormattedBirthday: function (htmlTarget) {
var datePickerPlugin = $(htmlTarget).data('plugin_swDatePicker'),
flatpickr = null,
currentValue = null,
- formattedDate = null,
+ splitted = [],
dateValue = null;
if (!datePickerPlugin) {
@@ -140,37 +140,27 @@
currentValue = $(datePickerPlugin.flatpickr._input).val();
}
- dateValue = new Date(currentValue);
+ if (!currentValue.includes('.')) {
+ return null;
+ }
- if (dateValue.toString() === 'Invalid Date') {
- if (currentValue.includes('.')) {
- var splitted = currentValue.split('.');
-
- if (splitted.length === 3) {
- dateValue = new Date(`${splitted[2]}-${splitted[1]}-${splitted[0]}`);
-
- if (dateValue.toString() !== 'Invalid Date') {
- try {
- formattedDate = flatpickr.formatDate(dateValue, datePickerPlugin.opts.dateFormat);
- } catch (e) {
- return null;
- }
- }
- }
- }
- } else {
- try {
- formattedDate = flatpickr.formatDate(dateValue, datePickerPlugin.opts.dateFormat);
- } catch (e) {
- return null;
- }
+ splitted = currentValue.split('.');
+
+ if (splitted.length !== 3) {
+ return null;
}
- if (new Date(formattedDate).toString() === 'Invalid Date') {
+ dateValue = new Date(splitted[2] + '-' + splitted[1] + '-' + splitted[0]);
+
+ if (dateValue.toString() === 'Invalid Date') {
return null;
}
- return formattedDate;
+ try {
+ return flatpickr.formatDate(dateValue, datePickerPlugin.opts.dateFormat);
+ } catch (e) {
+ return null;
+ }
}
});
diff --git a/Resources/frontend/js/jquery.heidelpay-credit-card.js b/Resources/frontend/js/jquery.heidelpay-credit-card.js
index ef45fc4..e070a7a 100644
--- a/Resources/frontend/js/jquery.heidelpay-credit-card.js
+++ b/Resources/frontend/js/jquery.heidelpay-credit-card.js
@@ -103,7 +103,7 @@
setValidationError: function (type, message) {
var $element = this.getEventElement(type),
- $elementLabel = $(`#card-element-error-${type}-label`);
+ $elementLabel = $('#card-element-error-' + type + '-label');
if (message) {
$elementLabel.removeClass(this.opts.elementHiddenClass);
@@ -136,7 +136,7 @@
},
getEventElement: function (type) {
- return $(`*[data-type="${type}"]`);
+ return $('*[data-type="' + type + '"]');
},
onFormChange: function (event) {
diff --git a/Resources/frontend/js/jquery.heidelpay-hire-purchase.js b/Resources/frontend/js/jquery.heidelpay-hire-purchase.js
index bfc61a6..4f2c843 100644
--- a/Resources/frontend/js/jquery.heidelpay-hire-purchase.js
+++ b/Resources/frontend/js/jquery.heidelpay-hire-purchase.js
@@ -51,7 +51,7 @@
amount: this.opts.basketAmount,
currency: this.opts.currencyIso,
effectiveInterest: this.opts.effectiveInterest
- }).then(() => {
+ }).then(function() {
$(me.opts.generatedBirthdayElementSelector).attr('required', 'required');
$(me.opts.generatedBirthdayElementSelector).attr('form', 'confirm--form');
}).catch(function() {
diff --git a/Resources/frontend/js/jquery.heidelpay-invoice-factoring.js b/Resources/frontend/js/jquery.heidelpay-invoice-factoring.js
index e30338b..0d4b509 100644
--- a/Resources/frontend/js/jquery.heidelpay-invoice-factoring.js
+++ b/Resources/frontend/js/jquery.heidelpay-invoice-factoring.js
@@ -104,7 +104,7 @@
var me = this,
birthDate = this.heidelpayPlugin.getFormattedBirthday(this.opts.birthdayElementSelector);
- if (!birthDate) {
+ if (!birthDate && !this.opts.isB2bCustomer) {
me.onError({ message: me.heidelpayPlugin.opts.heidelpayBirthdayError });
return;
diff --git a/Resources/frontend/js/jquery.heidelpay-invoice-guaranteed.js b/Resources/frontend/js/jquery.heidelpay-invoice-guaranteed.js
index d4fb2cb..65c46ce 100644
--- a/Resources/frontend/js/jquery.heidelpay-invoice-guaranteed.js
+++ b/Resources/frontend/js/jquery.heidelpay-invoice-guaranteed.js
@@ -61,7 +61,7 @@
containerId: 'heidelpay--invoice-guaranteed-container'
});
- $.publish('plugin/heidel_invoice_guaranteed/createB2bForm', [this, this.customerProvider]);
+ $.publish('plugin/heidelpay/invoice_guaranteed/createB2bForm', [this, this.customerProvider]);
}
});
},
@@ -71,7 +71,7 @@
$(this.opts.generatedBirthdayElementSelector).attr('form', 'confirm--form');
this.heidelpayPlugin.setSubmitButtonActive(true);
- $.publish('plugin/heidel_invoice_guaranteed/createB2cForm', [this, this.customerProvider]);
+ $.publish('plugin/heidelpay/invoice_guaranteed/createB2cForm', [this, this.customerProvider]);
},
registerEvents: function () {
@@ -103,7 +103,7 @@
var me = this,
birthDate = this.heidelpayPlugin.getFormattedBirthday(this.opts.birthdayElementSelector);
- if (!birthDate) {
+ if (!birthDate && !this.opts.isB2bCustomer) {
me.onError({ message: me.heidelpayPlugin.opts.heidelpayBirthdayError });
return;
diff --git a/Resources/frontend/js/jquery.heidelpay-sepa-direct-debit-guaranteed.js b/Resources/frontend/js/jquery.heidelpay-sepa-direct-debit-guaranteed.js
index db985ad..f6bc2cd 100644
--- a/Resources/frontend/js/jquery.heidelpay-sepa-direct-debit-guaranteed.js
+++ b/Resources/frontend/js/jquery.heidelpay-sepa-direct-debit-guaranteed.js
@@ -77,17 +77,13 @@
createPaymentFromVault: function (typeId) {
var me = this,
- birthDateTarget = `#${typeId}_birthDate`,
+ birthDateTarget = '#' + typeId + '_birthDate',
birthDate = $(birthDateTarget).val();
- if ($(birthDateTarget).data('datepicker')) {
- birthDate = this.heidelpayPlugin.getFormattedBirthday(birthDateTarget);
-
- if (!birthDate) {
- me.onError({ message: me.heidelpayPlugin.opts.heidelpayBirthdayError });
+ if (!birthDate) {
+ me.onError({ message: me.heidelpayPlugin.opts.heidelpayBirthdayError });
- return;
- }
+ return;
}
$.ajax({
diff --git a/Resources/services.xml b/Resources/services.xml
index 719ee3e..6c1c90e 100644
--- a/Resources/services.xml
+++ b/Resources/services.xml
@@ -2,11 +2,14 @@
-
+
+
+ Psr\Log\LogLevel::INFO
+
diff --git a/Resources/snippets/frontend/heidelpay/frames.ini b/Resources/snippets/frontend/heidelpay/frames.ini
index 8f4ea3e..d8dda82 100644
--- a/Resources/snippets/frontend/heidelpay/frames.ini
+++ b/Resources/snippets/frontend/heidelpay/frames.ini
@@ -1,5 +1,5 @@
[en_GB]
-label/birthday="Please enter your date of birth (in the following format: [YEAR-MONTH-DAY]):"
+label/birthday="Please enter your date of birth (in the following format: [DAY.MONTH.YEAR]):"
placeholder/birthday="Your Birthday"
invalid/birthday="The specified birthday has an invalid format"
diff --git a/Resources/views/frontend/heidelpay/frames/hire_purchase.tpl b/Resources/views/frontend/heidelpay/frames/hire_purchase.tpl
index baebd0d..d058500 100644
--- a/Resources/views/frontend/heidelpay/frames/hire_purchase.tpl
+++ b/Resources/views/frontend/heidelpay/frames/hire_purchase.tpl
@@ -31,7 +31,9 @@
placeholder="{s name="placeholder/birthday" namespace="frontend/heidelpay/frames"}{/s}"
{if $sUserData.additional.user.birthday !== ''}value="{$sUserData.additional.user.birthday}"{/if}
data-datepicker="true"
- data-allowInput="true"/>
+ data-allowInput="true"
+ data-dateFormat="d.m.Y"
+ data-altInput="false"/>
{/block}
{/block}
diff --git a/Resources/views/frontend/heidelpay/frames/invoice_factoring.tpl b/Resources/views/frontend/heidelpay/frames/invoice_factoring.tpl
index 0c4d2cc..da70b17 100644
--- a/Resources/views/frontend/heidelpay/frames/invoice_factoring.tpl
+++ b/Resources/views/frontend/heidelpay/frames/invoice_factoring.tpl
@@ -22,6 +22,7 @@
{if $sUserData.additional.user.birthday !== ''}value="{$sUserData.additional.user.birthday}"{/if}
data-datepicker="true"
data-allowInput="true"
+ data-dateFormat="d.m.Y"
data-altInput="false"/>
{/block}
diff --git a/Resources/views/frontend/heidelpay/frames/invoice_guaranteed.tpl b/Resources/views/frontend/heidelpay/frames/invoice_guaranteed.tpl
index 7b5b6e3..d430db9 100644
--- a/Resources/views/frontend/heidelpay/frames/invoice_guaranteed.tpl
+++ b/Resources/views/frontend/heidelpay/frames/invoice_guaranteed.tpl
@@ -22,6 +22,7 @@
{if $sUserData.additional.user.birthday !== ''}value="{$sUserData.additional.user.birthday}"{/if}
data-datepicker="true"
data-allowInput="true"
+ data-dateFormat="d.m.Y"
data-altInput="false"/>
{/block}
diff --git a/Resources/views/frontend/heidelpay/frames/sepa_direct_debit_guaranteed.tpl b/Resources/views/frontend/heidelpay/frames/sepa_direct_debit_guaranteed.tpl
index 4aa1b99..dce57fd 100644
--- a/Resources/views/frontend/heidelpay/frames/sepa_direct_debit_guaranteed.tpl
+++ b/Resources/views/frontend/heidelpay/frames/sepa_direct_debit_guaranteed.tpl
@@ -44,6 +44,7 @@
{if $sUserData.additional.user.birthday !== ''}value="{$sUserData.additional.user.birthday}"{/if}
data-datepicker="true"
data-allowInput="true"
+ data-dateFormat="d.m.Y"
data-altInput="false"/>
{/block}
diff --git a/Resources/views/frontend/heidelpay/frames/vault/sepa_direct_debit.tpl b/Resources/views/frontend/heidelpay/frames/vault/sepa_direct_debit.tpl
index b98af66..53c7927 100644
--- a/Resources/views/frontend/heidelpay/frames/vault/sepa_direct_debit.tpl
+++ b/Resources/views/frontend/heidelpay/frames/vault/sepa_direct_debit.tpl
@@ -33,6 +33,7 @@
{if $sUserData.additional.user.birthday !== ''}value="{$sUserData.additional.user.birthday}"{/if}
data-datepicker="true"
data-allowInput="true"
+ data-dateFormat="d.m.Y"
data-altInput="false"/>
{/if}
{/block}
diff --git a/Services/HeidelpayClient/HeidelpayClientService.php b/Services/HeidelpayClient/HeidelpayClientService.php
index b09d3ff..9691242 100644
--- a/Services/HeidelpayClient/HeidelpayClientService.php
+++ b/Services/HeidelpayClient/HeidelpayClientService.php
@@ -4,6 +4,7 @@
namespace HeidelPayment\Services\HeidelpayClient;
+use HeidelPayment\Components\HeidelpayDebugHandler;
use HeidelPayment\Services\ConfigReader\ConfigReaderServiceInterface;
use HeidelPayment\Services\HeidelpayApiLogger\HeidelpayApiLoggerServiceInterface;
use heidelpayPHP\Heidelpay;
@@ -44,7 +45,12 @@ public function getHeidelpayClient(): ?Heidelpay
}
try {
- return new Heidelpay($this->getPrivateKey(), $locale);
+ $heidelpay = new Heidelpay($this->getPrivateKey(), $locale);
+
+ $heidelpay->setDebugMode((bool) $this->configReaderService->get('extended_logging'));
+ $heidelpay->setDebugHandler((new HeidelpayDebugHandler($this->apiLoggerService->getPluginLogger())));
+
+ return $heidelpay;
} catch (RuntimeException $ex) {
$this->apiLoggerService->getPluginLogger()->error(sprintf('Could not initialize Heidelpay client due to the following error: %s', $ex->getMessage()));
}
diff --git a/composer.json b/composer.json
index ae06f3e..a50749f 100644
--- a/composer.json
+++ b/composer.json
@@ -10,9 +10,9 @@
"homepage": "https://www.heidelpay.com/de/support/"
},
{
- "name": "Kellerkinder / Pluginwerk GmbH",
- "email": "hallo@pluginwerk.de",
- "homepage": "https://www.pluginwerk.de",
+ "name": "Kellerkinder GmbH",
+ "email": "hallo@kellerkinder.de",
+ "homepage": "https://www.kellerkinder.de",
"role": "Contributor"
}
],
diff --git a/package-lock.json b/package-lock.json
index 1510fad..778480c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -910,9 +910,9 @@
}
},
"lodash": {
- "version": "4.17.15",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
- "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
+ "version": "4.17.19",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
+ "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
"dev": true
},
"mimic-fn": {
diff --git a/phpstan.neon b/phpstan.neon
index 89a6ade..9e1749d 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -7,3 +7,4 @@ parameters:
excludes_analyse:
- Controllers
- vendor
+ - node_modules
diff --git a/plugin.xml b/plugin.xml
index 4687faa..e3efbba 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -4,23 +4,148 @@
- 1.2.1
+ 1.2.2
heidelpay GmbH
MIT
- heidelpay GmbH, Kellerkinder Pluginwerk GmbH
+ heidelpay GmbH, Kellerkinder GmbH
https://www.heidelpay.com
Produktinformationen "heidelpay - Payment Plugin für ab 5.6 Zahlungen per Kreditkarte, Rechnungskauf, SOFORT, ..."Die Omnichannel Payment Solution: Vollständige Zahlungsabwicklung und –management mit heidelpay.
Die Installationsanleitung finden Sie im Online-Handbuch
Verfügbare Zahlarten:
- Kredit- / Debitkarten
- SEPA / Lastschrift
- FlexiPay® Lastschrift gesichert
- Vorkasse
- Giropay
- SOFORT
- FlexiPay® direct
- iDeal
- EPS
- Prezlewy 24
- Paypal
- Rechnungskauf B2C
- FlexiPay® Rechnungskauf
- FlexiPay® Rechnungskauf factoring
- AliPay
- WeChat
Speicherung für Bezahldaten bei Zahlungsarten:
- Kredit- / Debitkarten
- Lastschrift (versichert)
Weitere Features
- Installation via Composer möglich
- Einfache Installation über den Community-Store-Download
- Einfache Konfiguration
- Alle Funktionen und Abläufe stehen kostenfrei zum Testen im Test-Betriebsmodus bereit
- Zahlungsabwicklung über das heidelpay Merchant Gateway (neue Zahlungsschnittstelle)
- Nahtlose Integration in den Shopware Standard-Checkout-Prozess
- Transaktions-Management aus dem Backend möglich
- Alle Transaktionen werden dafür übersichtlich im Backend von Shopware visualisiert
- Alle administrativen debitorischen Funktionen stehen im Backend zur Verfügung, wie Gutschriften, Nachbuchungen oder Stornos
- Automatische Meldung des Versands bei gesicherten Zahlarten
- Geldeinzug nach Reservierung von Rechnungsbeträgen
- Stornierung von Rechnungsbeträgen
- Automatische Anpassung des Bezahlstatus für beispielsweise Rechnungskäufe (nach Aktivierung der Webhooks)
- Automatische Anpassung der Bestellbestätigungs-E-Mail mit allen Bezahlinformationen bei Rechnungskauf und Vorkasse (falls Sie dies wünschen)
- Quelloffener Code nach neuen Shopware-Plugin-Standards
- Anpassbare und erweiterbare Smarty-Templates für Bezahlarten
- persönlicher Support via E-Mail an support@unzer.com oder +49 (6221) 43101-00
+ Produktinformationen "heidelpay - Payment Plugin für ab 5.6 Zahlungen per Kreditkarte, Rechnungskauf, SOFORT, ..."
+ Die Omnichannel Payment Solution: Vollständige Zahlungsabwicklung und –management mit heidelpay.
+ Die Installationsanleitung finden Sie im Online-Handbuch
+
+ Verfügbare Zahlarten:
+
+
+ - Kredit- / Debitkarten
+ - SEPA / Lastschrift
+ - FlexiPay® Lastschrift gesichert
+ - Vorkasse
+ - Giropay
+ - SOFORT
+ - FlexiPay® direct
+ - iDeal
+ - EPS
+ - Prezlewy 24
+ - Paypal
+ - Rechnungskauf B2C
+ - FlexiPay® Rechnungskauf
+ - FlexiPay® Rechnungskauf factoring
+ - AliPay
+ - WeChat
+
+
+ Speicherung für Bezahldaten bei Zahlungsarten:
+
+
+ - Kredit- / Debitkarten
+ - Lastschrift (versichert)
+
+
+ Weitere Features
+
+
+ - Installation via Composer möglich
+ - Einfache Installation über den Community-Store-Download
+ - Einfache Konfiguration
+ - Alle Funktionen und Abläufe stehen kostenfrei zum Testen im Test-Betriebsmodus bereit
+ - Zahlungsabwicklung über das heidelpay Merchant Gateway (neue Zahlungsschnittstelle)
+ - Nahtlose Integration in den Shopware Standard-Checkout-Prozess
+ - Transaktions-Management aus dem Backend möglich
+ - Alle Transaktionen werden dafür übersichtlich im Backend von Shopware visualisiert
+ - Alle administrativen debitorischen Funktionen stehen im Backend zur Verfügung, wie Gutschriften, Nachbuchungen oder Stornos
+ - Automatische Meldung des Versands bei gesicherten Zahlarten
+ - Geldeinzug nach Reservierung von Rechnungsbeträgen
+ - Stornierung von Rechnungsbeträgen
+ - Automatische Anpassung des Bezahlstatus für beispielsweise Rechnungskäufe (nach Aktivierung der Webhooks)
+ - Automatische Anpassung der Bestellbestätigungs-E-Mail mit allen Bezahlinformationen bei Rechnungskauf und Vorkasse (falls Sie dies wünschen)
+ - Quelloffener Code nach neuen Shopware-Plugin-Standards
+ - Anpassbare und erweiterbare Smarty-Templates für Bezahlarten
+ - persönlicher Support via E-Mail an support@unzer.com oder +49 (6221) 43101-00
+
]]>
Productinformation "heidelpay - payment plugin for 5.6 for credit cards, direct debit, prepayment, PayPal, SOFORT and more…"You can find the manual at https://dev.heidelpay.de/handbuch-shopware-ab-5-6/
Available payment methods
- Credit card / Debit card
- SEPA / Direct debit
- SEPA / Direct debit (secured)
- Prepayment
- giropay
- SOFORT
- FlexiPay® Direct
- iDEAL
- EPS
- Prezlewy24
- PayPal
- Purchase on account B2C
- FlexiPay® Invoice (secured)
- FlexiPay® Invoice (factoring)
- AliPay
- WeChat Pay
Feature List:
Registration of payment data for following payment methods:
- Credit card & Debit card
- SEPA / Direct debit (secured)
Additional features:
- Installation via Composer possible
- Simple installation via Community-Store-Download
- Easy configuration
- all features and processes can be tested completely free of charge in a test operating mode
- Payment processing via heidelpay Merchant Gateway (new payment interface)
- Seamless integration with standard Shopware checkout process
- Transaction management is possible from the backend
- All transactions are clearly visualized in the backend of Shopware
- Here are all administrative debit-side functions available, such as credit memos, follow-up postings or reversals
- Sending notification for insured payment methods
- Money collection after reservation of invoice amounts
- Reversals of invoice amounts
- Automatic adjustment of the payment status for e.g. invoice purchases (after activation of webhooks)
- Automatic adaptation of an order confirmation e-mail with invoice purchase transferinformation if you want
- Open source code according to new Shopware plugin standards
- Customizable / extensible Smarty templates for payment methods
- personal support via support@unzer.com or +49 (6221) 43101-00
+ Productinformation "heidelpay - payment plugin for 5.6 for credit cards, direct debit, prepayment, PayPal, SOFORT and more…"
You can find the manual at https://dev.heidelpay.de/handbuch-shopware-ab-5-6/
Available payment methods
- Credit card / Debit card
+ - SEPA / Direct debit
+ - SEPA / Direct debit (secured)
+ - Prepayment
+ - giropay
+ - SOFORT
+ - FlexiPay® Direct
+ - iDEAL
+ - EPS
+ - Prezlewy24
+ - PayPal
+ - Purchase on account B2C
+ - FlexiPay® Invoice (secured)
+ - FlexiPay® Invoice (factoring)
+ - AliPay
+ - WeChat Pay
+
+
+ Feature List:
+
+ Registration of payment data for following payment methods:
+
+
+ - Credit card & Debit card
+ - SEPA / Direct debit (secured)
+
+
+ Additional features:
+
+
+ - Installation via Composer possible
+ - Simple installation via Community-Store-Download
+ - Easy configuration
+ - all features and processes can be tested completely free of charge in a test operating mode
+ - Payment processing via heidelpay Merchant Gateway (new payment interface)
+ - Seamless integration with standard Shopware checkout process
+ - Transaction management is possible from the backend
+ - All transactions are clearly visualized in the backend of Shopware
+ - Here are all administrative debit-side functions available, such as credit memos, follow-up postings or reversals
+ - Sending notification for insured payment methods
+ - Money collection after reservation of invoice amounts
+ - Reversals of invoice amounts
+ - Automatic adjustment of the payment status for e.g. invoice purchases (after activation of webhooks)
+ - Automatic adaptation of an order confirmation e-mail with invoice purchase transferinformation if you want
+ - Open source code according to new Shopware plugin standards
+ - Customizable / extensible Smarty templates for payment methods
+ - personal support via support@unzer.com or +49 (6221) 43101-00
+
]]>
+
+
+
+ Format der Geburtstagsangabe im Checkout wurde vereinheitlicht
+ Das erweiterte Logging wurde verbessert und erweitert.
+ Korrektur eines Fehlers für wiederkehrende Kreditkarten Zahlung in Verbindung mit SwagAboCommerce
+ Korrektur der Validierung des Geburtsdatums für FlexiPay Rechnung für B2B
+ Korrektur der Warenkorb Verarbeitung
+ Korrektur eines Fehlers für FlexiPay Lastschrift (gesichert) für gespeicherte Lastschriftkonten
+
+ ]]>
+
+
+
+ Birthday input format in the checkout got standardized
+ The extended logging was improved
+ Fixed an error of credit card payments in combination with AboCommerce orders
+ Fixed the validation of the birthdate for FlexiPay invoice for B2B
+ Fixed the shopping cart hydration
+ Fixed an error with FlexiPay Direct Debit (secured) for saved bank accounts
+
+ ]]>
+
+