Skip to content

Commit

Permalink
Merge pull request #161 from paynl/feature/PLUG-3141
Browse files Browse the repository at this point in the history
PLUG-3141 - Instore payment i.c.m. pickup in store
  • Loading branch information
woutse authored Jun 19, 2024
2 parents c428396 + 7a03fbe commit ebc7fed
Show file tree
Hide file tree
Showing 25 changed files with 387 additions and 25 deletions.
21 changes: 15 additions & 6 deletions Controller/Checkout/Finish.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,16 @@ public function __construct(
* @param Order $order
* @param string $orderId
* @param Session $session
* @param boolean $pickupMode
* @return void
*/
private function checkSession(Order $order, string $orderId, Session $session)
private function checkSession(Order $order, string $orderId, Session $session, $pickupMode = null)
{
if ($session->getLastOrderId() != $order->getId()) {
$additionalInformation = $order->getPayment()->getAdditionalInformation();
$transactionId = (isset($additionalInformation['transactionId'])) ? $additionalInformation['transactionId'] : null;
if ($orderId == $transactionId) {

if ($orderId == $transactionId || !empty($pickupMode)) {
$this->checkoutSession->setLastQuoteId($order->getQuoteId())
->setLastSuccessQuoteId($order->getQuoteId())
->setLastOrderId($order->getId())
Expand Down Expand Up @@ -139,6 +141,7 @@ public function execute()
$orderStatusId = empty($params['orderStatusId']) ? null : (int)$params['orderStatusId'];
$magOrderId = empty($params['entityid']) ? null : $params['entityid'];
$orderIds = empty($params['order_ids']) ? null : $params['order_ids'];
$pickupMode = !empty($params['pickup']);
$bSuccess = $orderStatusId === Config::ORDERSTATUS_PAID;
$bPending = in_array($orderStatusId, Config::ORDERSTATUS_PENDING);
$bDenied = $orderStatusId === Config::ORDERSTATUS_DENIED;
Expand All @@ -148,12 +151,17 @@ public function execute()
$multiShipFinish = is_array($orderIds);

try {
$this->checkEmpty($payOrderId, 'payOrderid', 101);
$this->checkEmpty($magOrderId, 'magOrderId', 1012);

$order = $this->orderRepository->get($magOrderId);
$this->checkEmpty($order, 'order', 1013);

if ($pickupMode) {
$this->deactivateCart($order, '', true);
$resultRedirect->setPath(Config::FINISH_PICKUP, ['_query' => ['utm_nooverride' => '1']]);
return $resultRedirect;
}

$this->checkEmpty($payOrderId, 'payOrderid', 101);
$this->config->setStore($order->getStore());

$payment = $order->getPayment();
Expand Down Expand Up @@ -268,14 +276,15 @@ private function handlePin(string $hash, Order $order)
/**
* @param Order $order
* @param string $payOrderId
* @param boolean $pickupMode
* @return void
*/
private function deactivateCart(Order $order, string $payOrderId)
private function deactivateCart(Order $order, string $payOrderId, $pickupMode = null)
{
# Make the cart inactive
$session = $this->checkoutSession;

$this->checkSession($order, $payOrderId, $session);
$this->checkSession($order, $payOrderId, $session, $pickupMode);

$quote = $session->getQuote();
$quote->setIsActive(false);
Expand Down
30 changes: 30 additions & 0 deletions Controller/Order/Pickup.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace Paynl\Payment\Controller\Order;

class Pickup extends \Magento\Framework\App\Action\Action
{
protected $_pageFactory;

/**
* Pickup construct
*
* @param \Magento\Framework\App\Action\Context $context
* @param \Magento\Framework\View\Result\PageFactory $pageFactory
*/
public function __construct(
\Magento\Framework\App\Action\Context $context,
\Magento\Framework\View\Result\PageFactory $pageFactory
) {
$this->_pageFactory = $pageFactory;
return parent::__construct($context);
}

/**
* @return object
*/
public function execute()
{
return $this->_pageFactory->create();
}
}
1 change: 1 addition & 0 deletions Model/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class Config
public const PENDING_PAY = 'paynl/order/pending';
public const CANCEL_PAY = 'paynl/order/cancel';
public const FINISH_STANDARD = 'checkout/onepage/success';
public const FINISH_PICKUP = 'paynl/order/pickup';
public const ORDERSTATUS_PAID = 100;
public const ORDERSTATUS_PENDING = array(20, 25, 40, 50, 90);
public const ORDERSTATUS_DENIED = -63;
Expand Down
42 changes: 42 additions & 0 deletions Model/Config/Source/PinMoment.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace Paynl\Payment\Model\Config\Source;

use Magento\Framework\Option\ArrayInterface;

class PinMoment implements ArrayInterface
{
public const LOCATION_CHECKOUT = 0;
public const LOCATION_PICKUP = 1;
public const LOCATION_CHOICE = 2;

/**
* Options getter
*
* @return array
*/
public function toOptionArray()
{
$arrOptions = $this->toArray();

$arrResult = [];
foreach ($arrOptions as $value => $label) {
$arrResult[] = ['value' => $value, 'label' => $label];
}
return $arrResult;
}

/**
* Get options in "key-value" format
*
* @return array
*/
public function toArray()
{
return [
'0' => __("Direct checkout payment (default)"),
'1' => __("Payment takes place at the pickup location, only create a backorder"),
'2' => __("Provide this choice in the checkout"),
];
}
}
20 changes: 20 additions & 0 deletions Model/ConfigProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ public function getConfig()
$config['payment']['showkvk'][$code] = $this->getKVK($code);
$config['payment']['showvat'][$code] = $this->getVAT($code);
$config['payment']['showdob'][$code] = $this->getDOB($code);
$config['payment']['showpinmoment'][$code] = $this->getPinMoment($code);
$config['payment']['pinmomentterminal'][$code] = $this->getPinLocationTerminal($code);
$config['payment']['showforcompany'][$code] = $this->getCompany($code);
$config['payment']['showforgroup'][$code] = $this->getCustomerGroup($code);

Expand Down Expand Up @@ -238,6 +240,24 @@ protected function getDOB($code)
return $this->methods[$code]->getDOB();
}

/**
* @param string $code
* @return mixed
*/
protected function getPinMoment($code)
{
return $this->methods[$code]->getPinMoment();
}

/**
* @param string $code
* @return mixed
*/
protected function getPinLocationTerminal($code)
{
return $this->methods[$code]->getPinLocationTerminal();
}

/**
* @param string $code
* @return string
Expand Down
57 changes: 47 additions & 10 deletions Model/Paymentmethod/Instore.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Magento\Sales\Model\Order;
use Paynl\Payment\Helper\PayHelper;
use Paynl\Payment\Model\Config\Source\PinMoment;
use Paynl\Payment\Model\PayPaymentCreate;

class Instore extends PaymentMethod
Expand Down Expand Up @@ -60,9 +61,20 @@ public function initialize($paymentAction, $stateObject)
public function startTransaction(Order $order, $fromAdmin = false)
{
$store = $order->getStore();
$url = $store->getBaseUrl() . 'checkout/cart/';
$redirectUrl = $store->getBaseUrl() . 'checkout/cart/';

$additionalData = $order->getPayment()->getAdditionalInformation();
$pinLocation = PinMoment::LOCATION_CHECKOUT;

if ($fromAdmin === false) {
$pinLocation = $this->getPinMoment();
# Payment starts from checkout
if ($pinLocation == PinMoment::LOCATION_CHOICE) {
# Checkout user chooses pinlocation
$pinLocation = $additionalData['pinmoment'] ?? PinMoment::LOCATION_CHECKOUT;
}
}

$terminalId = null;
if (isset($additionalData['payment_option'])) {
$terminalId = $additionalData['payment_option'];
Expand All @@ -71,21 +83,38 @@ public function startTransaction(Order $order, $fromAdmin = false)

try {
if (empty($terminalId)) {
if (!$fromAdmin) {
$this->messageManager->addNoticeMessage(__('Please select a pin-terminal'));
return;
}
throw new \Exception(__('Please select a pin-terminal'), 201);
}

$transaction = (new PayPaymentCreate($order, $this))->create();
$this->payHelper->logDebug('pinlocation', [$pinLocation], $store);

if ($this->getPaymentOptionId() === 1927) {
$additionalData['terminal_hash'] = $transaction->getData()['terminal']['hash'];
$url = $transaction->getRedirectUrl();
if ($pinLocation == PinMoment::LOCATION_PICKUP) {
$redirectUrl = $order->getStore()->getBaseUrl() . 'paynl/checkout/finish/?entityid=' . $order->getEntityId() . '&pickup=1';
$order->addStatusHistoryComment(__('PAY.: Payment at pick-up'));
} else {
$instorePayment = \Paynl\Instore::payment(['transactionId' => $transaction->getTransactionId(), 'terminalId' => $terminalId]);
$additionalData['terminal_hash'] = $instorePayment->getHash();
$url = $instorePayment->getRedirectUrl();
$transaction = (new PayPaymentCreate($order, $this))->create();

if ($this->getPaymentOptionId() === 1927) {
if (array_key_exists('terminal', $transaction->getData())) {
$additionalData['terminal_hash'] = $transaction->getData()['terminal']['hash'];
} else {
throw new \Exception(__('Pin transaction can not be started in test mode'));
}

$redirectUrl = $transaction->getRedirectUrl();
} else {
$instorePayment = \Paynl\Instore::payment(['transactionId' => $transaction->getTransactionId(), 'terminalId' => $terminalId]);
$additionalData['terminal_hash'] = $instorePayment->getHash();
$redirectUrl = $instorePayment->getRedirectUrl();
}

$additionalData['transactionId'] = $transaction->getTransactionId();
}

$additionalData['transactionId'] = $transaction->getTransactionId();
$additionalData['payment_option'] = $terminalId;

$order->getPayment()->setAdditionalInformation($additionalData);
Expand All @@ -108,7 +137,7 @@ public function startTransaction(Order $order, $fromAdmin = false)
}
}

return $url;
return $redirectUrl;
}

/**
Expand Down Expand Up @@ -193,6 +222,14 @@ public function getDefaultPaymentOption()
return $this->_scopeConfig->getValue('payment/' . $this->_code . '/default_terminal', 'store');
}

/**
* @return mixed
*/
public function getPinLocationTerminal()
{
return $this->_scopeConfig->getValue('payment/' . $this->_code . '/pinmoment_terminal', 'store');
}

/**
* @return boolean
*/
Expand Down
12 changes: 12 additions & 0 deletions Model/Paymentmethod/PaymentMethod.php
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,14 @@ public function getDOB()
return $this->_scopeConfig->getValue('payment/' . $this->_code . '/showdob', 'store');
}

/**
* @return mixed
*/
public function getPinMoment()
{
return $this->_scopeConfig->getValue('payment/' . $this->_code . '/pinmoment', 'store');
}

/**
* @return integer
*/
Expand Down Expand Up @@ -592,6 +600,10 @@ public function assignData(\Magento\Framework\DataObject $data)
if (isset($additional_data['dob'])) {
$this->getInfoInstance()->setAdditionalInformation('dob', $additional_data['dob']);
}

if (isset($additional_data['pinmoment'])) {
$this->getInfoInstance()->setAdditionalInformation('pinmoment', $additional_data['pinmoment']);
}
}
return $this;
}
Expand Down
7 changes: 6 additions & 1 deletion Plugin/InstoreButton.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,12 @@ public function beforePushButtons(
$currentUrl = $this->urlInterface->getCurrentUrl();

if (!isset($buttonList->getItems()['paynl']['start_instore_payment'])) {
if ($payment_method == 'paynl_payment_instore' && !$order->hasInvoices() && $store->getConfig('payment/paynl_payment_instore/show_pin_button') == 1) {
if (
$payment_method == 'paynl_payment_instore'
&& !$order->hasInvoices()
&& ($store->getConfig('payment/paynl_payment_instore/show_pin_button') == 1
|| $store->getConfig('payment/paynl_payment_instore/pinmoment') > 0)
) {
$instoreUrl = $this->backendUrl->getUrl('paynl/order/instore') . '?order_id=' . $order_id . '&return_url=' . urlencode($currentUrl);
$buttonList->add(
'start_instore_payment',
Expand Down
19 changes: 19 additions & 0 deletions etc/adminhtml/paymentmethods/instore.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,25 @@
<![CDATA[Enable this to start a card machine transaction via the Order detail page after making an order with the Instore option via the Magento2 backend.]]>
</comment>
</field>
<field id="pinmoment" translate="label" type="select" sortOrder="28" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Payment location</label>
<source_model>Paynl\Payment\Model\Config\Source\PinMoment</source_model>
<depends>
<field id="active">1</field>
</depends>
<config_path>payment/paynl_payment_instore/pinmoment</config_path>
<comment>
<![CDATA[Setting for where the payment should take place: instant, or at pickup location. Or provide this choice in the checkout.]]>
</comment>
</field>
<field id="pinmoment_terminal" translate="label" type="select" sortOrder="29" showInDefault="1" showInWebsite="1" showInStore="1">
<label>Payment location terminal</label>
<source_model>Paynl\Payment\Model\Config\Source\PinTerminals</source_model>
<depends>
<field id="pinmoment" negative="1">0</field>
</depends>
<config_path>payment/paynl_payment_instore/pinmoment_terminal</config_path>
</field>
<field id="order_status" translate="label" type="select" sortOrder="30" showInDefault="1" showInWebsite="1"
showInStore="1">
<label>New order status</label>
Expand Down
7 changes: 7 additions & 0 deletions i18n/de_AT.csv
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,13 @@
"Enter your company name","Geben Sie Ihren Firmennamen ein"
"Invalid company","Ungültiger firma"
"Enter a valid company name","Geben Sie einen gültigen Firmennamen ein"
"Payment location","Pin-Moment"
"Pay by card","Jetzt pinnen"
"Pay later, at pickup","PIN bei der Abholung im Geschäft"
"Setting for where the payment should take place: instant, or at pickup location. Or provide this choice in the checkout.","Ermöglichen Sie den Kunden, bei der Abholung der Bestellung im Geschäft zu bezahlen. In der Bestellansicht wird ein Pin-Button angezeigt."
"Don't show in checkout (default)","Nicht im Checkout anzeigen (Standard)"
"Show in checkout by pickup","Bei Abholung an der Kasse anzeigen"
"PAY.: Payment at pick-up","Pay.: Die Bestellung wurde zum Zeitpunkt der Abholung im Geschäft zur Zahlung erstellt"
"Follow payment method","Follow payment method"
"This will ensure the order is updated with the actual payment method used to complete the order. This can differ from the payment method initially selected","Dadurch wird sichergestellt, dass die Bestellung mit der tatsächlichen Zahlungsmethode aktualisiert wird, die zum Abschluss der Bestellung verwendet wurde. Diese kann von der ursprünglich gewählten Zahlungsart abweichen"
"PAY.: Updated payment method from %1 to %2","PAY.: Zahlungsmethode geändert von %1 bis %2"
Expand Down
7 changes: 7 additions & 0 deletions i18n/de_CH.csv
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,13 @@
"Enter your company name","Geben Sie Ihren Firmennamen ein"
"Invalid company","Ungültiger firma"
"Enter a valid company name","Geben Sie einen gültigen Firmennamen ein"
"Payment location","Pin-Moment"
"Pay by card","Jetzt pinnen"
"Pay later, at pickup","PIN bei der Abholung im Geschäft"
"Setting for where the payment should take place: instant, or at pickup location. Or provide this choice in the checkout.","Ermöglichen Sie den Kunden, bei der Abholung der Bestellung im Geschäft zu bezahlen. In der Bestellansicht wird ein Pin-Button angezeigt."
"Don't show in checkout (default)","Nicht im Checkout anzeigen (Standard)"
"Show in checkout by pickup","Bei Abholung an der Kasse anzeigen"
"PAY.: Payment at pick-up","Pay.: Die Bestellung wurde zum Zeitpunkt der Abholung im Geschäft zur Zahlung erstellt"
"Follow payment method","Follow payment method"
"This will ensure the order is updated with the actual payment method used to complete the order. This can differ from the payment method initially selected","Dadurch wird sichergestellt, dass die Bestellung mit der tatsächlichen Zahlungsmethode aktualisiert wird, die zum Abschluss der Bestellung verwendet wurde. Diese kann von der ursprünglich gewählten Zahlungsart abweichen"
"PAY.: Updated payment method from %1 to %2","PAY.: Zahlungsmethode geändert von %1 bis %2"
Expand Down
7 changes: 7 additions & 0 deletions i18n/de_DE.csv
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,13 @@
"Enter your company name","Geben Sie Ihren Firmennamen ein"
"Invalid company","Ungültiger firma"
"Enter a valid company name","Geben Sie einen gültigen Firmennamen ein"
"Payment location","Pin-Moment"
"Pay by card","Jetzt pinnen"
"Pay later, at pickup","PIN bei der Abholung im Geschäft"
"Setting for where the payment should take place: instant, or at pickup location. Or provide this choice in the checkout.","Ermöglichen Sie den Kunden, bei der Abholung der Bestellung im Geschäft zu bezahlen. In der Bestellansicht wird ein Pin-Button angezeigt."
"Don't show in checkout (default)","Nicht im Checkout anzeigen (Standard)"
"Show in checkout by pickup","Bei Abholung an der Kasse anzeigen"
"PAY.: Payment at pick-up","Pay.: Die Bestellung wurde zum Zeitpunkt der Abholung im Geschäft zur Zahlung erstellt"
"Follow payment method","Follow payment method"
"This will ensure the order is updated with the actual payment method used to complete the order. This can differ from the payment method initially selected","Dadurch wird sichergestellt, dass die Bestellung mit der tatsächlichen Zahlungsmethode aktualisiert wird, die zum Abschluss der Bestellung verwendet wurde. Diese kann von der ursprünglich gewählten Zahlungsart abweichen"
"PAY.: Updated payment method from %1 to %2","PAY.: Zahlungsmethode geändert von %1 bis %2"
Expand Down
Loading

0 comments on commit ebc7fed

Please sign in to comment.