diff --git a/Block/Adminhtml/Sales/Creditmemo.php b/Block/Adminhtml/Sales/Creditmemo.php new file mode 100644 index 0000000..f8bb778 --- /dev/null +++ b/Block/Adminhtml/Sales/Creditmemo.php @@ -0,0 +1,124 @@ + + * See COPYING.txt for license details. + */ + +namespace Moip\Magento2\Block\Adminhtml\Sales; + +use Moip\Magento2\Model\Ui\ConfigProviderBoleto; + +class Creditmemo extends \Magento\Backend\Block\Template +{ + const BANK_NUMBER = 'moip_magento2_boleto_bank_number'; + + const AGENCY_NUMBER = 'moip_magento2_boleto_agency_number'; + + const AGENCY_CHECK_NUMBER = 'moip_magento2_boleto_agency_check_number'; + + const ACCOUNT_NUMBER = 'moip_magento2_boleto_account_number'; + + const ACCOUNT_CHECK_NUMBER = 'moip_magento2_boleto_account_check_number'; + + const HOLDER_FULLNAME = 'moip_magento2_boleto_account_holder_fullname'; + + const HOLDER_DOCUMENT_NUMBER = 'moip_magento2_boleto_account_holder_document_number'; + + const CREDITMEMO_COMMENT_TEXT = 'comment_text'; + + /** + * @var \Magento\Framework\Registry + */ + private $coreRegistry; + + public function __construct( + \Magento\Backend\Block\Template\Context $context, + \Magento\Framework\Registry $registry, + array $data = [] + ) { + $this->coreRegistry = $registry; + parent::__construct($context, $data); + } + + /** + * @return \Magento\Sales\Model\Order\Creditmemo + */ + public function getCreditmemo() + { + return $this->coreRegistry->registry('current_creditmemo'); + } + + /** + * @return \Magento\Sales\Model\Order + */ + public function getOrder() + { + return $this->getCreditmemo()->getOrder(); + } + + /** + * Check whether can refund to payment by boleto. + * + * @return bool + */ + public function canRefundBoleto() + { + /** @var \Magento\Sales\Model\Order $order */ + $order = $this->getCreditmemo()->getOrder(); + + if ($order->getPayment()->getMethodInstance()->getCode() === ConfigProviderBoleto::CODE) { + return true; + } + + return false; + } + + /** + * Json configuration for tooltip. + * + * @parms $field + * + * @return string json + */ + public function getTooltipConfig($field) + { + $tooltipConfig = [ + 'tooltip' => [ + 'trigger' => '[data-tooltip-trigger=moip_magento2_tooltip_'.$field.']', + 'action' => 'click', + 'delay' => 0, + 'track' => false, + 'position' => 'top', + ], + ]; + + return str_replace('"', "'", \Zend_Json::encode($tooltipConfig)); + } + + public function getBankNumber() + { + return $this->getCreditmemo()->getData(self::BANK_NUMBER); + } + + public function getAgencyNumber() + { + return $this->getCreditmemo()->getData(self::AGENCY_NUMBER); + } + + public function getAgencyCheckNumber() + { + return $this->getCreditmemo()->getData(self::AGENCY_CHECK_NUMBER); + } + + public function getAccountNumber() + { + return $this->getCreditmemo()->getData(self::ACCOUNT_NUMBER); + } + + public function getAccountCheckNumber() + { + return $this->getCreditmemo()->getData(self::ACCOUNT_CHECK_NUMBER); + } +} diff --git a/Block/Adminhtml/System/Config/PaymentGroup.php b/Block/Adminhtml/System/Config/PaymentGroup.php index 46f776e..75c241c 100755 --- a/Block/Adminhtml/System/Config/PaymentGroup.php +++ b/Block/Adminhtml/System/Config/PaymentGroup.php @@ -74,4 +74,4 @@ protected function _isCollapseState($element) return false; } -} +} \ No newline at end of file diff --git a/Block/Customer/CardRenderer.php b/Block/Customer/CardRenderer.php index 859fd40..d84f8eb 100755 --- a/Block/Customer/CardRenderer.php +++ b/Block/Customer/CardRenderer.php @@ -1,6 +1,7 @@ * See COPYING.txt for license details. */ diff --git a/Controller/Adminhtml/Order/MassUpdate.php b/Controller/Adminhtml/Order/MassUpdate.php index 5a38b86..6174926 100755 --- a/Controller/Adminhtml/Order/MassUpdate.php +++ b/Controller/Adminhtml/Order/MassUpdate.php @@ -72,7 +72,7 @@ protected function massAction(AbstractCollection $collection) $method->fetchTransactionInfo($payment, $transactionId); $payment->getOrder()->save(); $state = $payment->getOrder()->getState(); - if($state === "processing") { + if ($state === 'processing') { $countUpdate++; } $countNotUpdate++; diff --git a/Controller/Webhooks/Accept.php b/Controller/Webhooks/Accept.php index 5386239..aead542 100755 --- a/Controller/Webhooks/Accept.php +++ b/Controller/Webhooks/Accept.php @@ -11,7 +11,7 @@ use Magento\Framework\App\Action\Action; use Magento\Framework\App\Action\Context; -use Magento\Framework\App\CsrfAwareActionInterface; +use Magento\Framework\App\CsrfAwareActionInterface as Csrf; use Magento\Framework\App\Request\InvalidRequestException; use Magento\Framework\App\RequestInterface; use Magento\Framework\Controller\Result\JsonFactory; @@ -27,7 +27,7 @@ /** * Class Accept - Receives communication for accept payment. */ -class Accept extends Action implements CsrfAwareActionInterface +class Accept extends Action implements Csrf { /** * createCsrfValidationException. @@ -136,12 +136,12 @@ public function execute() $storeCaptureToken = $this->config->getMerchantGatewayCaptureToken($storeId); if ($storeCaptureToken === $authorization) { $data = $originalNotification['resource']['order']; - $order = $this->orderFactory->create()->load($data['ownId'], 'ext_order_id'); + $order = $this->orderFactory->create()->load($data['id'], 'ext_order_id'); $this->logger->debug([ 'webhook' => 'accept', - 'ext_order_id' => $data['ownId'], + 'ext_order_id' => $data['id'], 'increment_order_id' => $order->getIncrementId(), - 'webhook_data' => $response + 'webhook_data' => $response, ]); $payment = $order->getPayment(); if (!$order->getInvoiceCollection()->count()) { diff --git a/Controller/Webhooks/Deny.php b/Controller/Webhooks/Deny.php index d443322..bbe2bc8 100755 --- a/Controller/Webhooks/Deny.php +++ b/Controller/Webhooks/Deny.php @@ -11,7 +11,7 @@ use Magento\Framework\App\Action\Action; use Magento\Framework\App\Action\Context; -use Magento\Framework\App\CsrfAwareActionInterface; +use Magento\Framework\App\CsrfAwareActionInterface as Csrf; use Magento\Framework\App\Request\InvalidRequestException; use Magento\Framework\App\RequestInterface; use Magento\Framework\Controller\Result\JsonFactory; @@ -19,8 +19,8 @@ use Magento\Payment\Model\Method\Logger; use Magento\Sales\Api\Data\OrderInterfaceFactory; use Magento\Sales\Model\Order\CreditmemoFactory; -use Magento\Sales\Model\Order\Invoice; use Magento\Sales\Model\Order\Email\Sender\OrderCommentSender; +use Magento\Sales\Model\Order\Invoice; use Magento\Sales\Model\Service\CreditmemoService; use Magento\Store\Model\StoreManagerInterface; use Moip\Magento2\Gateway\Config\Config; @@ -28,7 +28,7 @@ /** * Class Deny - Receives communication for deny payment. */ -class Deny extends Action implements CsrfAwareActionInterface +class Deny extends Action implements Csrf { /** * createCsrfValidationException. @@ -149,7 +149,7 @@ public function execute() 'webhook' => 'deny', 'ext_order_id' => $data['id'], 'increment_order_id' => $order->getIncrementId(), - 'webhook_data' => $response + 'webhook_data' => $response, ]); $payment = $order->getPayment(); if (!$order->canCancel()) { @@ -183,7 +183,6 @@ public function execute() $order->save(); $this->orderCommentSender->send($order, 1, $cancelDetailsCus); - } catch (\Exception $exc) { $resultPage->setHttpResponseCode(500); $resultPage->setJsonData( diff --git a/Controller/Webhooks/Refund.php b/Controller/Webhooks/Refund.php index 001f68d..a81c2ed 100755 --- a/Controller/Webhooks/Refund.php +++ b/Controller/Webhooks/Refund.php @@ -9,15 +9,19 @@ namespace Moip\Magento2\Controller\Webhooks; +use Exception; +use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Framework\App\Action\Action; use Magento\Framework\App\Action\Context; -use Magento\Framework\App\CsrfAwareActionInterface; +use Magento\Framework\App\CsrfAwareActionInterface as Crsf; use Magento\Framework\App\Request\InvalidRequestException; use Magento\Framework\App\RequestInterface; use Magento\Framework\Controller\Result\JsonFactory; use Magento\Framework\Serialize\Serializer\Json; use Magento\Payment\Model\Method\Logger; +use Magento\Sales\Api\CreditmemoRepositoryInterface; use Magento\Sales\Api\Data\OrderInterfaceFactory; +use Magento\Sales\Model\Order\Creditmemo; use Magento\Sales\Model\Order\CreditmemoFactory; use Magento\Sales\Model\Order\Invoice; use Magento\Sales\Model\Service\CreditmemoService; @@ -27,7 +31,7 @@ /** * Class Refund - Receives communication for refunded payment. */ -class Refund extends Action implements CsrfAwareActionInterface +class Refund extends Action implements Crsf { /** * createCsrfValidationException. @@ -76,12 +80,22 @@ public function validateForCsrf(RequestInterface $request): bool * @var storeManager */ protected $storeManager; - + /** * @var Json */ protected $json; + /** + * @var CreditmemoRepositoryInterface + */ + private $creditmemoRepository; + + /** + * @var schCriteriaBuilder + */ + protected $schCriteriaBuilder; + /** * @param Context $context * @param logger $logger @@ -100,7 +114,9 @@ public function __construct( Invoice $invoice, StoreManagerInterface $storeManager, JsonFactory $resultJsonFactory, - Json $json + Json $json, + CreditmemoRepositoryInterface $creditmemoRepository, + SearchCriteriaBuilder $schCriteriaBuilder ) { parent::__construct($context); $this->config = $config; @@ -112,10 +128,12 @@ public function __construct( $this->storeManager = $storeManager; $this->resultJsonFactory = $resultJsonFactory; $this->json = $json; + $this->creditmemoRepository = $creditmemoRepository; + $this->schCriteriaBuilder = $schCriteriaBuilder; } /** - * Command Accept. + * Command Refund. * * @return json */ @@ -134,56 +152,133 @@ public function execute() $authorization = $this->getRequest()->getHeader('Authorization'); $storeId = $this->storeManager->getStore()->getId(); $storeCaptureToken = $this->config->getMerchantGatewayRefundToken($storeId); + if ($storeCaptureToken === $authorization) { - $data = $originalNotification['resource']['order']; - $order = $this->orderFactory->create()->load($data['ownId'], 'ext_order_id'); - $this->logger->debug([ - 'webhook' => 'refund', - 'ext_order_id' => $data['ownId'], - 'increment_order_id' => $order->getIncrementId(), - 'webhook_data' => $response - ]); - $invoices = $order->getInvoiceCollection(); - if ($invoices) { - foreach ($invoices as $invoiceLoad) { - $invoiceincrementid = $invoiceLoad->getIncrementId(); + $resource = $originalNotification['resource']; + $extRefundId = $resource['refund']['id']; + $extStatus = $resource['refund']['status']; + + $creditmemos = $this->getCreditMemoByTransactionId($extRefundId); + if (count($creditmemos)) { + foreach ($creditmemos as $creditmemo) { + if ($extStatus === 'REQUESTED') { + $creditmemo->setState(Creditmemo::STATE_OPEN); + } elseif ($extStatus === 'COMPLETED') { + $creditmemo->setState(Creditmemo::STATE_REFUNDED); + } elseif ($extStatus === 'FAILED') { + $creditmemo->setState(Creditmemo::STATE_CANCELED); + } + + try { + $creditmemo->save(); + } catch (\Exception $exc) { + $resultPage->setHttpResponseCode(500); + $resultPage->setJsonData( + $this->json->serialize([ + 'error' => 400, + 'message' => $exc->getMessage(), + ]) + ); + } + + continue; } - $invoiceobj = $this->invoice->loadByIncrementId($invoiceincrementid); - $creditmemo = $this->creditmemoFactory->createByOrder($order); - $creditmemo->setInvoice($invoiceobj); - - try { - $this->creditmemoService->refund($creditmemo); - } catch (\Exception $exc) { - $resultPage->setHttpResponseCode(500); - $resultPage->setJsonData( + } else { + $extOrderId = $resource['refund']['_links']['order']['title']; + $creditmemo = $this->createNewCreditMemo($extOrderId, $extRefundId); + if ($creditmemo) { + if ($extStatus === 'REQUESTED') { + $creditmemo->setState(Creditmemo::STATE_OPEN); + } elseif ($extStatus === 'COMPLETED') { + $creditmemo->setState(Creditmemo::STATE_REFUNDED); + } elseif ($extStatus === 'FAILED') { + $creditmemo->setState(Creditmemo::STATE_CANCELED); + } + + try { + $this->creditmemoService->refund($creditmemo); + } catch (\Exception $exc) { + $resultPage->setHttpResponseCode(500); + $resultPage->setJsonData( + $this->json->serialize([ + 'error' => 400, + 'message' => $exc->getMessage(), + ]) + ); + } + } else { + return $resultPage->setJsonData( $this->json->serialize([ - 'error' => 400, - 'message' => $exc->getMessage(), + 'error' => 404, + 'message' => 'The transaction could not be refund', ]) ); } - - return $resultPage->setJsonData( - $this->json->serialize([ - 'success' => 1, - 'status' => $order->getStatus(), - 'state' => $order->getState(), - ]) - ); } - $resultPage->setHttpResponseCode(201); - return $resultPage->setJsonData( $this->json->serialize([ - 'error' => 400, - 'message' => 'The transaction could not be refund', + 'success' => 1, + 'extOrderId' => $extRefundId, + 'state' => $creditmemo->getState(), ]) ); } + $resultPage->setHttpResponseCode(401); return $resultPage; } + + /** + * Get Creditmemo. + * + * @params $extOrderId + * + * @return creditmemo + */ + public function getCreditMemoByTransactionId(string $transactionId) + { + $searchCriteria = $this->schCriteriaBuilder + ->addFilter('transaction_id', $transactionId)->create(); + + try { + $creditmemos = $this->creditmemoRepository->getList($searchCriteria); + $creditmemoRecords = $creditmemos->getItems(); + } catch (Exception $exception) { + $this->logger->critical($exception->getMessage()); + $creditmemoRecords = null; + } + + return $creditmemoRecords; + } + + /** + * Create new creditmemo. + * + * @params $extOrderId + * @parmas $extRefundId + * + * @return creditmemo + */ + public function createNewCreditMemo(string $extOrderId, string $extRefundId) + { + $order = $this->orderFactory->create()->load($extOrderId, 'ext_order_id'); + $creditmemo = null; + + $payment = $order->getPayment(); + $invoices = $order->getInvoiceCollection(); + + if ($invoices) { + foreach ($invoices as $invoiceLoad) { + $invoiceincrementid = $invoiceLoad->getIncrementId(); + } + $invoiceobj = $this->invoice->loadByIncrementId($invoiceincrementid); + $creditmemo = $this->creditmemoFactory->createByOrder($order); + $payment->setTransactionId($extRefundId); + $creditmemo->setInvoice($invoiceobj); + } + + return $creditmemo; + } } diff --git a/Gateway/Http/Client/AuthorizeClient.php b/Gateway/Http/Client/AuthorizeClient.php index e97ec08..64c923f 100755 --- a/Gateway/Http/Client/AuthorizeClient.php +++ b/Gateway/Http/Client/AuthorizeClient.php @@ -81,7 +81,7 @@ public function placeRequest(TransferInterface $transferObject) try { $client->setUri($url.'orders/'.$orderMoip.'/payments'); - $client->setConfig(['maxredirects' => 0, 'timeout' => 30]); + $client->setConfig(['maxredirects' => 0, 'timeout' => 120]); $client->setHeaders('Authorization', 'Bearer '.$apiBearer); $client->setRawData($this->json->serialize($request['paymentInstrument']), 'application/json'); $client->setMethod(ZendClient::POST); diff --git a/Gateway/Http/Client/CreateOrderAuthorizeClient.php b/Gateway/Http/Client/CreateOrderAuthorizeClient.php index 10bec72..ab50e6b 100755 --- a/Gateway/Http/Client/CreateOrderAuthorizeClient.php +++ b/Gateway/Http/Client/CreateOrderAuthorizeClient.php @@ -78,7 +78,7 @@ public function placeRequest(TransferInterface $transferObject) try { $client->setUri($url.'orders'); - $client->setConfig(['maxredirects' => 0, 'timeout' => 30]); + $client->setConfig(['maxredirects' => 0, 'timeout' => 120]); $client->setHeaders('Authorization', 'Bearer '.$apiBearer); $client->setRawData($this->json->serialize($request), 'application/json'); $client->setMethod(ZendClient::POST); @@ -111,9 +111,10 @@ public function placeRequest(TransferInterface $transferObject) } catch (InvalidArgumentException $e) { $this->logger->debug( [ - 'url' => $url.'orders', - 'request' => $this->json->serialize($transferObject->getBody()), - 'response' => $responseBody, + 'exception' => $e->getMessage(), + 'url' => $url.'orders', + 'request' => $this->json->serialize($transferObject->getBody()), + 'response' => $responseBody, ] ); // phpcs:ignore Magento2.Exceptions.DirectThrow diff --git a/Gateway/Http/Client/FetchTransactionInfoClient.php b/Gateway/Http/Client/FetchTransactionInfoClient.php index 38ec459..32acc50 100755 --- a/Gateway/Http/Client/FetchTransactionInfoClient.php +++ b/Gateway/Http/Client/FetchTransactionInfoClient.php @@ -81,7 +81,7 @@ public function placeRequest(TransferInterface $transferObject) try { $client->setUri($url.'orders/'.$orderMoip); - $client->setConfig(['maxredirects' => 0, 'timeout' => 30]); + $client->setConfig(['maxredirects' => 0, 'timeout' => 120]); $client->setHeaders('Authorization', 'Bearer '.$apiBearer); $client->setMethod(ZendClient::GET); diff --git a/Gateway/Http/Client/RefundClient.php b/Gateway/Http/Client/RefundClient.php index 9cee7ec..63c2180 100755 --- a/Gateway/Http/Client/RefundClient.php +++ b/Gateway/Http/Client/RefundClient.php @@ -10,6 +10,8 @@ namespace Moip\Magento2\Gateway\Http\Client; +use InvalidArgumentException; +use Magento\Framework\HTTP\ZendClient; use Magento\Framework\HTTP\ZendClientFactory; use Magento\Framework\Serialize\Serializer\Json; use Magento\Payment\Gateway\Http\ClientInterface; @@ -22,6 +24,8 @@ */ class RefundClient implements ClientInterface { + const MOIP_ORDER_ID = 'moip_order_id'; + /** * @var LoggerInterface */ @@ -69,11 +73,60 @@ public function __construct( */ public function placeRequest(TransferInterface $transferObject) { + $client = $this->httpClientFactory->create(); $request = $transferObject->getBody(); - if ($request) { - return [ - 'RESULT_CODE' => 1, - ]; + + $url = $this->config->getApiUrl(); + $apiBearer = $this->config->getMerchantGatewayOauth(); + $orderMoip = $request[self::MOIP_ORDER_ID]; + + try { + $client->setUri($url.'orders/'.$orderMoip.'/refunds'); + $client->setConfig(['maxredirects' => 0, 'timeout' => 120]); + $client->setHeaders('Authorization', 'Bearer '.$apiBearer); + $client->setRawData($this->json->serialize($request['send']), 'application/json'); + $client->setMethod(ZendClient::POST); + + $responseBody = $client->request()->getBody(); + + $data = $this->json->unserialize($responseBody); + + if (isset($data['id'])) { + $response = array_merge( + [ + 'RESULT_CODE' => 1, + 'STATUS' => $data['status'], + 'REFUND_ID' => $data['id'], + ], + $data + ); + } else { + $response = array_merge( + [ + 'RESULT_CODE' => 0, + ], + $data + ); + } + $this->logger->debug( + [ + 'url' => $url.'orders/'.$orderMoip.'/refunds', + 'request' => $this->json->serialize($request['send']), + 'response' => $responseBody, + ] + ); + } catch (InvalidArgumentException $e) { + $this->logger->debug( + [ + 'url' => $url.'orders/'.$orderMoip.'/refunds', + 'request' => $this->json->serialize($request['send']), + 'response' => $responseBody, + ] + ); + // phpcs:ignore Magento2.Exceptions.DirectThrow + throw new \Exception('Invalid JSON was returned by the gateway'); } + + return $response; } } diff --git a/Gateway/Request/RefundRequest.php b/Gateway/Request/RefundRequest.php index 3938c4c..145a77b 100755 --- a/Gateway/Request/RefundRequest.php +++ b/Gateway/Request/RefundRequest.php @@ -11,6 +11,8 @@ use Magento\Payment\Gateway\ConfigInterface; use Magento\Payment\Gateway\Data\PaymentDataObjectInterface; use Magento\Payment\Gateway\Request\BuilderInterface; +use Moip\Magento2\Gateway\Config\Config; +use Moip\Magento2\Model\Ui\ConfigProviderBoleto; /** * Class RefundRequest - Refund data structure. @@ -22,18 +24,39 @@ class RefundRequest implements BuilderInterface */ const MOIP_ORDER_ID = 'moip_order_id'; + const BANK_NUMBER = 'moip_magento2_boleto_bank_number'; + + const AGENCY_NUMBER = 'moip_magento2_boleto_agency_number'; + + const AGENCY_CHECK_NUMBER = 'moip_magento2_boleto_agency_check_number'; + + const ACCOUNT_NUMBER = 'moip_magento2_boleto_account_number'; + + const ACCOUNT_CHECK_NUMBER = 'moip_magento2_boleto_account_check_number'; + + const HOLDER_FULLNAME = 'moip_magento2_boleto_account_holder_fullname'; + + const HOLDER_DOCUMENT_NUMBER = 'moip_magento2_boleto_account_holder_document_number'; + /** * @var ConfigInterface */ private $config; + /** + * @var Config + */ + private $configPayment; + /** * @param ConfigInterface $config */ public function __construct( - ConfigInterface $config + ConfigInterface $config, + Config $configPayment ) { $this->config = $config; + $this->configPayment = $configPayment; } /** @@ -47,14 +70,67 @@ public function build(array $buildSubject) throw new \InvalidArgumentException('Payment data object should be provided'); } + $result = []; + $paymentDO = $buildSubject['payment']; $payment = $paymentDO->getPayment(); $order = $payment->getOrder(); - return [ + $creditmemo = $payment->getCreditMemo(); + + $total = $creditmemo->getGrandTotal(); + + $result = [ self::MOIP_ORDER_ID => $order->getExtOrderId(), + 'send' => [ + 'amount' => $this->configPayment->formatPrice($total), + ], ]; + + if ($order->getPayment()->getMethodInstance()->getCode() === ConfigProviderBoleto::CODE) { + $bankNumber = $creditmemo->getData(self::BANK_NUMBER); + $agencyNumber = $creditmemo->getData(self::AGENCY_NUMBER); + $agencyCheckNumber = $creditmemo->getData(self::AGENCY_CHECK_NUMBER); + $accountNumber = $creditmemo->getData(self::ACCOUNT_NUMBER); + $accountCheckNumber = $creditmemo->getData(self::ACCOUNT_CHECK_NUMBER); + $holderFullname = $creditmemo->getData(self::HOLDER_FULLNAME); + $holderDocumment = $creditmemo->getData(self::HOLDER_DOCUMENT_NUMBER); + + $typeDocument = 'CPF'; + $taxDocument = preg_replace('/[^0-9]/', '', $holderDocumment); + if (strlen($taxDocument) === 14) { + $typeDocument = 'CNPJ'; + } + + $resultBoleto = [ + 'send' => [ + 'amount' => $this->configPayment->formatPrice($total), + 'refundingInstrument' => [ + 'method' => 'BANK_ACCOUNT', + 'bankAccount' => [ + 'type' => 'CHECKING', + 'bankNumber' => $bankNumber, + 'agencyNumber' => $agencyNumber, + 'agencyCheckNumber' => $agencyCheckNumber, + 'accountNumber' => $accountNumber, + 'accountCheckNumber' => $accountCheckNumber, + 'holder' => [ + 'fullname' => $holderFullname, + 'taxDocument' => [ + 'type' => $typeDocument, + 'number' => $taxDocument, + ], + ], + ], + ], + ], + ]; + + $result = array_merge($result, $resultBoleto); + } + + return $result; } } diff --git a/Gateway/Request/SellerDataRequest.php b/Gateway/Request/SellerDataRequest.php index f1e2af8..8128344 100644 --- a/Gateway/Request/SellerDataRequest.php +++ b/Gateway/Request/SellerDataRequest.php @@ -134,8 +134,8 @@ public function build(array $buildSubject) $secondaryMPA = $this->config->getSplitValue('secondary_mpa', $storeId); $secondaryPercent = $this->config->getSplitValue('secondary_percent', $storeId); - $commissionUseShipping = $this->config->getSplitValue('secondary_percent_include_shipping', $storeId); - $commissionUseInterest = $this->config->getSplitValue('secondary_percent_include_interest', $storeId); + $commiUseShipping = $this->config->getSplitValue('secondary_percent_include_shipping', $storeId); + $commiUseInterest = $this->config->getSplitValue('secondary_percent_include_interest', $storeId); if ($commissionUseInterest) { if ($payment->getMethod() === 'moip_magento2_cc' || $payment->getMethod() === 'moip_magento2_cc_vault') { @@ -170,11 +170,11 @@ public function build(array $buildSubject) } } - if (!$commissionUseShipping) { + if (!$commiUseShipping) { $total = $total - $orderAdapter->getShippingAmount(); } - if ($commissionUseShipping) { + if ($commiUseInterest) { $total = $total + $addition; } diff --git a/Gateway/Response/RefundHandler.php b/Gateway/Response/RefundHandler.php index 8c8bedf..8431605 100755 --- a/Gateway/Response/RefundHandler.php +++ b/Gateway/Response/RefundHandler.php @@ -10,6 +10,7 @@ use Magento\Payment\Gateway\Data\PaymentDataObjectInterface; use Magento\Payment\Gateway\Response\HandlerInterface; +use Magento\Sales\Model\Order\Creditmemo; /** * Class AcceptPaymentHandler - Deals reading responses for refunded payment authorization. @@ -36,6 +37,14 @@ public function handle(array $handlingSubject, array $response) } $paymentDO = $handlingSubject['payment']; + $payment = $paymentDO->getPayment(); + + $payment->setTransactionId($response['REFUND_ID']); + + if ($response['STATUS'] === 'REQUESTED') { + $creditmemo = $payment->getCreditmemo(); + $creditmemo->setState(Creditmemo::STATE_OPEN); + } if ($response['RESULT_CODE']) { $paymentDO->getPayment(); diff --git a/Gateway/Response/VaultDetailsHandler.php b/Gateway/Response/VaultDetailsHandler.php index 8679690..82b06b5 100755 --- a/Gateway/Response/VaultDetailsHandler.php +++ b/Gateway/Response/VaultDetailsHandler.php @@ -31,7 +31,7 @@ class VaultDetailsHandler implements HandlerInterface /** * @var OrderPaymentExtensionInterfaceFactory */ - protected $paymentExtensionFactory; + protected $payExtensionFactory; /** * @var SubjectReader @@ -56,7 +56,7 @@ class VaultDetailsHandler implements HandlerInterface */ public function __construct( ObjectManagerInterface $objectManager, - OrderPaymentExtensionInterfaceFactory $paymentExtensionFactory, + OrderPaymentExtensionInterfaceFactory $payExtensionFactory, PaymentTokenFactoryInterface $paymentTokenFactory = null ) { if ($paymentTokenFactory === null) { @@ -64,7 +64,7 @@ public function __construct( } $this->objectManager = $objectManager; - $this->paymentExtensionFactory = $paymentExtensionFactory; + $this->payExtensionFactory = $payExtensionFactory; $this->paymentTokenFactory = $paymentTokenFactory; } @@ -146,7 +146,7 @@ private function getExtensionAttributes(InfoInterface $payment): OrderPaymentExt { $extensionAttributes = $payment->getExtensionAttributes(); if (null === $extensionAttributes) { - $extensionAttributes = $this->paymentExtensionFactory->create(); + $extensionAttributes = $this->payExtensionFactory->create(); $payment->setExtensionAttributes($extensionAttributes); } diff --git a/Model/Ui/ConfigProviderBase.php b/Model/Ui/ConfigProviderBase.php index 3c665b7..4d67942 100755 --- a/Model/Ui/ConfigProviderBase.php +++ b/Model/Ui/ConfigProviderBase.php @@ -82,7 +82,7 @@ public function getConfig() return [ 'payment' => [ Config::METHOD => [ - 'isActive' => false + 'isActive' => false, ], ], ]; diff --git a/Model/Ui/Vault/Adminhtml/TokenUiComponentProvider.php b/Model/Ui/Vault/Adminhtml/TokenUiComponentProvider.php index 40d4f17..e586264 100644 --- a/Model/Ui/Vault/Adminhtml/TokenUiComponentProvider.php +++ b/Model/Ui/Vault/Adminhtml/TokenUiComponentProvider.php @@ -8,7 +8,6 @@ namespace Moip\Magento2\Model\Ui\Vault\Adminhtml; - use Magento\Framework\View\Element\Template; use Magento\Vault\Api\Data\PaymentTokenInterface; use Magento\Vault\Model\Ui\TokenUiComponentInterfaceFactory; @@ -21,7 +20,6 @@ class TokenUiComponentProvider implements TokenUiComponentProviderInterface * @var TokenUiComponentInterfaceFactory */ private $componentFactory; - /** * TokenUiComponentProvider constructor. @@ -43,14 +41,15 @@ public function getComponentForToken(PaymentTokenInterface $paymentToken) $component = $this->componentFactory->create( [ 'config' => [ - 'code' => ConfigProviderCc::VAULT_CODE, - TokenUiComponentProviderInterface::COMPONENT_DETAILS => $details, + 'code' => ConfigProviderCc::VAULT_CODE, + TokenUiComponentProviderInterface::COMPONENT_DETAILS => $details, TokenUiComponentProviderInterface::COMPONENT_PUBLIC_HASH => $paymentToken->getPublicHash(), - 'template' => 'Moip_Magento2::form/vault.phtml' + 'template' => 'Moip_Magento2::form/vault.phtml', ], - 'name' => Template::class + 'name' => Template::class, ] ); + return $component; } -} \ No newline at end of file +} diff --git a/Observer/DataAssignObserverCc.php b/Observer/DataAssignObserverCc.php index ec403fe..47f89db 100755 --- a/Observer/DataAssignObserverCc.php +++ b/Observer/DataAssignObserverCc.php @@ -103,7 +103,7 @@ class DataAssignObserverCc extends AbstractDataAssignObserver self::PAYER_HOLDER_BIRTH_DATE, self::PAYER_HOLDER_PHONE, self::PAYER_CC_SAVE, - self::PAYER_CC_CID + self::PAYER_CC_CID, ]; /** diff --git a/Observer/DataAssignObserverCcVault.php b/Observer/DataAssignObserverCcVault.php deleted file mode 100644 index 7bbb4d5..0000000 --- a/Observer/DataAssignObserverCcVault.php +++ /dev/null @@ -1,94 +0,0 @@ - - * See COPYING.txt for license details. - */ - -namespace Moip\Magento2\Observer; - -use Magento\Framework\Event\Observer; -use Magento\Payment\Observer\AbstractDataAssignObserver; -use Magento\Quote\Api\Data\PaymentInterface; -use Moip\Magento2\Gateway\Config\Config; - -/** - * Class DataAssignObserverCc - Capture credit card payment information. - */ -class DataAssignObserverCcVault extends AbstractDataAssignObserver -{ - /** - * @const Method Name Block - */ - const METHOD_NAME = 'method_name'; - - /** - * @const Method Name - */ - const METHOD_NAME_TYPE = 'Cartão de Crédito - Cofre'; - - /** - * @const Credit Card - CVV - */ - const PAYER_CC_CVV = 'cc_cvv'; - - /** - * @const Installment - */ - const PAYER_CC_INSTALLMENTS = 'cc_installments'; - - /** - * @var array - */ - protected $addInformationList = [ - self::PAYER_CC_CVV, - self::PAYER_CC_INSTALLMENTS, - ]; - - /** - * @var - */ - protected $config; - - /** - * @param Config $config - */ - public function __construct( - Config $config - ) { - $this->config = $config; - } - - /** - * @param Observer $observer - */ - public function execute(Observer $observer) - { - $data = $this->readDataArgument($observer); - - $additionalData = $data->getData(PaymentInterface::KEY_ADDITIONAL_DATA); - - if (!is_array($additionalData)) { - return; - } - - $paymentInfo = $this->readPaymentModelArgument($observer); - - $paymentInfo->setAdditionalInformation( - self::METHOD_NAME, - self::METHOD_NAME_TYPE - ); - - foreach ($this->addInformationList as $addInformationKey) { - if (isset($additionalData[$addInformationKey])) { - if ($additionalData[$addInformationKey]) { - $paymentInfo->setAdditionalInformation( - $addInformationKey, - $additionalData[$addInformationKey] - ); - } - } - } - } -} diff --git a/Observer/SetBoletoDataToCreditmemo.php b/Observer/SetBoletoDataToCreditmemo.php new file mode 100644 index 0000000..d987c08 --- /dev/null +++ b/Observer/SetBoletoDataToCreditmemo.php @@ -0,0 +1,63 @@ + + * See COPYING.txt for license details. + */ + +namespace Moip\Magento2\Observer; + +use Magento\Framework\Event\ObserverInterface; +use Moip\Magento2\Block\Adminhtml\Sales\Creditmemo as CreditmemoBlock; +use Moip\Magento2\Model\Ui\ConfigProviderBoleto; + +/** + * Class SetBoletoDataToCreditmemo - Set refund data of boleto. + */ +class SetBoletoDataToCreditmemo implements ObserverInterface +{ + /** + * Set boleto data to creditmemo before register. + * + * @param \Magento\Framework\Event\Observer $observer + * + * @return $this + */ + public function execute(\Magento\Framework\Event\Observer $observer) + { + $input = $observer->getEvent()->getInput(); + /** @var \Magento\Sales\Model\Order\Creditmemo $creditmemo */ + $creditmemo = $observer->getEvent()->getCreditmemo(); + $order = $creditmemo->getOrder(); + + if ($order->getPayment()->getMethodInstance()->getCode() === ConfigProviderBoleto::CODE) { + $bankNumber = !empty($input[CreditmemoBlock::BANK_NUMBER]) ? $input[CreditmemoBlock::BANK_NUMBER] : null; + $creditmemo->setData(CreditmemoBlock::BANK_NUMBER, $bankNumber); + + $agencyNumber = !empty($input[CreditmemoBlock::AGENCY_NUMBER]) ? $input[CreditmemoBlock::AGENCY_NUMBER] : null; + $creditmemo->setData(CreditmemoBlock::AGENCY_NUMBER, $agencyNumber); + + $agencyCheckNumber = !empty($input[CreditmemoBlock::AGENCY_CHECK_NUMBER]) ? $input[CreditmemoBlock::AGENCY_CHECK_NUMBER] : null; + $creditmemo->setData(CreditmemoBlock::AGENCY_CHECK_NUMBER, $agencyCheckNumber); + + $accountNumber = !empty($input[CreditmemoBlock::ACCOUNT_NUMBER]) ? $input[CreditmemoBlock::ACCOUNT_NUMBER] : null; + $creditmemo->setData(CreditmemoBlock::ACCOUNT_NUMBER, $accountNumber); + + $accountCheckNumber = !empty($input[CreditmemoBlock::ACCOUNT_CHECK_NUMBER]) ? $input[CreditmemoBlock::ACCOUNT_CHECK_NUMBER] : null; + $creditmemo->setData(CreditmemoBlock::ACCOUNT_CHECK_NUMBER, $accountCheckNumber); + + $holderFullname = !empty($input[CreditmemoBlock::HOLDER_FULLNAME]) ? $input[CreditmemoBlock::HOLDER_FULLNAME] : null; + $creditmemo->setData(CreditmemoBlock::HOLDER_FULLNAME, $holderFullname); + + $holderDocumment = !empty($input[CreditmemoBlock::HOLDER_DOCUMENT_NUMBER]) ? $input[CreditmemoBlock::HOLDER_DOCUMENT_NUMBER] : null; + $creditmemo->setData(CreditmemoBlock::HOLDER_DOCUMENT_NUMBER, $holderDocumment); + + $comment = !empty($input[CreditmemoBlock::CREDITMEMO_COMMENT_TEXT]) ? $input[CreditmemoBlock::CREDITMEMO_COMMENT_TEXT] : null; + $comment = $comment.'\n'.__('Refund Request to Bank %1, Agency Number %2, Agency Check Number %3, Account Number %4, Account Check Number %5, Holder Name %6, Holder Tax Document %7', $bankNumber, $agencyNumber, $agencyCheckNumber, $accountNumber, $accountCheckNumber, $holderFullname, $holderDocumment); + $creditmemo->setComment($comment); + } + + return $this; + } +} diff --git a/etc/adminhtml/events.xml b/etc/adminhtml/events.xml new file mode 100644 index 0000000..b6cc538 --- /dev/null +++ b/etc/adminhtml/events.xml @@ -0,0 +1,13 @@ + + + + + + + diff --git a/etc/config.xml b/etc/config.xml index 23ab3a8..1b0279d 100755 --- a/etc/config.xml +++ b/etc/config.xml @@ -31,12 +31,12 @@ 1 1 0 - 0 - 0 + 1 + 1 1 1 1 - + 1 1 @@ -81,7 +81,7 @@ 1 0 0 - 0 + 1 1 1 1 @@ -116,7 +116,7 @@ 1 - 1 + 0 Magento2CcVaultFacade Stored Cards (Wirecard) 1 diff --git a/etc/crontab.xml b/etc/crontab.xml index 9c0968f..fb3c372 100755 --- a/etc/crontab.xml +++ b/etc/crontab.xml @@ -9,7 +9,7 @@ - * * * * * + 0 8 * * * 0 11 * * 1-5 diff --git a/etc/di.xml b/etc/di.xml index 6d4e599..7c351ab 100755 --- a/etc/di.xml +++ b/etc/di.xml @@ -463,6 +463,12 @@ + + + Magento2Logger + + + Magento2Logger diff --git a/etc/moip_error_mapping.xml b/etc/moip_error_mapping.xml index 6f8a345..8a37cfe 100755 --- a/etc/moip_error_mapping.xml +++ b/etc/moip_error_mapping.xml @@ -154,5 +154,41 @@ Não foi possível desfazer o pagamento, pois ele já está capturado na adquirente. Dados de pagamento MPOS inválidos. Verifique o CPF/CNPJ, ele não foi informado. + + O valor deve ser informado em centavos. + O valor solicitado para reembolso é maior que o valor do pagamento ou inválido. + O valor solicitado somado aos reembolsos parciais é maior que o valor disponível para reembolso. + Reembolso já realizado. + O reembolso não pode ser realizado pois o pagamento não foi autorizado. + O reembolso não foi autorizado pois o pedido ainda não foi pago. + Informe um instrumento financeiro válido. + Tipo de conta bancária inválido. + Esse pedido possui mais de um pagamento autorizado. É necessário fazer os reembolsos parciais individualmente nos pagamentos. + O identificador do banco deve ser numérico. + O identificador de banco informado é inválido, consulte lista de bancos disponíveis para reembolso. + A agência bancária deve ser numérica. + O digito verificador da agência bancária deve ser numérico ou caracter X. + O número da conta bancária possui caracteres inválidos. Apenas caracteres numéricos são aceitos. + O digito verificador da conta bancária deve ser numérico. + É necessario informar os dados do portador da conta bancária. + Informe o nome completo do titular da conta bancária. + É necessario informar o documento do portador da conta bancária. + Informe o tipo do documento. + O tipo de documento informado é inválido. + O número do documento deve ser informado. + O número do documento possui caracteres inválidos. Apenas caracteres numéricos são aceitos. + Prazo limite de reembolso em cartão de crédito excedido, tente realizar o reembolso em uma conta bancária. + Cliente não possui conta Moip, tente realizar o reembolso em uma conta bancária. + Reembolso só pode ser realizado para conta bancária do mesmo titular do pagamento. + Pagamento só pode ser reembolsado no cartão de crédito no período inferior a 180 dias após autorização pagamento. + Um dos recebedores do pagamento não possui saldo suficiente para o reembolso. + Uma das contas informadas não é recebedora do pagamento. + O recebedor primário não pode assumir o reembolso do recebedor secundário. + O recebedor secundário não pode reembolsar um valor maior do que o recebido no pagamento. + A conta a ser creditada é um dos recebedores do pagamento. Por favor escolha outra forma de reembolso. + O reembolso mPOS pode ser usado se e somente se o pagamento for feito via mPOS. + Para reembolso mPOS só é possível reembolso completo. + Conta Moip não encontrada. + Esse pedido contém transações com formas de pagamento distintas. É necessário fazer os reembolsos individualmente nos pagamentos. diff --git a/view/adminhtml/layout/sales_order_creditmemo_new.xml b/view/adminhtml/layout/sales_order_creditmemo_new.xml new file mode 100644 index 0000000..e72e8d8 --- /dev/null +++ b/view/adminhtml/layout/sales_order_creditmemo_new.xml @@ -0,0 +1,21 @@ + + + + + + + + + + Moip_Magento2::order/creditmemo/create/form.phtml + + + + + diff --git a/view/adminhtml/templates/order/creditmemo/create/form.phtml b/view/adminhtml/templates/order/creditmemo/create/form.phtml new file mode 100644 index 0000000..9f5409e --- /dev/null +++ b/view/adminhtml/templates/order/creditmemo/create/form.phtml @@ -0,0 +1,78 @@ + +
+ getBlockHtml('formkey') ?> + getCreditmemo()->getOrder() ?> + + getChildHtml('order_info') ?> + +
+
+ escapeHtml(__('Payment & Shipping Method')) ?> +
+
+ getIsVirtual()) : ?> +
+ +
+ + + +
+ escapeHtml(__('Payment Information')) ?> +
+
+
getChildHtml('order_payment') ?>
+
+ escapeHtml(__('The order was placed using %1.', $_order->getOrderCurrencyCode())) ?> +
+
+ getChildHtml('order_payment_additional') ?> +
+
+
+ + + getIsVirtual()) : ?> +
+ +
+ escapeHtml(__('Shipping Information')) ?> +
+
+
escapeHtml($_order->getShippingDescription()) ?>
+
+ escapeHtml(__('Total Shipping Charges')) ?>: + + helper(\Magento\Tax\Helper\Data::class)->displaySalesPriceInclTax($block->getSource()->getStoreId())) : ?> + displayShippingPriceInclTax($_order); ?> + + displayPriceAttribute('shipping_amount', false, ' '); ?> + + displayShippingPriceInclTax($_order); ?> + + + helper(\Magento\Tax\Helper\Data::class)->displaySalesBothPrices($block->getSource()->getStoreId()) && $_incl != $_excl) : ?> + (escapeHtml(__('Incl. Tax')) ?> ) + +
+
+
+ +
+
+ + getChildHtml('moip_magento2_boleto_refund'); ?> + +
+ getChildHtml('order_items') ?> +
+
diff --git a/view/adminhtml/templates/sales/creditmemo.phtml b/view/adminhtml/templates/sales/creditmemo.phtml new file mode 100644 index 0000000..57100c5 --- /dev/null +++ b/view/adminhtml/templates/sales/creditmemo.phtml @@ -0,0 +1,107 @@ +canRefundBoleto()): ?> +
+
+ +
+
+
+
+ +
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ +
+ +
+ +
+
+
+
+
+
+ +
+
+ +
+ +
+ +
+
+
+
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+ + +
+
+
+ \ No newline at end of file diff --git a/view/adminhtml/web/css/creditmemo.css b/view/adminhtml/web/css/creditmemo.css new file mode 100644 index 0000000..25bb6a8 --- /dev/null +++ b/view/adminhtml/web/css/creditmemo.css @@ -0,0 +1,18 @@ +.form-data-moip { + max-width: 500px; +} +.admin__field-control-two-field { + display: flex; + margin-top: 1.5rem; + margin-bottom: 1.5rem; +} +.admin__field.field-refund-boleto.agency-number, +.admin__field.field-refund-boleto.account-number { + flex: 2; +} +.admin__field.field-refund-boleto.agency-check-number, +.admin__field.field-refund-boleto.account-check-number { + flex: 1; + margin-top: 0; + padding-left: 1rem; +} \ No newline at end of file diff --git a/view/adminhtml/web/css/system_config.css b/view/adminhtml/web/css/system_config.css new file mode 100755 index 0000000..7688839 --- /dev/null +++ b/view/adminhtml/web/css/system_config.css @@ -0,0 +1,32 @@ +/** + * Copyright Moip. All rights reserved. + * See COPYING.txt for license details. +*/ +.complex.moip-payment-section .heading strong { + display: flex; + flex-direction: row; + align-items: center; + font-weight: normal; +} + +.complex.moip-payment-section .moip-payment-logo { + flex-basis: 15%; + height: 70px; + background: url('images/logo.svg') no-repeat center center; + -webkit-background-size: contain; + -moz-background-size: contain; + -o-background-size: contain; + background-size: contain; +} + +.complex.moip-payment-section .moip-payment-byline { + flex-basis: 85%; + padding-left: 2%; +} + +.complex.moip-payment-section .button-container { float: right; } + +fieldset#payment_other_moip_base, +fieldset#payment_us_moip_base { + margin-left: 2%; +} diff --git a/view/frontend/web/js/view/payment/method-renderer/vault.js b/view/frontend/web/js/view/payment/method-renderer/vault.js index b5c495e..a0d0b03 100755 --- a/view/frontend/web/js/view/payment/method-renderer/vault.js +++ b/view/frontend/web/js/view/payment/method-renderer/vault.js @@ -58,7 +58,7 @@ define([ }, isActive() { - var active = this.getId() === this.isChecked(); + var active = false; this.active(active); return active; }, diff --git a/view/frontend/web/template/payment/boleto.html b/view/frontend/web/template/payment/boleto.html index a7e20c4..1d5ba34 100755 --- a/view/frontend/web/template/payment/boleto.html +++ b/view/frontend/web/template/payment/boleto.html @@ -33,6 +33,11 @@
+
+ + + +