public function testVoid() { $orderId = 1005; $paymentObject = $this->setupPaymentObjectForVoid($orderId); $transactions = ['1' => \Braintree_Transaction::factory(['id' => '1', 'status' => \Braintree_Transaction::SUBMITTED_FOR_SETTLEMENT]), '2' => \Braintree_Transaction::factory(['id' => '2', 'status' => \Braintree_Transaction::AUTHORIZED])]; $this->setupTransactionIds($orderId, array_keys($transactions)); $index = 0; foreach ($transactions as $id => $transaction) { $this->braintreeTransactionMock->expects($this->at($index))->method('find')->with($id)->willReturn($transaction); $index++; } foreach (array_keys($transactions) as $id) { $resultSuccess = $this->setupSuccessResponse([]); $this->braintreeTransactionMock->expects($this->at($index))->method('void')->with($id)->willReturn($resultSuccess); $index++; } $index = 1; foreach (array_keys($transactions) as $id) { $transactionCollectionMock = $this->getMockBuilder('\\Magento\\Sales\\Model\\Resource\\Order\\Payment\\Transaction\\Collection')->disableOriginalConstructor()->getMock(); $transactionCollectionMock->expects($this->at(0))->method('addFieldToFilter')->with('parent_txn_id', ['eq' => $id])->willReturnSelf(); $transactionCollectionMock->expects($this->at(1))->method('addFieldToFilter')->with('txn_type', PaymentTransaction::TYPE_VOID)->willReturnSelf(); $transactionCollectionMock->expects($this->once())->method('getSize')->willReturn(1); $this->salesTransactionCollectionFactoryMock->expects($this->at($index))->method('create')->willReturn($transactionCollectionMock); $index++; } $this->model->void($paymentObject); $this->assertEquals(1, $paymentObject->getIsTransactionClosed()); $this->assertEquals('Voided capture.', $paymentObject->getMessage()->getText()); }
/** * Magento will consider a transaction for voiding only if it is an authorization * Braintree allows voiding captures too * * Lookup an authorization transaction using parent transaction id, if set * * @param Payment $subject * @param callable $proceed * * @return \Magento\Sales\Model\Order\Payment\Transaction|false * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function aroundGetAuthorizationTransaction(Payment $subject, \Closure $proceed) { if ($subject->getMethodInstance()->getCode() != PaymentMethod::METHOD_CODE) { return $proceed(); } $invoice = $this->registry->registry('current_invoice'); if ($invoice && $invoice->getId()) { $transactionId = $this->paymentHelper->clearTransactionId($invoice->getTransactionId()); $collection = $this->salesTransactionCollectionFactory->create()->addFieldToFilter('txn_id', ['eq' => $transactionId]); if ($collection->getSize() < 1) { return $proceed(); } else { return $collection->getFirstItem(); } } return $proceed(); }
/** * Find entities by criteria * * @param \Magento\Framework\Api\SearchCriteria $criteria * @return Transaction[] */ public function find(\Magento\Framework\Api\SearchCriteria $criteria) { /** @var TransactionResource\Collection $collection */ $collection = $this->transactionCollectionFactory->create(); foreach ($criteria->getFilterGroups() as $filterGroup) { foreach ($filterGroup->getFilters() as $filter) { $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq'; $collection->addFieldToFilter($filter->getField(), [$condition => $filter->getValue()]); } } $collection->setCurPage($criteria->getCurrentPage()); $collection->setPageSize($criteria->getPageSize()); $collection->addPaymentInformation(['method']); $collection->addOrderInformation(['increment_id']); foreach ($collection as $object) { $this->register($object); } $objectIds = $collection->getAllIds(); return array_intersect_key($this->registry, array_flip($objectIds)); }
/** * Find one transaction by ID or type * * @param string $txnId * @param bool|string $txnType * @return Transaction|false */ protected function _lookupTransaction($txnId, $txnType = false) { if (!$txnId) { if ($txnType && $this->getId()) { $collection = $this->_transactionCollectionFactory->create()->setOrderFilter($this->getOrder())->addPaymentIdFilter($this->getId())->addTxnTypeFilter($txnType)->setOrder('created_at', \Magento\Framework\Data\Collection::SORT_ORDER_DESC)->setOrder('transaction_id', \Magento\Framework\Data\Collection::SORT_ORDER_DESC); foreach ($collection as $txn) { $txn->setOrderPaymentObject($this); $this->_transactionsLookup[$txn->getTxnId()] = $txn; return $txn; } } return false; } if (isset($this->_transactionsLookup[$txnId])) { return $this->_transactionsLookup[$txnId]; } $txn = $this->_transactionFactory->create()->setOrderPaymentObject($this)->loadByTxnId($txnId); if ($txn->getId()) { $this->_transactionsLookup[$txnId] = $txn; } else { $this->_transactionsLookup[$txnId] = false; } return $this->_transactionsLookup[$txnId]; }
public function testAroundGetAuthorizationTransactionNoInvoiceTransaction() { $result = 'result'; $transactionId = 're45gf'; $transaction = 'invoice_transaction'; $proceed = function () use($result) { return $result; }; $methodInstanceMock = $this->getMock('\\Magento\\Payment\\Model\\MethodInterface'); $methodInstanceMock->expects($this->once())->method('getCode')->willReturn(PaymentMethod::METHOD_CODE); $invoiceMock = $this->getMockBuilder('\\Magento\\Sales\\Model\\Order\\Invoice')->disableOriginalConstructor()->getMock(); $invoiceMock->expects($this->once())->method('getId')->willReturn(1004); $invoiceMock->expects($this->once())->method('getTransactionId')->willReturn($transactionId); $this->helperMock->expects($this->once())->method('clearTransactionId')->with($transactionId)->willReturn($transactionId); $collectionMock = $this->getMockBuilder('\\Magento\\Sales\\Model\\Resource\\Order\\Payment\\Transaction\\Collection')->disableOriginalConstructor()->getMock(); $this->transactionCollectionFactoryMock->expects($this->once())->method('create')->willReturn($collectionMock); $collectionMock->expects($this->once())->method('addFieldToFilter')->with('txn_id', ['eq' => $transactionId])->willReturnSelf(); $collectionMock->expects($this->once())->method('getSize')->willReturn(0); $collectionMock->expects($this->never())->method('getFirstItem')->willReturn($transaction); $this->registryMock->expects($this->once())->method('registry')->with('current_invoice')->willReturn($invoiceMock); $payment = $this->getMockBuilder('\\Magento\\Sales\\Model\\Order\\Payment')->disableOriginalConstructor()->getMock(); $payment->expects($this->once())->method('getMethodInstance')->willReturn($methodInstanceMock); $this->assertEquals($result, $this->model->aroundGetAuthorizationTransaction($payment, $proceed)); }
/** * Voids transaction * * @param InfoInterface $payment * @throws LocalizedException * @return $this * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function void(InfoInterface $payment) { $transactionIds = $this->getTransactionsToVoid($payment); $message = false; foreach ($transactionIds as $transactionId) { $transaction = $this->braintreeTransaction->find($transactionId); if ($transaction->status !== \Braintree_Transaction::SUBMITTED_FOR_SETTLEMENT && $transaction->status !== \Braintree_Transaction::AUTHORIZED) { throw new LocalizedException(__('Some transactions are already settled or voided and cannot be voided.')); } if ($transaction->status === \Braintree_Transaction::SUBMITTED_FOR_SETTLEMENT) { $message = __('Voided capture.'); } } $errors = ''; foreach ($transactionIds as $transactionId) { $this->_debug('void-' . $transactionId); $result = $this->braintreeTransaction->void($transactionId); $this->_debug($result); if (!$result->success) { $errors .= ' ' . $this->errorHelper->parseBraintreeError($result)->getText(); } elseif ($message) { $payment->setMessage($message); } } if ($errors) { throw new LocalizedException(__('There was an error voiding the transaction: %1.', $errors)); } else { $match = true; foreach ($transactionIds as $transactionId) { $collection = $this->salesTransactionCollectionFactory->create()->addFieldToFilter('parent_txn_id', ['eq' => $transactionId])->addFieldToFilter('txn_type', PaymentTransaction::TYPE_VOID); if ($collection->getSize() < 1) { $match = false; } } if ($match) { $payment->setIsTransactionClosed(1); } } return $this; }