/** * Receives webhook events from Roadrunner */ public function execute() { $this->_logger->addDebug('paystandmagento/webhook/paystand endpoint was hit'); $body = @file_get_contents('php://input'); $json = json_decode($body); $this->_logger->addDebug(">>>>> body=" . print_r($body, TRUE)); if (isset($json->resource->meta->source) && $json->resource->meta->source == "magento 2") { $quoteId = $json->resource->meta->quote; $this->_logger->addDebug('magento 2 webhook identified with quote id = ' . $quoteId); $this->_order->loadByAttribute('quote_id', $quoteId); if (!empty($this->_order->getIncrementId())) { $this->_logger->addDebug('current order increment id = ' . $this->_order->getIncrementId()); $state = $this->_order->getState(); $this->_logger->addDebug('current order state = ' . $state); $status = $this->_order->getStatus(); $this->_logger->addDebug('current order status = ' . $status); $storeScope = \Magento\Store\Model\ScopeInterface::SCOPE_STORE; if ($this->scopeConfig->getValue(self::USE_SANDBOX, $storeScope)) { $base_url = 'https://api.paystand.co/v3'; } else { $base_url = 'https://api.paystand.com/v3'; } $url = $base_url . "/events/" . $json->id . "/verify"; $auth_header = array("x-publishable-key: " . $this->scopeConfig->getValue(self::PUBLISHABLE_KEY, $storeScope)); $curl = $this->buildCurl("POST", $url, json_encode($json), $auth_header); $response = $this->runCurl($curl); $this->_logger->addDebug("http_response_code is " . $this->http_response_code); if (FALSE !== $response && $this->http_response_code == 200) { if ($json->resource->object = "payment") { switch ($json->resource->status) { case 'posted': $state = 'pending'; $status = 'pending'; break; case 'paid': $state = 'processing'; $status = 'processing'; break; case 'failed': $state = 'closed'; $status = 'closed'; break; case 'canceled': $state = 'canceled'; $status = 'canceled'; break; } } $this->_order->setState($state); $this->_order->setStatus($status); $this->_order->save(); $this->_logger->addDebug('new order state = ' . $state); $this->_logger->addDebug('new order status = ' . $status); } else { $this->_logger->addDebug('event verify failed'); } } } }
/** * Perform order state and status assertions depending on currency code * * @param \Magento\Sales\Model\Order $order * @param string $currencyCode */ protected function _assertOrder($order, $currencyCode) { if ($currencyCode == 'USD') { $this->assertEquals('complete', $order->getState()); $this->assertEquals('complete', $order->getStatus()); } else { $this->assertEquals('payment_review', $order->getState()); $this->assertEquals('fraud', $order->getStatus()); } }
/** * @magentoDataFixture Magento/Paypal/_files/quote_payment_standard.php * @magentoConfigFixture current_store payment/paypal_standard/active 1 * @magentoConfigFixture current_store paypal/general/business_account merchant_2012050718_biz@example.com */ public function testCancelAction() { $quote = $this->_objectManager->create('Magento\\Sales\\Model\\Quote'); $quote->load('test01', 'reserved_order_id'); $this->_session->setQuoteId($quote->getId()); $this->_session->setPaypalStandardQuoteId($quote->getId())->setLastRealOrderId('100000002'); $this->dispatch('paypal/standard/cancel'); $this->_order->load('100000002', 'increment_id'); $this->assertEquals('canceled', $this->_order->getState()); $this->assertEquals($this->_session->getQuote()->getGrandTotal(), $quote->getGrandTotal()); $this->assertEquals($this->_session->getQuote()->getItemsCount(), $quote->getItemsCount()); }
/** * @param $order */ protected function _prepareInvoice() { $this->_debugData['_prepareInvoice'] = 'Prepare invoice for order'; $payment = $this->_order->getPayment()->getMethodInstance(); //Set order state to new because with order state payment_review it is not possible to create an invoice if (strcmp($this->_order->getState(), \Magento\Sales\Model\Order::STATE_PAYMENT_REVIEW) == 0) { $this->_order->setState(\Magento\Sales\Model\Order::STATE_NEW); } //capture mode if (!$this->_isAutoCapture()) { $this->_order->addStatusHistoryComment(__('Capture Mode set to Manual')); $this->_debugData['_prepareInvoice capture mode'] = 'Capture mode is set to Manual'; // show message if order is in manual review if ($this->_fraudManualReview) { // check if different status is selected $fraudManualReviewStatus = $this->_getFraudManualReviewStatus(); if ($fraudManualReviewStatus != "") { $status = $fraudManualReviewStatus; $comment = "Adyen Payment is in Manual Review check the Adyen platform"; $this->_order->addStatusHistoryComment(__($comment), $status); } } $createPendingInvoice = (bool) $this->_getConfigData('create_pending_invoice', 'adyen_abstract', $this->_order->getStoreId()); if (!$createPendingInvoice) { $this->_debugData['_prepareInvoice done'] = 'Setting pending invoice is off so don\'t create an invoice wait for the capture notification'; return; } } // validate if amount is total amount $orderCurrencyCode = $this->_order->getOrderCurrencyCode(); $orderAmount = (int) $this->_adyenHelper->formatAmount($this->_order->getGrandTotal(), $orderCurrencyCode); if ($this->_isTotalAmount($orderAmount)) { $this->_createInvoice(); } else { $this->_debugData['_prepareInvoice partial authorisation step1'] = 'This is a partial AUTHORISATION'; // Check if this is the first partial authorisation or if there is already been an authorisation $paymentObj = $this->_order->getPayment(); $authorisationAmount = $paymentObj->getAdyenAuthorisationAmount(); if ($authorisationAmount != "") { $this->_debugData['_prepareInvoice partial authorisation step2'] = 'There is already a partial AUTHORISATION received check if this combined with the previous amounts match the total amount of the order'; $authorisationAmount = (int) $authorisationAmount; $currentValue = (int) $this->_value; $totalAuthorisationAmount = $authorisationAmount + $currentValue; // update amount in column $paymentObj->setAdyenAuthorisationAmount($totalAuthorisationAmount); if ($totalAuthorisationAmount == $orderAmount) { $this->_debugData['_prepareInvoice partial authorisation step3'] = 'The full amount is paid. This is the latest AUTHORISATION notification. Create the invoice'; $this->_createInvoice(); } else { // this can be multiple times so use envenData as unique key $this->_debugData['_prepareInvoice partial authorisation step3'] = 'The full amount is not reached. Wait for the next AUTHORISATION notification. The current amount that is authorized is:' . $totalAuthorisationAmount; } } else { $this->_debugData['_prepareInvoice partial authorisation step2'] = 'This is the first partial AUTHORISATION save this into the adyen_authorisation_amount field'; $paymentObj->setAdyenAuthorisationAmount($this->_value); } } }
/** * Check order status before save * * @param Order $order * @return $this * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ public function check(Order $order) { if (!$order->getId()) { return $order; } if (!$order->isCanceled() && !$order->canUnhold() && !$order->canInvoice() && !$order->canShip()) { if (0 == $order->getBaseGrandTotal() || $order->canCreditmemo()) { if ($order->getState() !== Order::STATE_COMPLETE) { $order->setState(Order::STATE_COMPLETE)->setStatus($order->getConfig()->getStateDefaultStatus(Order::STATE_COMPLETE)); } } elseif (floatval($order->getTotalRefunded()) || !$order->getTotalRefunded() && $order->hasForcedCanCreditmemo()) { if ($order->getState() !== Order::STATE_CLOSED) { $order->setState(Order::STATE_CLOSED)->setStatus($order->getConfig()->getStateDefaultStatus(Order::STATE_CLOSED)); } } } if ($order->getState() == Order::STATE_NEW && $order->getIsInProcess()) { $order->setState(Order::STATE_PROCESSING)->setStatus($order->getConfig()->getStateDefaultStatus(Order::STATE_PROCESSING)); } return $this; }
/** * Check order status before save * * @param Order $order * @return $this */ public function check(Order $order) { if (!$order->getId()) { return $order; } $userNotification = $order->hasCustomerNoteNotify() ? $order->getCustomerNoteNotify() : null; if (!$order->isCanceled() && !$order->canUnhold() && !$order->canInvoice() && !$order->canShip()) { if (0 == $order->getBaseGrandTotal() || $order->canCreditmemo()) { if ($order->getState() !== Order::STATE_COMPLETE) { $order->setState(Order::STATE_COMPLETE, true, '', $userNotification, false); } } elseif (floatval($order->getTotalRefunded()) || !$order->getTotalRefunded() && $order->hasForcedCanCreditmemo()) { if ($order->getState() !== Order::STATE_CLOSED) { $order->setState(Order::STATE_CLOSED, true, '', $userNotification, false); } } } if ($order->getState() == Order::STATE_NEW && $order->getIsInProcess()) { $order->setState(Order::STATE_PROCESSING, true, '', $userNotification); } return $this; }
/** * @throws Exception */ protected function _prepareInvoice() { $this->_adyenLogger->addAdyenNotificationCronjob('Prepare invoice for order'); //Set order state to new because with order state payment_review it is not possible to create an invoice if (strcmp($this->_order->getState(), \Magento\Sales\Model\Order::STATE_PAYMENT_REVIEW) == 0) { $this->_order->setState(\Magento\Sales\Model\Order::STATE_NEW); } $paymentObj = $this->_order->getPayment(); // set pspReference as transactionId $paymentObj->setCcTransId($this->_pspReference); $paymentObj->setLastTransId($this->_pspReference); // set transaction $paymentObj->setTransactionId($this->_pspReference); //capture mode if (!$this->_isAutoCapture()) { $this->_order->addStatusHistoryComment(__('Capture Mode set to Manual')); $this->_adyenLogger->addAdyenNotificationCronjob('Capture mode is set to Manual'); // show message if order is in manual review if ($this->_fraudManualReview) { // check if different status is selected $fraudManualReviewStatus = $this->_getFraudManualReviewStatus(); if ($fraudManualReviewStatus != "") { $status = $fraudManualReviewStatus; $comment = "Adyen Payment is in Manual Review check the Adyen platform"; $this->_order->addStatusHistoryComment(__($comment), $status); } } $createPendingInvoice = (bool) $this->_getConfigData('create_pending_invoice', 'adyen_abstract', $this->_order->getStoreId()); if (!$createPendingInvoice) { $this->_adyenLogger->addAdyenNotificationCronjob('Setting pending invoice is off so don\'t create an invoice wait for the capture notification'); return; } } // validate if amount is total amount $orderCurrencyCode = $this->_order->getOrderCurrencyCode(); $amount = $this->_adyenHelper->originalAmount($this->_value, $orderCurrencyCode); // add to order payment $date = new \DateTime(); $this->_adyenOrderPaymentFactory->create()->setPspreference($this->_pspReference)->setMerchantReference($this->_merchantReference)->setPaymentId($paymentObj->getId())->setPaymentMethod($this->_paymentMethod)->setAmount($amount)->setTotalRefunded(0)->setCreatedAt($date)->setUpdatedAt($date)->save(); if ($this->_isTotalAmount($paymentObj->getEntityId(), $orderCurrencyCode)) { $this->_createInvoice(); } else { $this->_adyenLogger->addAdyenNotificationCronjob('This is a partial AUTHORISATION and the full amount is not reached'); } }
/** * Process payment pending notification * * @return void * @throws Exception */ public function _registerPaymentPending() { $reason = $this->getRequestData('pending_reason'); if ('authorization' === $reason) { $this->_registerPaymentAuthorization(); return; } if ('order' === $reason) { throw new Exception('The "order" authorizations are not implemented.'); } // case when was placed using PayPal standard if (\Magento\Sales\Model\Order::STATE_PENDING_PAYMENT == $this->_order->getState() && !$this->getRequestData('transaction_entity')) { $this->_registerPaymentCapture(); return; } $this->_importPaymentInformation(); $this->_order->getPayment()->setPreparedMessage($this->_createIpnComment($this->_paypalInfo->explainPendingReason($reason)))->setTransactionId($this->getRequestData('txn_id'))->setIsTransactionClosed(0)->update(false); $this->_order->save(); }
/** * Instantiate * * @return void * @throws \Magento\Framework\Exception\LocalizedException */ protected function _initCheckout() { $pre = __METHOD__ . " : "; $this->_logger->debug($pre . 'bof'); $this->_order = $this->_checkoutSession->getLastRealOrder(); if (!$this->_order->getId()) { $this->getResponse()->setStatusHeader(404, '1.1', 'Not found'); throw new \Magento\Framework\Exception\LocalizedException(__('We could not find "Order" for processing')); } if ($this->_order->getState() != \Magento\Sales\Model\Order::STATE_PENDING_PAYMENT) { $this->_order->setState(\Magento\Sales\Model\Order::STATE_PENDING_PAYMENT)->save(); } if ($this->_order->getQuoteId()) { $this->_checkoutSession->setPayfastQuoteId($this->_checkoutSession->getQuoteId()); $this->_checkoutSession->setPayfastSuccessQuoteId($this->_checkoutSession->getLastSuccessQuoteId()); $this->_checkoutSession->setPayfastRealOrderId($this->_checkoutSession->getLastRealOrderId()); $this->_checkoutSession->getQuote()->setIsActive(false)->save(); //$this->_checkoutSession->clear(); } $this->_logger->debug($pre . 'eof'); //$this->_checkout = $this->_checkoutTypes[$this->_checkoutType]; }
/** * Set appropriate state to order or add status to order history * * @param Order $order * @param string $orderState * @param string $orderStatus * @param bool $isCustomerNotified * @return void */ protected function updateOrder(Order $order, $orderState, $orderStatus, $isCustomerNotified) { // add message if order was put into review during authorization or capture $message = $order->getCustomerNote(); $originalOrderState = $order->getState(); $originalOrderStatus = $order->getStatus(); switch (true) { case $message && $originalOrderState == Order::STATE_PAYMENT_REVIEW: $order->addStatusToHistory($originalOrderStatus, $message, $isCustomerNotified); break; case $message: case $originalOrderState && $message: case $originalOrderState != $orderState: case $originalOrderStatus != $orderStatus: $order->setState($orderState)->setStatus($orderStatus)->addStatusHistoryComment($message)->setIsCustomerNotified($isCustomerNotified); break; default: break; } }
/** * @param \Magento\Sales\Model\Order $order * @return bool */ public function validateState(\Magento\Sales\Model\Order $order) { return !in_array($order->getState(), [\Magento\Sales\Model\Order::STATE_CANCELED, \Magento\Sales\Model\Order::STATE_CLOSED, \Magento\Sales\Model\Order::STATE_COMPLETE]); }
/** * Capture order's payment using AIM. * * @param \Magento\Sales\Model\Order $order * @return void */ protected function _captureOrder(\Magento\Sales\Model\Order $order) { $payment = $order->getPayment(); if ($payment->getAdditionalInformation('payment_type') == self::ACTION_AUTHORIZE_CAPTURE) { try { $payment->setTransactionId(null)->setParentTransactionId($this->getResponse()->getXTransId())->capture(null); // set status from config for AUTH_AND_CAPTURE orders. if ($order->getState() == \Magento\Sales\Model\Order::STATE_PROCESSING) { $orderStatus = $this->getConfigData('order_status'); if (!$orderStatus || $order->getIsVirtual()) { $orderStatus = $order->getConfig()->getStateDefaultStatus(\Magento\Sales\Model\Order::STATE_PROCESSING); } if ($orderStatus) { $order->setStatus($orderStatus); } } $order->save(); } catch (\Exception $e) { //if we couldn't capture order, just leave it as NEW order. $this->_logger->logException($e); } } }
/** * Check order state * * @param Order $order * @return bool */ protected function checkOrderState(Order $order) { return in_array($order->getState(), $this->allowedOrderStates); }