From b19af913b2be91746b6d2995ca1ef79a730daddb Mon Sep 17 00:00:00 2001 From: leonardo albuquerque Date: Thu, 19 Jul 2018 10:23:18 -0300 Subject: [PATCH 01/46] =?UTF-8?q?#11177=20Iniciado=20cria=C3=A7=C3=A3o=20d?= =?UTF-8?q?o=20meio=20de=20pagamento=20por=20cart=C3=A3o=20de=20cr=C3=A9di?= =?UTF-8?q?to?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 - .../Vindi/Payment/Controller/Index/Index.php | 25 + app/code/Vindi/Payment/Model/Api.php | 706 ++++++++++++++++++ .../Payment/Model/Payment/CreditCard.php | 325 ++++++++ .../Vindi/Payment/Model/Payment/Vindi.php | 322 ++++++++ .../Vindi/Payment/etc/adminhtml/system.xml | 56 ++ app/code/Vindi/Payment/etc/config.xml | 16 + .../Vindi/Payment/etc/frontend/routes.xml | 8 + app/code/Vindi/Payment/etc/module.xml | 5 + app/code/Vindi/Payment/etc/payment.xml | 14 + app/code/Vindi/Payment/registration.php | 6 + .../frontend/layout/checkout_index_index.xml | 46 ++ .../payment/method-renderer/vindi-method.js | 16 + .../frontend/web/js/view/payment/vindi.js | 19 + .../web/template/payment/cc-form.html | 107 +++ .../frontend/web/template/payment/vindi.html | 50 ++ 16 files changed, 1721 insertions(+), 1 deletion(-) delete mode 100644 README.md create mode 100644 app/code/Vindi/Payment/Controller/Index/Index.php create mode 100644 app/code/Vindi/Payment/Model/Api.php create mode 100644 app/code/Vindi/Payment/Model/Payment/CreditCard.php create mode 100644 app/code/Vindi/Payment/Model/Payment/Vindi.php create mode 100644 app/code/Vindi/Payment/etc/adminhtml/system.xml create mode 100644 app/code/Vindi/Payment/etc/config.xml create mode 100644 app/code/Vindi/Payment/etc/frontend/routes.xml create mode 100644 app/code/Vindi/Payment/etc/module.xml create mode 100644 app/code/Vindi/Payment/etc/payment.xml create mode 100644 app/code/Vindi/Payment/registration.php create mode 100644 app/code/Vindi/Payment/view/frontend/layout/checkout_index_index.xml create mode 100644 app/code/Vindi/Payment/view/frontend/web/js/view/payment/method-renderer/vindi-method.js create mode 100644 app/code/Vindi/Payment/view/frontend/web/js/view/payment/vindi.js create mode 100644 app/code/Vindi/Payment/view/frontend/web/template/payment/cc-form.html create mode 100644 app/code/Vindi/Payment/view/frontend/web/template/payment/vindi.html diff --git a/README.md b/README.md deleted file mode 100644 index 83f0885e..00000000 --- a/README.md +++ /dev/null @@ -1 +0,0 @@ -# vindi-magento2 diff --git a/app/code/Vindi/Payment/Controller/Index/Index.php b/app/code/Vindi/Payment/Controller/Index/Index.php new file mode 100644 index 00000000..f59a2c10 --- /dev/null +++ b/app/code/Vindi/Payment/Controller/Index/Index.php @@ -0,0 +1,25 @@ +_pageFactory = $pageFactory; + $this->api = $api; + return parent::__construct($context); + } + + public function execute() + { + return $this->_pageFactory->create(); + } +} \ No newline at end of file diff --git a/app/code/Vindi/Payment/Model/Api.php b/app/code/Vindi/Payment/Model/Api.php new file mode 100644 index 00000000..7b36957b --- /dev/null +++ b/app/code/Vindi/Payment/Model/Api.php @@ -0,0 +1,706 @@ +scopeConfig = $scopeConfig; + $this->logger = $logger; + $this->cacheType = $cacheType; + $this->message = $message; + + $storeScope = \Magento\Store\Model\ScopeInterface::SCOPE_STORE; + $isSandBox = $this->scopeConfig->getValue('payment/vindi/sandboxmode', $storeScope); + + if ($isSandBox) { + $this->base_path = 'https://sandbox-app.vindi.com.br/api/v1/'; + } else { + $this->base_path = 'https://app.vindi.com.br/api/v1/'; + } + + $moduleInfo = $moduleList->getOne('Vindi_Payment'); + $this->version = $moduleInfo['setup_version']; + $this->key = $this->scopeConfig->getValue('payment/vindi/key', $storeScope); + } + + + public function execute(Observer $observer) + { + $storeScope = \Magento\Store\Model\ScopeInterface::SCOPE_STORE; + $notifyEmail = $this->scopeConfig->getValue(self::BASEPATH, $storeScope); + + echo $notifyEmail; + } + + /** + * @param string $message + * @param int|null $level + */ + private function log($message) + { + $this->logger->warning($message); + } + + /** + * @return \Zend_Cache_Core + */ + private function cache() + { + return $this->cacheType; + } + + /** + * Build HTTP Query. + * + * @param array $data + * + * @return string + */ + private function buildBody($data) + { + $body = null; + if (!empty($data)) { + $body = json_encode($data); + } + return $body; + } + + /** + * @param array $error + * @param $endpoint + * + * @return string + */ + private function getErrorMessage($error, $endpoint) + { + return "Erro em $endpoint: {$error['id']}: {$error['parameter']} - {$error['message']}"; + } + + /** + * @param array $response + * @param $endpoint + * + * @return bool + */ + private function checkResponse($response, $endpoint) + { + if (isset($response['errors']) && !empty($response['errors'])) { + foreach ($response['errors'] as $error) { + $message = $this->getErrorMessage($error, $endpoint); + $this->message->addErrorMessage($message); + $this->lastError = $message; + } + return false; + } + $this->lastError = ''; + return true; + } + + /** + * Perform request to API. + * + * @param string $endpoint + * @param string $method + * @param array $data + * @param null $dataToLog + * + * @return array|bool|mixed + */ + private function request($endpoint, $method = 'POST', $data = [], $dataToLog = null) + { + if (!$this->key) { + return false; + } + $url = $this->base_path . $endpoint; + $body = $this->buildBody($data); + $requestId = rand(); + $dataToLog = null !== $dataToLog ? $this->buildBody($dataToLog) : $body; + $this->log(sprintf("[Request #%s]: Novo Request para a API.\n%s %s\n%s", $requestId, $method, $url, + $dataToLog)); + $ch = curl_init(); + $ch_options = [ + CURLOPT_HTTPHEADER => [ + 'Content-Type: application/json', + ], + CURLOPT_TIMEOUT => 60, + CURLOPT_SSL_VERIFYPEER => true, + CURLOPT_HEADER => true, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_USERAGENT => 'Vindi-Magento/' . $this->version, + CURLOPT_SSLVERSION => 'CURL_SSLVERSION_TLSv1_2', + CURLOPT_USERPWD => $this->key . ':', + CURLOPT_URL => $url, + CURLOPT_CUSTOMREQUEST => $method + ]; + if (!empty($body)) { + $ch_options[CURLOPT_POSTFIELDS] = $body; + } + curl_setopt_array($ch, $ch_options); + $response = curl_exec($ch); + $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + $body = substr($response, curl_getinfo($ch, CURLINFO_HEADER_SIZE)); + if (curl_errno($ch) || $response === false) { + $this->log(sprintf("[Request #%s]: Erro ao fazer request!\n%s", $requestId, print_r($response, true))); + return false; + } + curl_close($ch); + $status = "HTTP Status: $statusCode"; + $this->log(sprintf("[Request #%s]: Nova Resposta da API.\n%s\n%s", $requestId, $status, $body)); + $responseBody = json_decode($body, true); + if (!$responseBody) { + $this->log(sprintf('[Request #%s]: Erro ao recuperar corpo do request! %s', $requestId, + print_r($body, true))); + return false; + } + if (!$this->checkResponse($responseBody, $endpoint)) { + return false; + } + return $responseBody; + } + + /** + * Make an API request to create a Customer. + * + * @param array $body (name, email, code) + * + * @return array|bool|mixed + */ + public function createCustomer($body) + { + if ($response = $this->request('customers', 'POST', $body)) { + return $response['customer']['id']; + } + return false; + } + + /** + * Make an API request to retrieve an existing Customer. + * + * @param string $code + * + * @return array|bool|mixed + */ + public function findCustomerByCode($code) + { + $customerId = $this->cache()->load("vindi_customer_by_code_{$code}"); + if ($customerId === false) { + $response = $this->request("customers/search?code={$code}", 'GET'); + if ($response && (1 === count($response['customers'])) && isset($response['customers'][0]['id'])) { + $customerId = $response['customers'][0]['id']; + $this->cache()->save(serialize($customerId), "vindi_customer_by_code_{$code}", ['vindi_cache'], + 5 * 60); // 5 minutes + } + } else { + $customerId = unserialize($customerId); + } + return $customerId; + } + + /** + * Make an API request to retrieve an existing Customer or to create one if not found. + * + * @param array $body (name, email, code) + * + * @return array|bool|mixed + */ + public function findOrCreateCustomer($body) + { + $customerId = $this->findCustomerByCode($body['code']); + // TODO update information + if (false === $customerId) { + return $this->createCustomer($body); + } + return $customerId; + } + + /** + * Make an API request to create a Payment Profile to a Customer. + * + * @param $body (holder_name, card_expiration, card_number, card_cvv, customer_id) + * + * @return array|bool|mixed + */ + public function createCustomerPaymentProfile($body) + { + // Protect credit card number. + $dataToLog = $body; + $dataToLog['card_number'] = '**** *' . substr($dataToLog['card_number'], -3); + $dataToLog['card_cvv'] = '***'; + $customerId = $body['customer_id']; + $this->cache()->remove("vindi_payment_profile_{$customerId}"); + return $this->request('payment_profiles', 'POST', $body, $dataToLog); + } + + /** + * Make an API request to verify a Payment Profile to a Customer. + * + * @param $id integer + * + * @return array|bool|mixed + */ + public function verifyCustomerPaymentProfile($id) + { + return $this->request('payment_profiles/' . $id . '/verify', 'POST'); + } + + /** + * @param $userCode + * + * @return bool + */ + public function getCustomerPaymentProfile($userCode, $type = "CreditCard") + { + $customerId = $this->findCustomerByCode($userCode); + if (false === $customerId) { + return false; + } + $paymentProfile = $this->cache()->load("vindi_payment_profile_{$customerId}"); + if ($paymentProfile === false || strpos($paymentProfile, $type) === false) { + $endpoint = 'payment_profiles?query=customer_id%3D' . $customerId + . '%20status%3Dactive%20type%3DPaymentProfile%3A%3A' . $type; + $response = $this->request($endpoint, 'GET'); + if ($response && $response['payment_profiles'] && count($response['payment_profiles'])) { + $paymentProfile = $response['payment_profiles'][0]; + $this->cache()->save(serialize($paymentProfile), "vindi_payment_profile_{$customerId}", ['vindi_cache'], + 5 * 60); // 5 minutes + } else { + $paymentProfile = false; + } + } else { + $paymentProfile = unserialize($paymentProfile); + } + return $paymentProfile; + } + + /** + * Make an API request to create a Subscription. + * + * @param $body (plan_id, customer_id, payment_method_code, product_items[{product_id}]) + * + * @return array + */ + public function createSubscription($body) + { + if (($response = $this->request('subscriptions', 'POST', $body)) && isset($response['subscription']['id'])) { + $subscription = $response['subscription']; + $subscription['bill'] = $response['bill']; + return $subscription; + } + return false; + } + + /** + * Make an API request to retrieve Payment Methods. + * + * @return array|bool + */ + public function getPaymentMethods() + { + $paymentMethods = $this->cache()->load('vindi_payment_methods'); + if ($paymentMethods === false) { + $paymentMethods = [ + 'credit_card' => [], + 'debit_card' => [], + 'bank_slip' => false, + ]; + $response = $this->request('payment_methods', 'GET'); + if (false === $response) { + return $this->acceptBankSlip = false; + } + foreach ($response['payment_methods'] as $method) { + if ('active' !== $method['status']) { + continue; + } + if ('PaymentMethod::CreditCard' === $method['type']) { + $paymentMethods['credit_card'] = array_merge( + $paymentMethods['credit_card'], + $method['payment_companies'] + ); + } elseif ('PaymentMethod::DebitCard' === $method['type']) { + $paymentMethods['debit_card'] = array_merge( + $paymentMethods['debit_card'], + $method['payment_companies'] + ); + } elseif ('PaymentMethod::BankSlip' === $method['type']) { + $paymentMethods['bank_slip'] = true; + } + } + $this->cache()->save(serialize($paymentMethods), 'vindi_payment_methods', ['vindi_cache'], + 12 * 60 * 60); // 12 hours + } else { + $paymentMethods = unserialize($paymentMethods); + } + $this->acceptBankSlip = $paymentMethods['bank_slip']; + return $paymentMethods; + } + + /** + * Retrieve Credit Card Types from Payment Methods. + * + * @return array + */ + public function getCreditCardTypes() + { + $methods = $this->getPaymentMethods(); + $types = []; + foreach ($methods['credit_card'] as $type) { + $types[$type['code']] = $type['name']; + } + return $types; + } + + /** + * Retrieve Debit Card Types from Payment Methods. + * + * @return array + */ + public function getDebitCardTypes() + { + $methods = $this->getPaymentMethods(); + $types = []; + foreach ($methods['debit_card'] as $type) { + $types[$type['code']] = $type['name']; + } + return $types; + } + + /** + * @return bool|null + */ + public function acceptBankSlip() + { + if (null === $this->acceptBankSlip) { + $this->getPaymentMethods(); + } + return $this->acceptBankSlip; + } + + /** + * @param array $body + * + * @return int|bool + */ + public function createBill($body) + { + if ($response = $this->request('bills', 'POST', $body)) { + return $response['bill']; + } + return false; + } + + /** + * @param $billId + * + * @return array|bool|mixed + */ + public function approveBill($billId) + { + $response = $this->request("bills/{$billId}", 'GET'); + if (false === $response || !isset($response['bill'])) { + return false; + } + $bill = $response['bill']; + if ('review' !== $bill['status']) { + return true; + } + return $this->request("bills/{$billId}/approve", 'POST'); + } + + /** + * @param $billId + */ + public function deleteBill($billId) + { + $this->request("bills/{$billId}", 'DELETE'); + } + + /** + * @param $billId + * + * @return string + */ + public function getBankSlipDownload($billId) + { + $response = $this->request("bills/{$billId}", 'GET'); + if (false === $response) { + return false; + } + return $response['bill']['charges'][0]['print_url']; + } + + /** + * @return array + */ + public function getProducts() + { + $list = []; + $response = $this->request('products?query=status:active', 'GET'); + if ($products = $response['products']) { + foreach ($products as $product) { + $list[$product['id']] = "{$product['name']} ({$product['pricing_schema']['short_format']})"; + } + } + return $list; + } + + /** + * @param int $id + * + * @return array + */ + public function getPlanItems($id) + { + $list = []; + $response = $this->request("plans/{$id}", 'GET'); + if ($plan = $response['plan']) { + foreach ($plan['plan_items'] as $item) { + if (isset($item['product'])) { + $list[] = $item['product']['id']; + } + } + } + return $list; + } + + /** + * @param Mage_Sales_Model_Order $order + * + * @return array + */ + public function buildPlanItemsForSubscription($order) + { + $list = []; + $orderItems = $order->getItemsCollection(); + $orderSubtotal = $order->getQuote()->getSubtotal(); + $orderDiscount = $order->getDiscountAmount() * -1; + $discount = null; + if (!empty($orderDiscount)) { + $discountPercentage = $orderDiscount * 100 / $orderSubtotal; + $discountPercentage = number_format(floor($discountPercentage * 100) / 100, 2); + $discount = [[ + 'discount_type' => 'percentage', + 'percentage' => $discountPercentage + ]]; + } + foreach ($orderItems as $item) { + $product = Mage::getModel('catalog/product')->load($item->getProductId()); + if ($product->getTypeID() !== 'subscription') { + throw new \Exception("O produto {$item->getName()} não é uma assinatura."); + return false; + } + $productVindiId = $this->findOrCreateProduct(array('sku' => $item->getSku(), 'name' => $item->getName())); + for ($i = 1; $i <= $item->getQtyOrdered(); $i++) { + $list[] = [ + 'product_id' => $productVindiId, + 'pricing_schema' => ['price' => $item->getPrice()], + 'discounts' => $discount, + ]; + } + } + // Create product for shipping + $productVindiId = $this->findOrCreateProduct(array('sku' => 'frete', 'name' => 'Frete')); + $list[] = [ + 'product_id' => $productVindiId, + 'pricing_schema' => ['price' => $order->getShippingAmount()], + ]; + return $list; + } + + /** + * @return array + */ + public function getPlans() + { + $list = $this->cache()->load('vindi_plans'); + if (($list === false) || !count($list = unserialize($list))) { + $list = []; + $response = $this->request('plans?query=status:active', 'GET'); + if ($plans = $response['plans']) { + foreach ($plans as $plan) { + $list[$plan['id']] = $plan['name']; + } + } + $this->cache()->save(serialize($list), 'vindi_plans', ['vindi_cache'], 10 * 60); // 10 minutes + } + return $list; + } + + public function getPlanInstallments($id) + { + $response = $this->request("plans/{$id}", 'GET'); + $plan = $response['plan']; + $installments = $plan['installments']; + return $installments; + } + + /** + * Make an API request to create a Product. + * + * @param array $body (name, code, status, pricing_schema (price)) + * + * @return array|bool|mixed + */ + public function createProduct($body) + { + if ($response = $this->request('products', 'POST', $body)) { + return $response['product']['id']; + } + return false; + } + + /** + * Make an API request to retrieve an existing Product. + * + * @param string $code + * + * @return array|bool|mixed + */ + public function findProductByCode($code) + { + $response = $this->request("products?query=code%3D{$code}", 'GET'); + if ($response && (1 === count($response['products'])) && isset($response['products'][0]['id'])) { + return $response['products'][0]['id']; + } + return false; + } + + /** + * Make an API request to retrieve the Unique Payment Product or to create it if not found. + * + * @return array|bool|mixed + */ + public function findOrCreateUniquePaymentProduct() + { + $productId = $this->findProductByCode('mag-pagtounico'); + if (false === $productId) { + return $this->createProduct([ + 'name' => 'Pagamento Único (não remover)', + 'code' => 'mag-pagtounico', + 'status' => 'active', + 'pricing_schema' => [ + 'price' => 0, + ], + ]); + } + return $productId; + } + + /** + * Make an API request to retrieve a Product or to create it if not found. + * @param array $product + * + * @return array|bool|mixed + */ + public function findOrCreateProduct($product) + { + // + $productId = $this->findProductByCode($product['sku']); + if (false === $productId) { + return $this->createProduct([ + 'name' => $product['name'], + 'code' => $product['sku'], + 'status' => 'active', + 'pricing_schema' => [ + 'price' => 0, + ], + ]); + } + return $productId; + } + + /** + * Make an API request to retrieve information about the Merchant. + * + * @return array|bool|mixed + */ + public function getMerchant() + { + $merchant = $this->cache()->load('vindi_merchant'); + if ($merchant === false) { + $response = $this->request('merchant', 'GET'); + if (!$response || !isset($response['merchant'])) { + return false; + } + $merchant = $response['merchant']; + $this->cache()->save(serialize($merchant), 'vindi_merchant', ['vindi_cache'], 1 * 60 * 60); // 1 hour + } else { + $merchant = unserialize($merchant); + } + return $merchant; + } + + /** + * Check to see if Merchant Status is Trial. + * + * @return boolean + */ + public function isMerchantStatusTrial() + { + if ($merchant = $this->getMerchant()) { + return 'trial' === $merchant['status']; + } + return false; + } + + /** + * @param $billId + * + * @return array|bool + */ + public function getBill($billId) + { + $response = $this->request("bills/{$billId}", 'GET'); + if (!$response || !isset($response['bill'])) { + return false; + } + return $response['bill']; + } + + public function getDebitCardRedirectUrl($billId) + { + $bill = $this->request('bills/' . $billId, 'GET'); + $chargeId = $bill['bill']['charges'][0]['id']; + $charged = $this->request('charges/' . $chargeId . '/charge', 'POST', [ + 'id' => $bill['bill']['payment_profile']['id'] + ]); + return $charged['charge']['last_transaction']['gateway_response_fields']['authorization_url']; + } +} \ No newline at end of file diff --git a/app/code/Vindi/Payment/Model/Payment/CreditCard.php b/app/code/Vindi/Payment/Model/Payment/CreditCard.php new file mode 100644 index 00000000..88b1ba8d --- /dev/null +++ b/app/code/Vindi/Payment/Model/Payment/CreditCard.php @@ -0,0 +1,325 @@ +getInfoInstance(); + $quote = $info->getQuote(); + + $info->setAdditionalInformation('installments', $data->getCcInstallments()); + + if ($data->getCcChoice() === 'saved') { + $info->setAdditionalInformation('PaymentMethod', $this->_code) + ->setAdditionalInformation('use_saved_cc', true); + + return $this; + } + + $info->setCcType($data->getCcType()) + ->setCcOwner($data->getCcOwner()) + ->setCcLast4(substr($data->getCcNumber(), -4)) + ->setCcNumber($data->getCcNumber()) + ->setCcCid($data->getCcCid()) + ->setCcExpMonth($data->getCcExpMonth()) + ->setCcExpYear($data->getCcExpYear()) + ->setCcSsIssue($data->getCcSsIssue()) + ->setCcSsStartMonth($data->getCcSsStartMonth()) + ->setCcSsStartYear($data->getCcSsStartYear()) + ->setAdditionalInformation('PaymentMethod', $this->_code) + ->setAdditionalInformation('use_saved_cc', false); + + return $this; + } + + /** + * @param string $paymentAction + * @param object $stateObject + * + * @return bool|Mage_Payment_Model_Method_Abstract + */ + protected function processNewOrder($paymentAction, $stateObject) + { + $payment = $this->getInfoInstance(); + $order = $payment->getOrder(); + + $customer = Mage::getModel('customer/customer'); + + $customerId = $this->createCustomer($order, $customer); + $customerVindiId = $customer->getVindiUserCode(); + + if (!$payment->getAdditionalInformation('use_saved_cc')) { + $this->createPaymentProfile($customerId); + } else { + $this->assignDataFromPreviousPaymentProfile($customerVindiId); + } + + if ($this->isSingleOrder($order)) { + $result = $this->processSinglePayment($payment, $order, $customerId); + } else { + $result = $this->processSubscription($payment, $order, $customerId); + } + + if (!$result) { + return false; + } + + $billData = $this->api()->getBill($result); + $installments = $billData['installments']; + $response_fields = $billData['charges'][0]['last_transaction']['gateway_response_fields']; + $possible = ['nsu', 'proof_of_sale']; + $nsu = ''; + foreach ($possible as $nsu_field) { + if ($response_fields[$nsu_field]) { + $nsu = $response_fields[$nsu_field]; + } + } + + $this->getInfoInstance()->setAdditionalInformation( + [ + 'installments' => $installments, + 'nsu' => $nsu + ] + ); + + $stateObject->setStatus(Mage_Sales_Model_Order::STATE_PENDING_PAYMENT) + ->setState(Mage_Sales_Model_Order::STATE_PENDING_PAYMENT); + + return $this; + } + + /** + * @param int $customerId + * + * @return array|bool + */ + protected function createPaymentProfile($customerId) + { + $payment = $this->getInfoInstance(); + + $creditCardData = [ + 'holder_name' => $payment->getCcOwner(), + 'card_expiration' => str_pad($payment->getCcExpMonth(), 2, '0', STR_PAD_LEFT) + . '/' . $payment->getCcExpYear(), + 'card_number' => $payment->getCcNumber(), + 'card_cvv' => $payment->getCcCid() ?: '000', + 'customer_id' => $customerId, + 'payment_company_code' => $payment->getCcType(), + 'payment_method_code' => $this->getPaymentMethodCode() + ]; + + $paymentProfile = $this->api()->createCustomerPaymentProfile($creditCardData); + + if ($paymentProfile === false) { + Mage::throwException('Erro ao informar os dados de cartão de crédito. Verifique os dados e tente novamente!'); + + return false; + } + + $verifyMethod = Mage::getStoreConfig('vindi_subscription/general/verify_method'); + + if ($verifyMethod && !$this->verifyPaymentProfile($paymentProfile['payment_profile']['id'])) { + Mage::throwException('Não foi possível realizar a verificação do seu cartão de crédito!'); + return false; + } + return $paymentProfile; + } + + /** + * @param int $paymentProfileId + * + * @return array|bool + */ + public function verifyPaymentProfile($paymentProfileId) + { + $verify_status = $this->api()->verifyCustomerPaymentProfile($paymentProfileId); + return ($verify_status['transaction']['status'] === 'success'); + } + + /** + * @param int $customerVindiId + */ + protected function assignDataFromPreviousPaymentProfile($customerVindiId) + { + $api = Mage::helper('vindi_subscription/api'); + $savedCc = $api->getCustomerPaymentProfile($customerVindiId); + $info = $this->getInfoInstance(); + + $info->setCcType($savedCc['payment_company']['code']) + ->setCcOwner($savedCc['holder_name']) + ->setCcLast4($savedCc['card_number_last_four']) + ->setCcNumber($savedCc['card_number_last_four']) + ->setAdditionalInformation('use_saved_cc', true); + } + + /** + * Check whether payment method can be used + * + * @param Mage_Sales_Model_Quote|null $quote + * + * @return bool + */ + public function isAvailable($quote = null) + { + return Mage::getStoreConfig('payment/vindi_creditcard/active') + && Mage::helper('vindi_subscription')->getKey(); + } + + /** + * Validate payment method information object + * + * @return Mage_Payment_Model_Method_Abstract + */ + public function validate() + { + $info = $this->getInfoInstance(); + + $quote = $info->getQuote(); + + $maxInstallmentsNumber = Mage::getStoreConfig('payment/vindi_creditcard/max_installments_number'); + + if ($this->isSingleOrder($quote) && ($maxInstallmentsNumber > 1)) { + if (!$installments = $info->getAdditionalInformation('installments')) { + return $this->error('Você deve informar o número de parcelas.'); + } + + if ($installments > $maxInstallmentsNumber) { + return $this->error('O número de parcelas selecionado é inválido.'); + } + + $minInstallmentsValue = Mage::getStoreConfig('payment/vindi_creditcard/min_installment_value'); + $installmentValue = ceil($quote->getGrandTotal() / $installments * 100) / 100; + + if (($installmentValue < $minInstallmentsValue) && ($installments > 1)) { + return $this->error('O número de parcelas selecionado é inválido.'); + } + } + + if ($info->getAdditionalInformation('use_saved_cc')) { + return $this; + } + + $availableTypes = $this->api()->getCreditCardTypes(); + + $ccNumber = $info->getCcNumber(); + + // remove credit card non-numbers + $ccNumber = preg_replace('/\D/', '', $ccNumber); + + $info->setCcNumber($ccNumber); + + if (!$this->_validateExpDate($info->getCcExpYear(), $info->getCcExpMonth())) { + return $this->error(Mage::helper('payment')->__('Incorrect credit card expiration date.')); + } + + if (!array_key_exists($info->getCcType(), $availableTypes)) { + return $this->error(Mage::helper('payment')->__('Credit card type is not allowed for this payment method.')); + } + + return $this; + } + + /** + * @param string $errorMsg + * + * @return bool + * @throws \Mage_Core_Exception + */ + private function error($errorMsg) + { + Mage::throwException($errorMsg); + + return false; + } + + /** + * @return string + */ + protected function getPaymentMethodCode() + { + // TODO fix it to proper method code + return 'credit_card'; + } +} diff --git a/app/code/Vindi/Payment/Model/Payment/Vindi.php b/app/code/Vindi/Payment/Model/Payment/Vindi.php new file mode 100644 index 00000000..b75a61a2 --- /dev/null +++ b/app/code/Vindi/Payment/Model/Payment/Vindi.php @@ -0,0 +1,322 @@ +getInfoInstance(); + $quote = $info->getQuote(); + + $info->setAdditionalInformation('installments', $data->getCcInstallments()); + + if ($data->getCcChoice() === 'saved') { + $info->setAdditionalInformation('PaymentMethod', $this->_code) + ->setAdditionalInformation('use_saved_cc', true); + + return $this; + } + + $info->setCcType($data->getCcType()) + ->setCcOwner($data->getCcOwner()) + ->setCcLast4(substr($data->getCcNumber(), -4)) + ->setCcNumber($data->getCcNumber()) + ->setCcCid($data->getCcCid()) + ->setCcExpMonth($data->getCcExpMonth()) + ->setCcExpYear($data->getCcExpYear()) + ->setCcSsIssue($data->getCcSsIssue()) + ->setCcSsStartMonth($data->getCcSsStartMonth()) + ->setCcSsStartYear($data->getCcSsStartYear()) + ->setAdditionalInformation('PaymentMethod', $this->_code) + ->setAdditionalInformation('use_saved_cc', false); + + return $this; + } + + /** + * @param string $paymentAction + * @param object $stateObject + * + * @return bool|Mage_Payment_Model_Method_Abstract + */ + protected function processNewOrder($paymentAction, $stateObject) + { + $payment = $this->getInfoInstance(); + $order = $payment->getOrder(); + + $customer = Mage::getModel('customer/customer'); + + $customerId = $this->createCustomer($order, $customer); + $customerVindiId = $customer->getVindiUserCode(); + + if (!$payment->getAdditionalInformation('use_saved_cc')) { + $this->createPaymentProfile($customerId); + } else { + $this->assignDataFromPreviousPaymentProfile($customerVindiId); + } + + if ($this->isSingleOrder($order)) { + $result = $this->processSinglePayment($payment, $order, $customerId); + } else { + $result = $this->processSubscription($payment, $order, $customerId); + } + + if (!$result) { + return false; + } + + $billData = $this->api()->getBill($result); + $installments = $billData['installments']; + $response_fields = $billData['charges'][0]['last_transaction']['gateway_response_fields']; + $possible = ['nsu', 'proof_of_sale']; + $nsu = ''; + foreach ($possible as $nsu_field) { + if ($response_fields[$nsu_field]) { + $nsu = $response_fields[$nsu_field]; + } + } + + $this->getInfoInstance()->setAdditionalInformation( + [ + 'installments' => $installments, + 'nsu' => $nsu + ] + ); + + $stateObject->setStatus(Mage_Sales_Model_Order::STATE_PENDING_PAYMENT) + ->setState(Mage_Sales_Model_Order::STATE_PENDING_PAYMENT); + + return $this; + } + + /** + * @param int $customerId + * + * @return array|bool + */ + protected function createPaymentProfile($customerId) + { + $payment = $this->getInfoInstance(); + + $creditCardData = [ + 'holder_name' => $payment->getCcOwner(), + 'card_expiration' => str_pad($payment->getCcExpMonth(), 2, '0', STR_PAD_LEFT) + . '/' . $payment->getCcExpYear(), + 'card_number' => $payment->getCcNumber(), + 'card_cvv' => $payment->getCcCid() ?: '000', + 'customer_id' => $customerId, + 'payment_company_code' => $payment->getCcType(), + 'payment_method_code' => $this->getPaymentMethodCode() + ]; + + $paymentProfile = $this->api()->createCustomerPaymentProfile($creditCardData); + + if ($paymentProfile === false) { + Mage::throwException('Erro ao informar os dados de cartão de crédito. Verifique os dados e tente novamente!'); + + return false; + } + + $verifyMethod = Mage::getStoreConfig('vindi_subscription/general/verify_method'); + + if ($verifyMethod && !$this->verifyPaymentProfile($paymentProfile['payment_profile']['id'])) { + Mage::throwException('Não foi possível realizar a verificação do seu cartão de crédito!'); + return false; + } + return $paymentProfile; + } + + /** + * @param int $paymentProfileId + * + * @return array|bool + */ + public function verifyPaymentProfile($paymentProfileId) + { + $verify_status = $this->api()->verifyCustomerPaymentProfile($paymentProfileId); + return ($verify_status['transaction']['status'] === 'success'); + } + + /** + * @param int $customerVindiId + */ + protected function assignDataFromPreviousPaymentProfile($customerVindiId) + { + $api = Mage::helper('vindi_subscription/api'); + $savedCc = $api->getCustomerPaymentProfile($customerVindiId); + $info = $this->getInfoInstance(); + + $info->setCcType($savedCc['payment_company']['code']) + ->setCcOwner($savedCc['holder_name']) + ->setCcLast4($savedCc['card_number_last_four']) + ->setCcNumber($savedCc['card_number_last_four']) + ->setAdditionalInformation('use_saved_cc', true); + } + + /** + * Validate payment method information object + * + * @return Mage_Payment_Model_Method_Abstract + */ + public function validate() + { + $info = $this->getInfoInstance(); + + $quote = $info->getQuote(); + + $maxInstallmentsNumber = Mage::getStoreConfig('payment/vindi_creditcard/max_installments_number'); + + if ($this->isSingleOrder($quote) && ($maxInstallmentsNumber > 1)) { + if (!$installments = $info->getAdditionalInformation('installments')) { + return $this->error('Você deve informar o número de parcelas.'); + } + + if ($installments > $maxInstallmentsNumber) { + return $this->error('O número de parcelas selecionado é inválido.'); + } + + $minInstallmentsValue = Mage::getStoreConfig('payment/vindi_creditcard/min_installment_value'); + $installmentValue = ceil($quote->getGrandTotal() / $installments * 100) / 100; + + if (($installmentValue < $minInstallmentsValue) && ($installments > 1)) { + return $this->error('O número de parcelas selecionado é inválido.'); + } + } + + if ($info->getAdditionalInformation('use_saved_cc')) { + return $this; + } + + $availableTypes = $this->api()->getCreditCardTypes(); + + $ccNumber = $info->getCcNumber(); + + // remove credit card non-numbers + $ccNumber = preg_replace('/\D/', '', $ccNumber); + + $info->setCcNumber($ccNumber); + + if (!$this->_validateExpDate($info->getCcExpYear(), $info->getCcExpMonth())) { + return $this->error(Mage::helper('payment')->__('Incorrect credit card expiration date.')); + } + + if (!array_key_exists($info->getCcType(), $availableTypes)) { + return $this->error(Mage::helper('payment')->__('Credit card type is not allowed for this payment method.')); + } + + return $this; + } + + /** + * @param string $errorMsg + * + * @return bool + * @throws \Mage_Core_Exception + */ + private function error($errorMsg) + { + Mage::throwException($errorMsg); + + return false; + } + + /** + * @return string + */ + protected function getPaymentMethodCode() + { + return 'credit_card'; + } +} diff --git a/app/code/Vindi/Payment/etc/adminhtml/system.xml b/app/code/Vindi/Payment/etc/adminhtml/system.xml new file mode 100644 index 00000000..82844330 --- /dev/null +++ b/app/code/Vindi/Payment/etc/adminhtml/system.xml @@ -0,0 +1,56 @@ + + + +
+ + + + + Magento\Config\Model\Config\Source\Yesno + + + + + + + + Magento\Config\Model\Config\Source\Yesno + + + + + + + + Magento\Sales\Model\Config\Source\Order\Status\NewStatus + + + + Magento\Payment\Model\Config\Source\Allspecificcountries + + + + Magento\Directory\Model\Config\Source\Country + 1 + + + + + + + + +
+
+
diff --git a/app/code/Vindi/Payment/etc/config.xml b/app/code/Vindi/Payment/etc/config.xml new file mode 100644 index 00000000..8df8ef3f --- /dev/null +++ b/app/code/Vindi/Payment/etc/config.xml @@ -0,0 +1,16 @@ + + + + + + 1 + Vindi\Payment\Model\Payment\Vindi + pending + Vindi + 0 + offline + + + + diff --git a/app/code/Vindi/Payment/etc/frontend/routes.xml b/app/code/Vindi/Payment/etc/frontend/routes.xml new file mode 100644 index 00000000..3effe552 --- /dev/null +++ b/app/code/Vindi/Payment/etc/frontend/routes.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/code/Vindi/Payment/etc/module.xml b/app/code/Vindi/Payment/etc/module.xml new file mode 100644 index 00000000..ce0cf03b --- /dev/null +++ b/app/code/Vindi/Payment/etc/module.xml @@ -0,0 +1,5 @@ + + + + diff --git a/app/code/Vindi/Payment/etc/payment.xml b/app/code/Vindi/Payment/etc/payment.xml new file mode 100644 index 00000000..84ca3481 --- /dev/null +++ b/app/code/Vindi/Payment/etc/payment.xml @@ -0,0 +1,14 @@ + + + + + + + + + + 1 + + + diff --git a/app/code/Vindi/Payment/registration.php b/app/code/Vindi/Payment/registration.php new file mode 100644 index 00000000..8d120c87 --- /dev/null +++ b/app/code/Vindi/Payment/registration.php @@ -0,0 +1,6 @@ + + + + + + + + + + + + + + + + + + + + Vindi_Payment/js/view/payment/vindi + + + + true + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Vindi/Payment/view/frontend/web/js/view/payment/method-renderer/vindi-method.js b/app/code/Vindi/Payment/view/frontend/web/js/view/payment/method-renderer/vindi-method.js new file mode 100644 index 00000000..51ab10f0 --- /dev/null +++ b/app/code/Vindi/Payment/view/frontend/web/js/view/payment/method-renderer/vindi-method.js @@ -0,0 +1,16 @@ +define( + [ + 'Magento_Checkout/js/view/payment/default' + ], + function (Component) { + 'use strict'; + return Component.extend({ + defaults: { + template: 'Vindi_Payment/payment/vindi' + }, + getMailingAddress: function () { + return window.checkoutConfig.payment.checkmo.mailingAddress; + }, + }); + } +); diff --git a/app/code/Vindi/Payment/view/frontend/web/js/view/payment/vindi.js b/app/code/Vindi/Payment/view/frontend/web/js/view/payment/vindi.js new file mode 100644 index 00000000..26293a5e --- /dev/null +++ b/app/code/Vindi/Payment/view/frontend/web/js/view/payment/vindi.js @@ -0,0 +1,19 @@ +define( + [ + 'uiComponent', + 'Magento_Checkout/js/model/payment/renderer-list' + ], + function ( + Component, + rendererList + ) { + 'use strict'; + rendererList.push( + { + type: 'vindi', + component: 'Vindi_Payment/js/view/payment/method-renderer/vindi-method' + } + ); + return Component.extend({}); + } +); \ No newline at end of file diff --git a/app/code/Vindi/Payment/view/frontend/web/template/payment/cc-form.html b/app/code/Vindi/Payment/view/frontend/web/template/payment/cc-form.html new file mode 100644 index 00000000..fdf6e030 --- /dev/null +++ b/app/code/Vindi/Payment/view/frontend/web/template/payment/cc-form.html @@ -0,0 +1,107 @@ +
+ + +
+
+
+
    + +
  • +
  • + +
+ +
+
+
+ +
+ +
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+ +
+ +
+ +
+ + + +
+
+
+ +
\ No newline at end of file diff --git a/app/code/Vindi/Payment/view/frontend/web/template/payment/vindi.html b/app/code/Vindi/Payment/view/frontend/web/template/payment/vindi.html new file mode 100644 index 00000000..4a4545be --- /dev/null +++ b/app/code/Vindi/Payment/view/frontend/web/template/payment/vindi.html @@ -0,0 +1,50 @@ + +
+
+ + +
+
+ + + +
+ + + +
+ +
+ +
+ +
+ + + +
+
+
+ +
+
+
+
From 63e2baef19789194f2c3f6f3c097a4994f150dcd Mon Sep 17 00:00:00 2001 From: leonardo albuquerque Date: Tue, 24 Jul 2018 16:13:57 -0300 Subject: [PATCH 02/46] #11177 adicionado estrutura base --- README.md | 1 - .../Vindi/Payment/Controller/Index/Index.php | 25 +++++++++ app/code/Vindi/Payment/Model/Payment/.gitkeep | 0 .../Vindi/Payment/etc/adminhtml/system.xml | 56 +++++++++++++++++++ app/code/Vindi/Payment/etc/config.xml | 16 ++++++ .../Vindi/Payment/etc/frontend/routes.xml | 8 +++ app/code/Vindi/Payment/etc/module.xml | 5 ++ app/code/Vindi/Payment/etc/payment.xml | 14 +++++ app/code/Vindi/Payment/registration.php | 6 ++ .../frontend/layout/checkout_index_index.xml | 46 +++++++++++++++ .../payment/method-renderer/vindi-method.js | 16 ++++++ .../frontend/web/js/view/payment/vindi.js | 19 +++++++ .../frontend/web/template/payment/vindi.html | 50 +++++++++++++++++ 13 files changed, 261 insertions(+), 1 deletion(-) delete mode 100644 README.md create mode 100644 app/code/Vindi/Payment/Controller/Index/Index.php create mode 100644 app/code/Vindi/Payment/Model/Payment/.gitkeep create mode 100644 app/code/Vindi/Payment/etc/adminhtml/system.xml create mode 100644 app/code/Vindi/Payment/etc/config.xml create mode 100644 app/code/Vindi/Payment/etc/frontend/routes.xml create mode 100644 app/code/Vindi/Payment/etc/module.xml create mode 100644 app/code/Vindi/Payment/etc/payment.xml create mode 100644 app/code/Vindi/Payment/registration.php create mode 100644 app/code/Vindi/Payment/view/frontend/layout/checkout_index_index.xml create mode 100644 app/code/Vindi/Payment/view/frontend/web/js/view/payment/method-renderer/vindi-method.js create mode 100644 app/code/Vindi/Payment/view/frontend/web/js/view/payment/vindi.js create mode 100644 app/code/Vindi/Payment/view/frontend/web/template/payment/vindi.html diff --git a/README.md b/README.md deleted file mode 100644 index 83f0885e..00000000 --- a/README.md +++ /dev/null @@ -1 +0,0 @@ -# vindi-magento2 diff --git a/app/code/Vindi/Payment/Controller/Index/Index.php b/app/code/Vindi/Payment/Controller/Index/Index.php new file mode 100644 index 00000000..f59a2c10 --- /dev/null +++ b/app/code/Vindi/Payment/Controller/Index/Index.php @@ -0,0 +1,25 @@ +_pageFactory = $pageFactory; + $this->api = $api; + return parent::__construct($context); + } + + public function execute() + { + return $this->_pageFactory->create(); + } +} \ No newline at end of file diff --git a/app/code/Vindi/Payment/Model/Payment/.gitkeep b/app/code/Vindi/Payment/Model/Payment/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/app/code/Vindi/Payment/etc/adminhtml/system.xml b/app/code/Vindi/Payment/etc/adminhtml/system.xml new file mode 100644 index 00000000..82844330 --- /dev/null +++ b/app/code/Vindi/Payment/etc/adminhtml/system.xml @@ -0,0 +1,56 @@ + + + +
+ + + + + Magento\Config\Model\Config\Source\Yesno + + + + + + + + Magento\Config\Model\Config\Source\Yesno + + + + + + + + Magento\Sales\Model\Config\Source\Order\Status\NewStatus + + + + Magento\Payment\Model\Config\Source\Allspecificcountries + + + + Magento\Directory\Model\Config\Source\Country + 1 + + + + + + + + +
+
+
diff --git a/app/code/Vindi/Payment/etc/config.xml b/app/code/Vindi/Payment/etc/config.xml new file mode 100644 index 00000000..8df8ef3f --- /dev/null +++ b/app/code/Vindi/Payment/etc/config.xml @@ -0,0 +1,16 @@ + + + + + + 1 + Vindi\Payment\Model\Payment\Vindi + pending + Vindi + 0 + offline + + + + diff --git a/app/code/Vindi/Payment/etc/frontend/routes.xml b/app/code/Vindi/Payment/etc/frontend/routes.xml new file mode 100644 index 00000000..3effe552 --- /dev/null +++ b/app/code/Vindi/Payment/etc/frontend/routes.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/app/code/Vindi/Payment/etc/module.xml b/app/code/Vindi/Payment/etc/module.xml new file mode 100644 index 00000000..ce0cf03b --- /dev/null +++ b/app/code/Vindi/Payment/etc/module.xml @@ -0,0 +1,5 @@ + + + + diff --git a/app/code/Vindi/Payment/etc/payment.xml b/app/code/Vindi/Payment/etc/payment.xml new file mode 100644 index 00000000..84ca3481 --- /dev/null +++ b/app/code/Vindi/Payment/etc/payment.xml @@ -0,0 +1,14 @@ + + + + + + + + + + 1 + + + diff --git a/app/code/Vindi/Payment/registration.php b/app/code/Vindi/Payment/registration.php new file mode 100644 index 00000000..8d120c87 --- /dev/null +++ b/app/code/Vindi/Payment/registration.php @@ -0,0 +1,6 @@ + + + + + + + + + + + + + + + + + + + + Vindi_Payment/js/view/payment/vindi + + + + true + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Vindi/Payment/view/frontend/web/js/view/payment/method-renderer/vindi-method.js b/app/code/Vindi/Payment/view/frontend/web/js/view/payment/method-renderer/vindi-method.js new file mode 100644 index 00000000..51ab10f0 --- /dev/null +++ b/app/code/Vindi/Payment/view/frontend/web/js/view/payment/method-renderer/vindi-method.js @@ -0,0 +1,16 @@ +define( + [ + 'Magento_Checkout/js/view/payment/default' + ], + function (Component) { + 'use strict'; + return Component.extend({ + defaults: { + template: 'Vindi_Payment/payment/vindi' + }, + getMailingAddress: function () { + return window.checkoutConfig.payment.checkmo.mailingAddress; + }, + }); + } +); diff --git a/app/code/Vindi/Payment/view/frontend/web/js/view/payment/vindi.js b/app/code/Vindi/Payment/view/frontend/web/js/view/payment/vindi.js new file mode 100644 index 00000000..26293a5e --- /dev/null +++ b/app/code/Vindi/Payment/view/frontend/web/js/view/payment/vindi.js @@ -0,0 +1,19 @@ +define( + [ + 'uiComponent', + 'Magento_Checkout/js/model/payment/renderer-list' + ], + function ( + Component, + rendererList + ) { + 'use strict'; + rendererList.push( + { + type: 'vindi', + component: 'Vindi_Payment/js/view/payment/method-renderer/vindi-method' + } + ); + return Component.extend({}); + } +); \ No newline at end of file diff --git a/app/code/Vindi/Payment/view/frontend/web/template/payment/vindi.html b/app/code/Vindi/Payment/view/frontend/web/template/payment/vindi.html new file mode 100644 index 00000000..4a4545be --- /dev/null +++ b/app/code/Vindi/Payment/view/frontend/web/template/payment/vindi.html @@ -0,0 +1,50 @@ + +
+
+ + +
+
+ + + +
+ + + +
+ +
+ +
+ +
+ + + +
+
+
+ +
+
+
+
From b157a82a64cfa34a730ff3de402e5e28e6f4ff96 Mon Sep 17 00:00:00 2001 From: leonardo albuquerque Date: Tue, 24 Jul 2018 16:34:13 -0300 Subject: [PATCH 03/46] #11177 adicionada estrutura base --- .../Vindi/Payment/Model/Payment/Vindi.php | 307 +----------------- app/code/Vindi/Payment/composer.json | 22 ++ .../Vindi/Payment/etc/adminhtml/system.xml | 88 ++--- app/code/Vindi/Payment/etc/config.xml | 27 +- app/code/Vindi/Payment/etc/module.xml | 5 +- app/code/Vindi/Payment/etc/payment.xml | 23 +- .../frontend/layout/checkout_index_index.xml | 83 +++-- .../frontend/web/template/payment/vindi.html | 8 +- 8 files changed, 124 insertions(+), 439 deletions(-) create mode 100644 app/code/Vindi/Payment/composer.json diff --git a/app/code/Vindi/Payment/Model/Payment/Vindi.php b/app/code/Vindi/Payment/Model/Payment/Vindi.php index b75a61a2..cc3c19d1 100644 --- a/app/code/Vindi/Payment/Model/Payment/Vindi.php +++ b/app/code/Vindi/Payment/Model/Payment/Vindi.php @@ -3,10 +3,6 @@ namespace Vindi\Payment\Model\Payment; -use Magento\Framework\DataObject; -use Magento\Quote\Api\Data\CartInterface; -use Vindi\Payment\Model\Api; - class Vindi extends \Magento\Payment\Model\Method\AbstractMethod { @@ -15,308 +11,7 @@ class Vindi extends \Magento\Payment\Model\Method\AbstractMethod public function isAvailable( \Magento\Quote\Api\Data\CartInterface $quote = null - ) - { + ) { return parent::isAvailable($quote); } - - /** - * @var bool - */ - protected $_isGateway = true; - - /** - * @var bool - */ - protected $_canAuthorize = true; - - /** - * @var bool - */ - protected $_canCapture = true; - - /** - * @var bool - */ - protected $_canCapturePartial = false; - - /** - * @var bool - */ - protected $_canRefund = false; - - /** - * @var bool - */ - protected $_canVoid = false; - - /** - * @var bool - */ - protected $_canUseInternal = true; - - /** - * @var bool - */ - protected $_canUseCheckout = true; - - /** - * @var bool - */ - protected $_canUseForMultishipping = false; - - /** - * @var bool - */ - protected $_isInitializeNeeded = true; - - /** - * @var bool - */ - protected $_canSaveCc = false; - - /** - * @var string - */ - protected $_formBlockType = 'vindi_subscription/form_cc'; - - /** - * @var string - */ - protected $_infoBlockType = 'vindi_subscription/info_cc'; - - /** - * Assign data to info model instance - * - * @param mixed $data - * - * @return Mage_Payment_Model_Method_Abstract - */ - public function assignData(DataObject $data) - { - if (!($data instanceof Varien_Object)) { - $data = new Varien_Object($data); - } - $info = $this->getInfoInstance(); - $quote = $info->getQuote(); - - $info->setAdditionalInformation('installments', $data->getCcInstallments()); - - if ($data->getCcChoice() === 'saved') { - $info->setAdditionalInformation('PaymentMethod', $this->_code) - ->setAdditionalInformation('use_saved_cc', true); - - return $this; - } - - $info->setCcType($data->getCcType()) - ->setCcOwner($data->getCcOwner()) - ->setCcLast4(substr($data->getCcNumber(), -4)) - ->setCcNumber($data->getCcNumber()) - ->setCcCid($data->getCcCid()) - ->setCcExpMonth($data->getCcExpMonth()) - ->setCcExpYear($data->getCcExpYear()) - ->setCcSsIssue($data->getCcSsIssue()) - ->setCcSsStartMonth($data->getCcSsStartMonth()) - ->setCcSsStartYear($data->getCcSsStartYear()) - ->setAdditionalInformation('PaymentMethod', $this->_code) - ->setAdditionalInformation('use_saved_cc', false); - - return $this; - } - - /** - * @param string $paymentAction - * @param object $stateObject - * - * @return bool|Mage_Payment_Model_Method_Abstract - */ - protected function processNewOrder($paymentAction, $stateObject) - { - $payment = $this->getInfoInstance(); - $order = $payment->getOrder(); - - $customer = Mage::getModel('customer/customer'); - - $customerId = $this->createCustomer($order, $customer); - $customerVindiId = $customer->getVindiUserCode(); - - if (!$payment->getAdditionalInformation('use_saved_cc')) { - $this->createPaymentProfile($customerId); - } else { - $this->assignDataFromPreviousPaymentProfile($customerVindiId); - } - - if ($this->isSingleOrder($order)) { - $result = $this->processSinglePayment($payment, $order, $customerId); - } else { - $result = $this->processSubscription($payment, $order, $customerId); - } - - if (!$result) { - return false; - } - - $billData = $this->api()->getBill($result); - $installments = $billData['installments']; - $response_fields = $billData['charges'][0]['last_transaction']['gateway_response_fields']; - $possible = ['nsu', 'proof_of_sale']; - $nsu = ''; - foreach ($possible as $nsu_field) { - if ($response_fields[$nsu_field]) { - $nsu = $response_fields[$nsu_field]; - } - } - - $this->getInfoInstance()->setAdditionalInformation( - [ - 'installments' => $installments, - 'nsu' => $nsu - ] - ); - - $stateObject->setStatus(Mage_Sales_Model_Order::STATE_PENDING_PAYMENT) - ->setState(Mage_Sales_Model_Order::STATE_PENDING_PAYMENT); - - return $this; - } - - /** - * @param int $customerId - * - * @return array|bool - */ - protected function createPaymentProfile($customerId) - { - $payment = $this->getInfoInstance(); - - $creditCardData = [ - 'holder_name' => $payment->getCcOwner(), - 'card_expiration' => str_pad($payment->getCcExpMonth(), 2, '0', STR_PAD_LEFT) - . '/' . $payment->getCcExpYear(), - 'card_number' => $payment->getCcNumber(), - 'card_cvv' => $payment->getCcCid() ?: '000', - 'customer_id' => $customerId, - 'payment_company_code' => $payment->getCcType(), - 'payment_method_code' => $this->getPaymentMethodCode() - ]; - - $paymentProfile = $this->api()->createCustomerPaymentProfile($creditCardData); - - if ($paymentProfile === false) { - Mage::throwException('Erro ao informar os dados de cartão de crédito. Verifique os dados e tente novamente!'); - - return false; - } - - $verifyMethod = Mage::getStoreConfig('vindi_subscription/general/verify_method'); - - if ($verifyMethod && !$this->verifyPaymentProfile($paymentProfile['payment_profile']['id'])) { - Mage::throwException('Não foi possível realizar a verificação do seu cartão de crédito!'); - return false; - } - return $paymentProfile; - } - - /** - * @param int $paymentProfileId - * - * @return array|bool - */ - public function verifyPaymentProfile($paymentProfileId) - { - $verify_status = $this->api()->verifyCustomerPaymentProfile($paymentProfileId); - return ($verify_status['transaction']['status'] === 'success'); - } - - /** - * @param int $customerVindiId - */ - protected function assignDataFromPreviousPaymentProfile($customerVindiId) - { - $api = Mage::helper('vindi_subscription/api'); - $savedCc = $api->getCustomerPaymentProfile($customerVindiId); - $info = $this->getInfoInstance(); - - $info->setCcType($savedCc['payment_company']['code']) - ->setCcOwner($savedCc['holder_name']) - ->setCcLast4($savedCc['card_number_last_four']) - ->setCcNumber($savedCc['card_number_last_four']) - ->setAdditionalInformation('use_saved_cc', true); - } - - /** - * Validate payment method information object - * - * @return Mage_Payment_Model_Method_Abstract - */ - public function validate() - { - $info = $this->getInfoInstance(); - - $quote = $info->getQuote(); - - $maxInstallmentsNumber = Mage::getStoreConfig('payment/vindi_creditcard/max_installments_number'); - - if ($this->isSingleOrder($quote) && ($maxInstallmentsNumber > 1)) { - if (!$installments = $info->getAdditionalInformation('installments')) { - return $this->error('Você deve informar o número de parcelas.'); - } - - if ($installments > $maxInstallmentsNumber) { - return $this->error('O número de parcelas selecionado é inválido.'); - } - - $minInstallmentsValue = Mage::getStoreConfig('payment/vindi_creditcard/min_installment_value'); - $installmentValue = ceil($quote->getGrandTotal() / $installments * 100) / 100; - - if (($installmentValue < $minInstallmentsValue) && ($installments > 1)) { - return $this->error('O número de parcelas selecionado é inválido.'); - } - } - - if ($info->getAdditionalInformation('use_saved_cc')) { - return $this; - } - - $availableTypes = $this->api()->getCreditCardTypes(); - - $ccNumber = $info->getCcNumber(); - - // remove credit card non-numbers - $ccNumber = preg_replace('/\D/', '', $ccNumber); - - $info->setCcNumber($ccNumber); - - if (!$this->_validateExpDate($info->getCcExpYear(), $info->getCcExpMonth())) { - return $this->error(Mage::helper('payment')->__('Incorrect credit card expiration date.')); - } - - if (!array_key_exists($info->getCcType(), $availableTypes)) { - return $this->error(Mage::helper('payment')->__('Credit card type is not allowed for this payment method.')); - } - - return $this; - } - - /** - * @param string $errorMsg - * - * @return bool - * @throws \Mage_Core_Exception - */ - private function error($errorMsg) - { - Mage::throwException($errorMsg); - - return false; - } - - /** - * @return string - */ - protected function getPaymentMethodCode() - { - return 'credit_card'; - } } diff --git a/app/code/Vindi/Payment/composer.json b/app/code/Vindi/Payment/composer.json new file mode 100644 index 00000000..434f78fa --- /dev/null +++ b/app/code/Vindi/Payment/composer.json @@ -0,0 +1,22 @@ +{ + "name": "vindi/module-payment", + "description": "", + "type": "magento2-module", + "license": "proprietary", + "authors": [ + { + "email": "info@mage2gen.com", + "name": "Mage2Gen" + } + ], + "minimum-stability": "dev", + "require": {}, + "autoload": { + "files": [ + "registration.php" + ], + "psr-4": { + "Vindi\\Payment\\": "" + } + } +} \ No newline at end of file diff --git a/app/code/Vindi/Payment/etc/adminhtml/system.xml b/app/code/Vindi/Payment/etc/adminhtml/system.xml index 82844330..18e6dc33 100644 --- a/app/code/Vindi/Payment/etc/adminhtml/system.xml +++ b/app/code/Vindi/Payment/etc/adminhtml/system.xml @@ -1,56 +1,36 @@ - - -
- - - - - Magento\Config\Model\Config\Source\Yesno - - - - - - - - Magento\Config\Model\Config\Source\Yesno - - - - - - - - Magento\Sales\Model\Config\Source\Order\Status\NewStatus - - - - Magento\Payment\Model\Config\Source\Allspecificcountries - - - - Magento\Directory\Model\Config\Source\Country - 1 - - - - - - - - -
-
+ + +
+ + + + + Magento\Config\Model\Config\Source\Yesno + + + + + + + Magento\Sales\Model\Config\Source\Order\Status\NewStatus + + + + Magento\Payment\Model\Config\Source\Allspecificcountries + + + + Magento\Directory\Model\Config\Source\Country + 1 + + + + + + + + +
+
diff --git a/app/code/Vindi/Payment/etc/config.xml b/app/code/Vindi/Payment/etc/config.xml index 8df8ef3f..17583699 100644 --- a/app/code/Vindi/Payment/etc/config.xml +++ b/app/code/Vindi/Payment/etc/config.xml @@ -1,16 +1,15 @@ - - - - - 1 - Vindi\Payment\Model\Payment\Vindi - pending - Vindi - 0 - offline - - - + + + + + 1 + Vindi\Payment\Model\Payment\Vindi + pending + Vindi + 0 + offline + + + diff --git a/app/code/Vindi/Payment/etc/module.xml b/app/code/Vindi/Payment/etc/module.xml index ce0cf03b..d9645236 100644 --- a/app/code/Vindi/Payment/etc/module.xml +++ b/app/code/Vindi/Payment/etc/module.xml @@ -1,5 +1,4 @@ - - + + diff --git a/app/code/Vindi/Payment/etc/payment.xml b/app/code/Vindi/Payment/etc/payment.xml index 84ca3481..cbe2c415 100644 --- a/app/code/Vindi/Payment/etc/payment.xml +++ b/app/code/Vindi/Payment/etc/payment.xml @@ -1,14 +1,13 @@ - - - - - - - - - 1 - - + + + + + + + + + 1 + + diff --git a/app/code/Vindi/Payment/view/frontend/layout/checkout_index_index.xml b/app/code/Vindi/Payment/view/frontend/layout/checkout_index_index.xml index 11ff49eb..01dbadc4 100644 --- a/app/code/Vindi/Payment/view/frontend/layout/checkout_index_index.xml +++ b/app/code/Vindi/Payment/view/frontend/layout/checkout_index_index.xml @@ -1,46 +1,41 @@ - - - - - - - - - - - - - - - - - - - Vindi_Payment/js/view/payment/vindi - - - - true - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + Vindi_Payment/js/view/payment/vindi + + + true + + + + + + + + + + + + + + + + + + diff --git a/app/code/Vindi/Payment/view/frontend/web/template/payment/vindi.html b/app/code/Vindi/Payment/view/frontend/web/template/payment/vindi.html index 4a4545be..cebbb9ac 100644 --- a/app/code/Vindi/Payment/view/frontend/web/template/payment/vindi.html +++ b/app/code/Vindi/Payment/view/frontend/web/template/payment/vindi.html @@ -21,14 +21,9 @@ - -
- -
-
- +
@@ -48,3 +43,4 @@
+ \ No newline at end of file From 4c6f977d21461e2267485b32c732d87a32d7128e Mon Sep 17 00:00:00 2001 From: leonardo albuquerque Date: Tue, 24 Jul 2018 16:42:16 -0300 Subject: [PATCH 04/46] =?UTF-8?q?#11177=20removido=20arquivos=20n=C3=A3o?= =?UTF-8?q?=20necess=C3=A1rios=20para=20esta=20release?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/code/Vindi/Payment/Model/Api.php | 706 ------------------ .../Payment/Model/Payment/CreditCard.php | 325 -------- .../web/template/payment/cc-form.html | 107 --- 3 files changed, 1138 deletions(-) delete mode 100644 app/code/Vindi/Payment/Model/Api.php delete mode 100644 app/code/Vindi/Payment/Model/Payment/CreditCard.php delete mode 100644 app/code/Vindi/Payment/view/frontend/web/template/payment/cc-form.html diff --git a/app/code/Vindi/Payment/Model/Api.php b/app/code/Vindi/Payment/Model/Api.php deleted file mode 100644 index 7b36957b..00000000 --- a/app/code/Vindi/Payment/Model/Api.php +++ /dev/null @@ -1,706 +0,0 @@ -scopeConfig = $scopeConfig; - $this->logger = $logger; - $this->cacheType = $cacheType; - $this->message = $message; - - $storeScope = \Magento\Store\Model\ScopeInterface::SCOPE_STORE; - $isSandBox = $this->scopeConfig->getValue('payment/vindi/sandboxmode', $storeScope); - - if ($isSandBox) { - $this->base_path = 'https://sandbox-app.vindi.com.br/api/v1/'; - } else { - $this->base_path = 'https://app.vindi.com.br/api/v1/'; - } - - $moduleInfo = $moduleList->getOne('Vindi_Payment'); - $this->version = $moduleInfo['setup_version']; - $this->key = $this->scopeConfig->getValue('payment/vindi/key', $storeScope); - } - - - public function execute(Observer $observer) - { - $storeScope = \Magento\Store\Model\ScopeInterface::SCOPE_STORE; - $notifyEmail = $this->scopeConfig->getValue(self::BASEPATH, $storeScope); - - echo $notifyEmail; - } - - /** - * @param string $message - * @param int|null $level - */ - private function log($message) - { - $this->logger->warning($message); - } - - /** - * @return \Zend_Cache_Core - */ - private function cache() - { - return $this->cacheType; - } - - /** - * Build HTTP Query. - * - * @param array $data - * - * @return string - */ - private function buildBody($data) - { - $body = null; - if (!empty($data)) { - $body = json_encode($data); - } - return $body; - } - - /** - * @param array $error - * @param $endpoint - * - * @return string - */ - private function getErrorMessage($error, $endpoint) - { - return "Erro em $endpoint: {$error['id']}: {$error['parameter']} - {$error['message']}"; - } - - /** - * @param array $response - * @param $endpoint - * - * @return bool - */ - private function checkResponse($response, $endpoint) - { - if (isset($response['errors']) && !empty($response['errors'])) { - foreach ($response['errors'] as $error) { - $message = $this->getErrorMessage($error, $endpoint); - $this->message->addErrorMessage($message); - $this->lastError = $message; - } - return false; - } - $this->lastError = ''; - return true; - } - - /** - * Perform request to API. - * - * @param string $endpoint - * @param string $method - * @param array $data - * @param null $dataToLog - * - * @return array|bool|mixed - */ - private function request($endpoint, $method = 'POST', $data = [], $dataToLog = null) - { - if (!$this->key) { - return false; - } - $url = $this->base_path . $endpoint; - $body = $this->buildBody($data); - $requestId = rand(); - $dataToLog = null !== $dataToLog ? $this->buildBody($dataToLog) : $body; - $this->log(sprintf("[Request #%s]: Novo Request para a API.\n%s %s\n%s", $requestId, $method, $url, - $dataToLog)); - $ch = curl_init(); - $ch_options = [ - CURLOPT_HTTPHEADER => [ - 'Content-Type: application/json', - ], - CURLOPT_TIMEOUT => 60, - CURLOPT_SSL_VERIFYPEER => true, - CURLOPT_HEADER => true, - CURLOPT_RETURNTRANSFER => true, - CURLOPT_USERAGENT => 'Vindi-Magento/' . $this->version, - CURLOPT_SSLVERSION => 'CURL_SSLVERSION_TLSv1_2', - CURLOPT_USERPWD => $this->key . ':', - CURLOPT_URL => $url, - CURLOPT_CUSTOMREQUEST => $method - ]; - if (!empty($body)) { - $ch_options[CURLOPT_POSTFIELDS] = $body; - } - curl_setopt_array($ch, $ch_options); - $response = curl_exec($ch); - $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); - $body = substr($response, curl_getinfo($ch, CURLINFO_HEADER_SIZE)); - if (curl_errno($ch) || $response === false) { - $this->log(sprintf("[Request #%s]: Erro ao fazer request!\n%s", $requestId, print_r($response, true))); - return false; - } - curl_close($ch); - $status = "HTTP Status: $statusCode"; - $this->log(sprintf("[Request #%s]: Nova Resposta da API.\n%s\n%s", $requestId, $status, $body)); - $responseBody = json_decode($body, true); - if (!$responseBody) { - $this->log(sprintf('[Request #%s]: Erro ao recuperar corpo do request! %s', $requestId, - print_r($body, true))); - return false; - } - if (!$this->checkResponse($responseBody, $endpoint)) { - return false; - } - return $responseBody; - } - - /** - * Make an API request to create a Customer. - * - * @param array $body (name, email, code) - * - * @return array|bool|mixed - */ - public function createCustomer($body) - { - if ($response = $this->request('customers', 'POST', $body)) { - return $response['customer']['id']; - } - return false; - } - - /** - * Make an API request to retrieve an existing Customer. - * - * @param string $code - * - * @return array|bool|mixed - */ - public function findCustomerByCode($code) - { - $customerId = $this->cache()->load("vindi_customer_by_code_{$code}"); - if ($customerId === false) { - $response = $this->request("customers/search?code={$code}", 'GET'); - if ($response && (1 === count($response['customers'])) && isset($response['customers'][0]['id'])) { - $customerId = $response['customers'][0]['id']; - $this->cache()->save(serialize($customerId), "vindi_customer_by_code_{$code}", ['vindi_cache'], - 5 * 60); // 5 minutes - } - } else { - $customerId = unserialize($customerId); - } - return $customerId; - } - - /** - * Make an API request to retrieve an existing Customer or to create one if not found. - * - * @param array $body (name, email, code) - * - * @return array|bool|mixed - */ - public function findOrCreateCustomer($body) - { - $customerId = $this->findCustomerByCode($body['code']); - // TODO update information - if (false === $customerId) { - return $this->createCustomer($body); - } - return $customerId; - } - - /** - * Make an API request to create a Payment Profile to a Customer. - * - * @param $body (holder_name, card_expiration, card_number, card_cvv, customer_id) - * - * @return array|bool|mixed - */ - public function createCustomerPaymentProfile($body) - { - // Protect credit card number. - $dataToLog = $body; - $dataToLog['card_number'] = '**** *' . substr($dataToLog['card_number'], -3); - $dataToLog['card_cvv'] = '***'; - $customerId = $body['customer_id']; - $this->cache()->remove("vindi_payment_profile_{$customerId}"); - return $this->request('payment_profiles', 'POST', $body, $dataToLog); - } - - /** - * Make an API request to verify a Payment Profile to a Customer. - * - * @param $id integer - * - * @return array|bool|mixed - */ - public function verifyCustomerPaymentProfile($id) - { - return $this->request('payment_profiles/' . $id . '/verify', 'POST'); - } - - /** - * @param $userCode - * - * @return bool - */ - public function getCustomerPaymentProfile($userCode, $type = "CreditCard") - { - $customerId = $this->findCustomerByCode($userCode); - if (false === $customerId) { - return false; - } - $paymentProfile = $this->cache()->load("vindi_payment_profile_{$customerId}"); - if ($paymentProfile === false || strpos($paymentProfile, $type) === false) { - $endpoint = 'payment_profiles?query=customer_id%3D' . $customerId - . '%20status%3Dactive%20type%3DPaymentProfile%3A%3A' . $type; - $response = $this->request($endpoint, 'GET'); - if ($response && $response['payment_profiles'] && count($response['payment_profiles'])) { - $paymentProfile = $response['payment_profiles'][0]; - $this->cache()->save(serialize($paymentProfile), "vindi_payment_profile_{$customerId}", ['vindi_cache'], - 5 * 60); // 5 minutes - } else { - $paymentProfile = false; - } - } else { - $paymentProfile = unserialize($paymentProfile); - } - return $paymentProfile; - } - - /** - * Make an API request to create a Subscription. - * - * @param $body (plan_id, customer_id, payment_method_code, product_items[{product_id}]) - * - * @return array - */ - public function createSubscription($body) - { - if (($response = $this->request('subscriptions', 'POST', $body)) && isset($response['subscription']['id'])) { - $subscription = $response['subscription']; - $subscription['bill'] = $response['bill']; - return $subscription; - } - return false; - } - - /** - * Make an API request to retrieve Payment Methods. - * - * @return array|bool - */ - public function getPaymentMethods() - { - $paymentMethods = $this->cache()->load('vindi_payment_methods'); - if ($paymentMethods === false) { - $paymentMethods = [ - 'credit_card' => [], - 'debit_card' => [], - 'bank_slip' => false, - ]; - $response = $this->request('payment_methods', 'GET'); - if (false === $response) { - return $this->acceptBankSlip = false; - } - foreach ($response['payment_methods'] as $method) { - if ('active' !== $method['status']) { - continue; - } - if ('PaymentMethod::CreditCard' === $method['type']) { - $paymentMethods['credit_card'] = array_merge( - $paymentMethods['credit_card'], - $method['payment_companies'] - ); - } elseif ('PaymentMethod::DebitCard' === $method['type']) { - $paymentMethods['debit_card'] = array_merge( - $paymentMethods['debit_card'], - $method['payment_companies'] - ); - } elseif ('PaymentMethod::BankSlip' === $method['type']) { - $paymentMethods['bank_slip'] = true; - } - } - $this->cache()->save(serialize($paymentMethods), 'vindi_payment_methods', ['vindi_cache'], - 12 * 60 * 60); // 12 hours - } else { - $paymentMethods = unserialize($paymentMethods); - } - $this->acceptBankSlip = $paymentMethods['bank_slip']; - return $paymentMethods; - } - - /** - * Retrieve Credit Card Types from Payment Methods. - * - * @return array - */ - public function getCreditCardTypes() - { - $methods = $this->getPaymentMethods(); - $types = []; - foreach ($methods['credit_card'] as $type) { - $types[$type['code']] = $type['name']; - } - return $types; - } - - /** - * Retrieve Debit Card Types from Payment Methods. - * - * @return array - */ - public function getDebitCardTypes() - { - $methods = $this->getPaymentMethods(); - $types = []; - foreach ($methods['debit_card'] as $type) { - $types[$type['code']] = $type['name']; - } - return $types; - } - - /** - * @return bool|null - */ - public function acceptBankSlip() - { - if (null === $this->acceptBankSlip) { - $this->getPaymentMethods(); - } - return $this->acceptBankSlip; - } - - /** - * @param array $body - * - * @return int|bool - */ - public function createBill($body) - { - if ($response = $this->request('bills', 'POST', $body)) { - return $response['bill']; - } - return false; - } - - /** - * @param $billId - * - * @return array|bool|mixed - */ - public function approveBill($billId) - { - $response = $this->request("bills/{$billId}", 'GET'); - if (false === $response || !isset($response['bill'])) { - return false; - } - $bill = $response['bill']; - if ('review' !== $bill['status']) { - return true; - } - return $this->request("bills/{$billId}/approve", 'POST'); - } - - /** - * @param $billId - */ - public function deleteBill($billId) - { - $this->request("bills/{$billId}", 'DELETE'); - } - - /** - * @param $billId - * - * @return string - */ - public function getBankSlipDownload($billId) - { - $response = $this->request("bills/{$billId}", 'GET'); - if (false === $response) { - return false; - } - return $response['bill']['charges'][0]['print_url']; - } - - /** - * @return array - */ - public function getProducts() - { - $list = []; - $response = $this->request('products?query=status:active', 'GET'); - if ($products = $response['products']) { - foreach ($products as $product) { - $list[$product['id']] = "{$product['name']} ({$product['pricing_schema']['short_format']})"; - } - } - return $list; - } - - /** - * @param int $id - * - * @return array - */ - public function getPlanItems($id) - { - $list = []; - $response = $this->request("plans/{$id}", 'GET'); - if ($plan = $response['plan']) { - foreach ($plan['plan_items'] as $item) { - if (isset($item['product'])) { - $list[] = $item['product']['id']; - } - } - } - return $list; - } - - /** - * @param Mage_Sales_Model_Order $order - * - * @return array - */ - public function buildPlanItemsForSubscription($order) - { - $list = []; - $orderItems = $order->getItemsCollection(); - $orderSubtotal = $order->getQuote()->getSubtotal(); - $orderDiscount = $order->getDiscountAmount() * -1; - $discount = null; - if (!empty($orderDiscount)) { - $discountPercentage = $orderDiscount * 100 / $orderSubtotal; - $discountPercentage = number_format(floor($discountPercentage * 100) / 100, 2); - $discount = [[ - 'discount_type' => 'percentage', - 'percentage' => $discountPercentage - ]]; - } - foreach ($orderItems as $item) { - $product = Mage::getModel('catalog/product')->load($item->getProductId()); - if ($product->getTypeID() !== 'subscription') { - throw new \Exception("O produto {$item->getName()} não é uma assinatura."); - return false; - } - $productVindiId = $this->findOrCreateProduct(array('sku' => $item->getSku(), 'name' => $item->getName())); - for ($i = 1; $i <= $item->getQtyOrdered(); $i++) { - $list[] = [ - 'product_id' => $productVindiId, - 'pricing_schema' => ['price' => $item->getPrice()], - 'discounts' => $discount, - ]; - } - } - // Create product for shipping - $productVindiId = $this->findOrCreateProduct(array('sku' => 'frete', 'name' => 'Frete')); - $list[] = [ - 'product_id' => $productVindiId, - 'pricing_schema' => ['price' => $order->getShippingAmount()], - ]; - return $list; - } - - /** - * @return array - */ - public function getPlans() - { - $list = $this->cache()->load('vindi_plans'); - if (($list === false) || !count($list = unserialize($list))) { - $list = []; - $response = $this->request('plans?query=status:active', 'GET'); - if ($plans = $response['plans']) { - foreach ($plans as $plan) { - $list[$plan['id']] = $plan['name']; - } - } - $this->cache()->save(serialize($list), 'vindi_plans', ['vindi_cache'], 10 * 60); // 10 minutes - } - return $list; - } - - public function getPlanInstallments($id) - { - $response = $this->request("plans/{$id}", 'GET'); - $plan = $response['plan']; - $installments = $plan['installments']; - return $installments; - } - - /** - * Make an API request to create a Product. - * - * @param array $body (name, code, status, pricing_schema (price)) - * - * @return array|bool|mixed - */ - public function createProduct($body) - { - if ($response = $this->request('products', 'POST', $body)) { - return $response['product']['id']; - } - return false; - } - - /** - * Make an API request to retrieve an existing Product. - * - * @param string $code - * - * @return array|bool|mixed - */ - public function findProductByCode($code) - { - $response = $this->request("products?query=code%3D{$code}", 'GET'); - if ($response && (1 === count($response['products'])) && isset($response['products'][0]['id'])) { - return $response['products'][0]['id']; - } - return false; - } - - /** - * Make an API request to retrieve the Unique Payment Product or to create it if not found. - * - * @return array|bool|mixed - */ - public function findOrCreateUniquePaymentProduct() - { - $productId = $this->findProductByCode('mag-pagtounico'); - if (false === $productId) { - return $this->createProduct([ - 'name' => 'Pagamento Único (não remover)', - 'code' => 'mag-pagtounico', - 'status' => 'active', - 'pricing_schema' => [ - 'price' => 0, - ], - ]); - } - return $productId; - } - - /** - * Make an API request to retrieve a Product or to create it if not found. - * @param array $product - * - * @return array|bool|mixed - */ - public function findOrCreateProduct($product) - { - // - $productId = $this->findProductByCode($product['sku']); - if (false === $productId) { - return $this->createProduct([ - 'name' => $product['name'], - 'code' => $product['sku'], - 'status' => 'active', - 'pricing_schema' => [ - 'price' => 0, - ], - ]); - } - return $productId; - } - - /** - * Make an API request to retrieve information about the Merchant. - * - * @return array|bool|mixed - */ - public function getMerchant() - { - $merchant = $this->cache()->load('vindi_merchant'); - if ($merchant === false) { - $response = $this->request('merchant', 'GET'); - if (!$response || !isset($response['merchant'])) { - return false; - } - $merchant = $response['merchant']; - $this->cache()->save(serialize($merchant), 'vindi_merchant', ['vindi_cache'], 1 * 60 * 60); // 1 hour - } else { - $merchant = unserialize($merchant); - } - return $merchant; - } - - /** - * Check to see if Merchant Status is Trial. - * - * @return boolean - */ - public function isMerchantStatusTrial() - { - if ($merchant = $this->getMerchant()) { - return 'trial' === $merchant['status']; - } - return false; - } - - /** - * @param $billId - * - * @return array|bool - */ - public function getBill($billId) - { - $response = $this->request("bills/{$billId}", 'GET'); - if (!$response || !isset($response['bill'])) { - return false; - } - return $response['bill']; - } - - public function getDebitCardRedirectUrl($billId) - { - $bill = $this->request('bills/' . $billId, 'GET'); - $chargeId = $bill['bill']['charges'][0]['id']; - $charged = $this->request('charges/' . $chargeId . '/charge', 'POST', [ - 'id' => $bill['bill']['payment_profile']['id'] - ]); - return $charged['charge']['last_transaction']['gateway_response_fields']['authorization_url']; - } -} \ No newline at end of file diff --git a/app/code/Vindi/Payment/Model/Payment/CreditCard.php b/app/code/Vindi/Payment/Model/Payment/CreditCard.php deleted file mode 100644 index 88b1ba8d..00000000 --- a/app/code/Vindi/Payment/Model/Payment/CreditCard.php +++ /dev/null @@ -1,325 +0,0 @@ -getInfoInstance(); - $quote = $info->getQuote(); - - $info->setAdditionalInformation('installments', $data->getCcInstallments()); - - if ($data->getCcChoice() === 'saved') { - $info->setAdditionalInformation('PaymentMethod', $this->_code) - ->setAdditionalInformation('use_saved_cc', true); - - return $this; - } - - $info->setCcType($data->getCcType()) - ->setCcOwner($data->getCcOwner()) - ->setCcLast4(substr($data->getCcNumber(), -4)) - ->setCcNumber($data->getCcNumber()) - ->setCcCid($data->getCcCid()) - ->setCcExpMonth($data->getCcExpMonth()) - ->setCcExpYear($data->getCcExpYear()) - ->setCcSsIssue($data->getCcSsIssue()) - ->setCcSsStartMonth($data->getCcSsStartMonth()) - ->setCcSsStartYear($data->getCcSsStartYear()) - ->setAdditionalInformation('PaymentMethod', $this->_code) - ->setAdditionalInformation('use_saved_cc', false); - - return $this; - } - - /** - * @param string $paymentAction - * @param object $stateObject - * - * @return bool|Mage_Payment_Model_Method_Abstract - */ - protected function processNewOrder($paymentAction, $stateObject) - { - $payment = $this->getInfoInstance(); - $order = $payment->getOrder(); - - $customer = Mage::getModel('customer/customer'); - - $customerId = $this->createCustomer($order, $customer); - $customerVindiId = $customer->getVindiUserCode(); - - if (!$payment->getAdditionalInformation('use_saved_cc')) { - $this->createPaymentProfile($customerId); - } else { - $this->assignDataFromPreviousPaymentProfile($customerVindiId); - } - - if ($this->isSingleOrder($order)) { - $result = $this->processSinglePayment($payment, $order, $customerId); - } else { - $result = $this->processSubscription($payment, $order, $customerId); - } - - if (!$result) { - return false; - } - - $billData = $this->api()->getBill($result); - $installments = $billData['installments']; - $response_fields = $billData['charges'][0]['last_transaction']['gateway_response_fields']; - $possible = ['nsu', 'proof_of_sale']; - $nsu = ''; - foreach ($possible as $nsu_field) { - if ($response_fields[$nsu_field]) { - $nsu = $response_fields[$nsu_field]; - } - } - - $this->getInfoInstance()->setAdditionalInformation( - [ - 'installments' => $installments, - 'nsu' => $nsu - ] - ); - - $stateObject->setStatus(Mage_Sales_Model_Order::STATE_PENDING_PAYMENT) - ->setState(Mage_Sales_Model_Order::STATE_PENDING_PAYMENT); - - return $this; - } - - /** - * @param int $customerId - * - * @return array|bool - */ - protected function createPaymentProfile($customerId) - { - $payment = $this->getInfoInstance(); - - $creditCardData = [ - 'holder_name' => $payment->getCcOwner(), - 'card_expiration' => str_pad($payment->getCcExpMonth(), 2, '0', STR_PAD_LEFT) - . '/' . $payment->getCcExpYear(), - 'card_number' => $payment->getCcNumber(), - 'card_cvv' => $payment->getCcCid() ?: '000', - 'customer_id' => $customerId, - 'payment_company_code' => $payment->getCcType(), - 'payment_method_code' => $this->getPaymentMethodCode() - ]; - - $paymentProfile = $this->api()->createCustomerPaymentProfile($creditCardData); - - if ($paymentProfile === false) { - Mage::throwException('Erro ao informar os dados de cartão de crédito. Verifique os dados e tente novamente!'); - - return false; - } - - $verifyMethod = Mage::getStoreConfig('vindi_subscription/general/verify_method'); - - if ($verifyMethod && !$this->verifyPaymentProfile($paymentProfile['payment_profile']['id'])) { - Mage::throwException('Não foi possível realizar a verificação do seu cartão de crédito!'); - return false; - } - return $paymentProfile; - } - - /** - * @param int $paymentProfileId - * - * @return array|bool - */ - public function verifyPaymentProfile($paymentProfileId) - { - $verify_status = $this->api()->verifyCustomerPaymentProfile($paymentProfileId); - return ($verify_status['transaction']['status'] === 'success'); - } - - /** - * @param int $customerVindiId - */ - protected function assignDataFromPreviousPaymentProfile($customerVindiId) - { - $api = Mage::helper('vindi_subscription/api'); - $savedCc = $api->getCustomerPaymentProfile($customerVindiId); - $info = $this->getInfoInstance(); - - $info->setCcType($savedCc['payment_company']['code']) - ->setCcOwner($savedCc['holder_name']) - ->setCcLast4($savedCc['card_number_last_four']) - ->setCcNumber($savedCc['card_number_last_four']) - ->setAdditionalInformation('use_saved_cc', true); - } - - /** - * Check whether payment method can be used - * - * @param Mage_Sales_Model_Quote|null $quote - * - * @return bool - */ - public function isAvailable($quote = null) - { - return Mage::getStoreConfig('payment/vindi_creditcard/active') - && Mage::helper('vindi_subscription')->getKey(); - } - - /** - * Validate payment method information object - * - * @return Mage_Payment_Model_Method_Abstract - */ - public function validate() - { - $info = $this->getInfoInstance(); - - $quote = $info->getQuote(); - - $maxInstallmentsNumber = Mage::getStoreConfig('payment/vindi_creditcard/max_installments_number'); - - if ($this->isSingleOrder($quote) && ($maxInstallmentsNumber > 1)) { - if (!$installments = $info->getAdditionalInformation('installments')) { - return $this->error('Você deve informar o número de parcelas.'); - } - - if ($installments > $maxInstallmentsNumber) { - return $this->error('O número de parcelas selecionado é inválido.'); - } - - $minInstallmentsValue = Mage::getStoreConfig('payment/vindi_creditcard/min_installment_value'); - $installmentValue = ceil($quote->getGrandTotal() / $installments * 100) / 100; - - if (($installmentValue < $minInstallmentsValue) && ($installments > 1)) { - return $this->error('O número de parcelas selecionado é inválido.'); - } - } - - if ($info->getAdditionalInformation('use_saved_cc')) { - return $this; - } - - $availableTypes = $this->api()->getCreditCardTypes(); - - $ccNumber = $info->getCcNumber(); - - // remove credit card non-numbers - $ccNumber = preg_replace('/\D/', '', $ccNumber); - - $info->setCcNumber($ccNumber); - - if (!$this->_validateExpDate($info->getCcExpYear(), $info->getCcExpMonth())) { - return $this->error(Mage::helper('payment')->__('Incorrect credit card expiration date.')); - } - - if (!array_key_exists($info->getCcType(), $availableTypes)) { - return $this->error(Mage::helper('payment')->__('Credit card type is not allowed for this payment method.')); - } - - return $this; - } - - /** - * @param string $errorMsg - * - * @return bool - * @throws \Mage_Core_Exception - */ - private function error($errorMsg) - { - Mage::throwException($errorMsg); - - return false; - } - - /** - * @return string - */ - protected function getPaymentMethodCode() - { - // TODO fix it to proper method code - return 'credit_card'; - } -} diff --git a/app/code/Vindi/Payment/view/frontend/web/template/payment/cc-form.html b/app/code/Vindi/Payment/view/frontend/web/template/payment/cc-form.html deleted file mode 100644 index fdf6e030..00000000 --- a/app/code/Vindi/Payment/view/frontend/web/template/payment/cc-form.html +++ /dev/null @@ -1,107 +0,0 @@ -
- - -
-
-
-
    - -
  • -
  • - -
- -
-
-
- -
- -
-
-
- -
-
-
-
- -
-
-
-
- -
-
-
-
-
- -
- -
- -
- - - -
-
-
- -
\ No newline at end of file From 4f7f874c7238fc22bb8daf9465b4643e2bfd736a Mon Sep 17 00:00:00 2001 From: leonardo albuquerque Date: Tue, 24 Jul 2018 16:50:57 -0300 Subject: [PATCH 05/46] =?UTF-8?q?#11177=20iniciado=20implementa=C3=A7?= =?UTF-8?q?=C3=A3o=20do=20checkout?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/code/Vindi/Payment/Model/Api.php | 706 ++++++++++++++++++ .../Payment/Model/Payment/CreditCard.php | 325 ++++++++ .../Vindi/Payment/Model/Payment/Vindi.php | 307 +++++++- .../Vindi/Payment/etc/adminhtml/system.xml | 36 +- app/code/Vindi/Payment/etc/config.xml | 3 +- app/code/Vindi/Payment/etc/module.xml | 3 +- app/code/Vindi/Payment/etc/payment.xml | 3 +- .../frontend/layout/checkout_index_index.xml | 11 +- .../web/template/payment/cc-form.html | 107 +++ .../frontend/web/template/payment/vindi.html | 8 +- 10 files changed, 1492 insertions(+), 17 deletions(-) create mode 100644 app/code/Vindi/Payment/Model/Api.php create mode 100644 app/code/Vindi/Payment/Model/Payment/CreditCard.php create mode 100644 app/code/Vindi/Payment/view/frontend/web/template/payment/cc-form.html diff --git a/app/code/Vindi/Payment/Model/Api.php b/app/code/Vindi/Payment/Model/Api.php new file mode 100644 index 00000000..7b36957b --- /dev/null +++ b/app/code/Vindi/Payment/Model/Api.php @@ -0,0 +1,706 @@ +scopeConfig = $scopeConfig; + $this->logger = $logger; + $this->cacheType = $cacheType; + $this->message = $message; + + $storeScope = \Magento\Store\Model\ScopeInterface::SCOPE_STORE; + $isSandBox = $this->scopeConfig->getValue('payment/vindi/sandboxmode', $storeScope); + + if ($isSandBox) { + $this->base_path = 'https://sandbox-app.vindi.com.br/api/v1/'; + } else { + $this->base_path = 'https://app.vindi.com.br/api/v1/'; + } + + $moduleInfo = $moduleList->getOne('Vindi_Payment'); + $this->version = $moduleInfo['setup_version']; + $this->key = $this->scopeConfig->getValue('payment/vindi/key', $storeScope); + } + + + public function execute(Observer $observer) + { + $storeScope = \Magento\Store\Model\ScopeInterface::SCOPE_STORE; + $notifyEmail = $this->scopeConfig->getValue(self::BASEPATH, $storeScope); + + echo $notifyEmail; + } + + /** + * @param string $message + * @param int|null $level + */ + private function log($message) + { + $this->logger->warning($message); + } + + /** + * @return \Zend_Cache_Core + */ + private function cache() + { + return $this->cacheType; + } + + /** + * Build HTTP Query. + * + * @param array $data + * + * @return string + */ + private function buildBody($data) + { + $body = null; + if (!empty($data)) { + $body = json_encode($data); + } + return $body; + } + + /** + * @param array $error + * @param $endpoint + * + * @return string + */ + private function getErrorMessage($error, $endpoint) + { + return "Erro em $endpoint: {$error['id']}: {$error['parameter']} - {$error['message']}"; + } + + /** + * @param array $response + * @param $endpoint + * + * @return bool + */ + private function checkResponse($response, $endpoint) + { + if (isset($response['errors']) && !empty($response['errors'])) { + foreach ($response['errors'] as $error) { + $message = $this->getErrorMessage($error, $endpoint); + $this->message->addErrorMessage($message); + $this->lastError = $message; + } + return false; + } + $this->lastError = ''; + return true; + } + + /** + * Perform request to API. + * + * @param string $endpoint + * @param string $method + * @param array $data + * @param null $dataToLog + * + * @return array|bool|mixed + */ + private function request($endpoint, $method = 'POST', $data = [], $dataToLog = null) + { + if (!$this->key) { + return false; + } + $url = $this->base_path . $endpoint; + $body = $this->buildBody($data); + $requestId = rand(); + $dataToLog = null !== $dataToLog ? $this->buildBody($dataToLog) : $body; + $this->log(sprintf("[Request #%s]: Novo Request para a API.\n%s %s\n%s", $requestId, $method, $url, + $dataToLog)); + $ch = curl_init(); + $ch_options = [ + CURLOPT_HTTPHEADER => [ + 'Content-Type: application/json', + ], + CURLOPT_TIMEOUT => 60, + CURLOPT_SSL_VERIFYPEER => true, + CURLOPT_HEADER => true, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_USERAGENT => 'Vindi-Magento/' . $this->version, + CURLOPT_SSLVERSION => 'CURL_SSLVERSION_TLSv1_2', + CURLOPT_USERPWD => $this->key . ':', + CURLOPT_URL => $url, + CURLOPT_CUSTOMREQUEST => $method + ]; + if (!empty($body)) { + $ch_options[CURLOPT_POSTFIELDS] = $body; + } + curl_setopt_array($ch, $ch_options); + $response = curl_exec($ch); + $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + $body = substr($response, curl_getinfo($ch, CURLINFO_HEADER_SIZE)); + if (curl_errno($ch) || $response === false) { + $this->log(sprintf("[Request #%s]: Erro ao fazer request!\n%s", $requestId, print_r($response, true))); + return false; + } + curl_close($ch); + $status = "HTTP Status: $statusCode"; + $this->log(sprintf("[Request #%s]: Nova Resposta da API.\n%s\n%s", $requestId, $status, $body)); + $responseBody = json_decode($body, true); + if (!$responseBody) { + $this->log(sprintf('[Request #%s]: Erro ao recuperar corpo do request! %s', $requestId, + print_r($body, true))); + return false; + } + if (!$this->checkResponse($responseBody, $endpoint)) { + return false; + } + return $responseBody; + } + + /** + * Make an API request to create a Customer. + * + * @param array $body (name, email, code) + * + * @return array|bool|mixed + */ + public function createCustomer($body) + { + if ($response = $this->request('customers', 'POST', $body)) { + return $response['customer']['id']; + } + return false; + } + + /** + * Make an API request to retrieve an existing Customer. + * + * @param string $code + * + * @return array|bool|mixed + */ + public function findCustomerByCode($code) + { + $customerId = $this->cache()->load("vindi_customer_by_code_{$code}"); + if ($customerId === false) { + $response = $this->request("customers/search?code={$code}", 'GET'); + if ($response && (1 === count($response['customers'])) && isset($response['customers'][0]['id'])) { + $customerId = $response['customers'][0]['id']; + $this->cache()->save(serialize($customerId), "vindi_customer_by_code_{$code}", ['vindi_cache'], + 5 * 60); // 5 minutes + } + } else { + $customerId = unserialize($customerId); + } + return $customerId; + } + + /** + * Make an API request to retrieve an existing Customer or to create one if not found. + * + * @param array $body (name, email, code) + * + * @return array|bool|mixed + */ + public function findOrCreateCustomer($body) + { + $customerId = $this->findCustomerByCode($body['code']); + // TODO update information + if (false === $customerId) { + return $this->createCustomer($body); + } + return $customerId; + } + + /** + * Make an API request to create a Payment Profile to a Customer. + * + * @param $body (holder_name, card_expiration, card_number, card_cvv, customer_id) + * + * @return array|bool|mixed + */ + public function createCustomerPaymentProfile($body) + { + // Protect credit card number. + $dataToLog = $body; + $dataToLog['card_number'] = '**** *' . substr($dataToLog['card_number'], -3); + $dataToLog['card_cvv'] = '***'; + $customerId = $body['customer_id']; + $this->cache()->remove("vindi_payment_profile_{$customerId}"); + return $this->request('payment_profiles', 'POST', $body, $dataToLog); + } + + /** + * Make an API request to verify a Payment Profile to a Customer. + * + * @param $id integer + * + * @return array|bool|mixed + */ + public function verifyCustomerPaymentProfile($id) + { + return $this->request('payment_profiles/' . $id . '/verify', 'POST'); + } + + /** + * @param $userCode + * + * @return bool + */ + public function getCustomerPaymentProfile($userCode, $type = "CreditCard") + { + $customerId = $this->findCustomerByCode($userCode); + if (false === $customerId) { + return false; + } + $paymentProfile = $this->cache()->load("vindi_payment_profile_{$customerId}"); + if ($paymentProfile === false || strpos($paymentProfile, $type) === false) { + $endpoint = 'payment_profiles?query=customer_id%3D' . $customerId + . '%20status%3Dactive%20type%3DPaymentProfile%3A%3A' . $type; + $response = $this->request($endpoint, 'GET'); + if ($response && $response['payment_profiles'] && count($response['payment_profiles'])) { + $paymentProfile = $response['payment_profiles'][0]; + $this->cache()->save(serialize($paymentProfile), "vindi_payment_profile_{$customerId}", ['vindi_cache'], + 5 * 60); // 5 minutes + } else { + $paymentProfile = false; + } + } else { + $paymentProfile = unserialize($paymentProfile); + } + return $paymentProfile; + } + + /** + * Make an API request to create a Subscription. + * + * @param $body (plan_id, customer_id, payment_method_code, product_items[{product_id}]) + * + * @return array + */ + public function createSubscription($body) + { + if (($response = $this->request('subscriptions', 'POST', $body)) && isset($response['subscription']['id'])) { + $subscription = $response['subscription']; + $subscription['bill'] = $response['bill']; + return $subscription; + } + return false; + } + + /** + * Make an API request to retrieve Payment Methods. + * + * @return array|bool + */ + public function getPaymentMethods() + { + $paymentMethods = $this->cache()->load('vindi_payment_methods'); + if ($paymentMethods === false) { + $paymentMethods = [ + 'credit_card' => [], + 'debit_card' => [], + 'bank_slip' => false, + ]; + $response = $this->request('payment_methods', 'GET'); + if (false === $response) { + return $this->acceptBankSlip = false; + } + foreach ($response['payment_methods'] as $method) { + if ('active' !== $method['status']) { + continue; + } + if ('PaymentMethod::CreditCard' === $method['type']) { + $paymentMethods['credit_card'] = array_merge( + $paymentMethods['credit_card'], + $method['payment_companies'] + ); + } elseif ('PaymentMethod::DebitCard' === $method['type']) { + $paymentMethods['debit_card'] = array_merge( + $paymentMethods['debit_card'], + $method['payment_companies'] + ); + } elseif ('PaymentMethod::BankSlip' === $method['type']) { + $paymentMethods['bank_slip'] = true; + } + } + $this->cache()->save(serialize($paymentMethods), 'vindi_payment_methods', ['vindi_cache'], + 12 * 60 * 60); // 12 hours + } else { + $paymentMethods = unserialize($paymentMethods); + } + $this->acceptBankSlip = $paymentMethods['bank_slip']; + return $paymentMethods; + } + + /** + * Retrieve Credit Card Types from Payment Methods. + * + * @return array + */ + public function getCreditCardTypes() + { + $methods = $this->getPaymentMethods(); + $types = []; + foreach ($methods['credit_card'] as $type) { + $types[$type['code']] = $type['name']; + } + return $types; + } + + /** + * Retrieve Debit Card Types from Payment Methods. + * + * @return array + */ + public function getDebitCardTypes() + { + $methods = $this->getPaymentMethods(); + $types = []; + foreach ($methods['debit_card'] as $type) { + $types[$type['code']] = $type['name']; + } + return $types; + } + + /** + * @return bool|null + */ + public function acceptBankSlip() + { + if (null === $this->acceptBankSlip) { + $this->getPaymentMethods(); + } + return $this->acceptBankSlip; + } + + /** + * @param array $body + * + * @return int|bool + */ + public function createBill($body) + { + if ($response = $this->request('bills', 'POST', $body)) { + return $response['bill']; + } + return false; + } + + /** + * @param $billId + * + * @return array|bool|mixed + */ + public function approveBill($billId) + { + $response = $this->request("bills/{$billId}", 'GET'); + if (false === $response || !isset($response['bill'])) { + return false; + } + $bill = $response['bill']; + if ('review' !== $bill['status']) { + return true; + } + return $this->request("bills/{$billId}/approve", 'POST'); + } + + /** + * @param $billId + */ + public function deleteBill($billId) + { + $this->request("bills/{$billId}", 'DELETE'); + } + + /** + * @param $billId + * + * @return string + */ + public function getBankSlipDownload($billId) + { + $response = $this->request("bills/{$billId}", 'GET'); + if (false === $response) { + return false; + } + return $response['bill']['charges'][0]['print_url']; + } + + /** + * @return array + */ + public function getProducts() + { + $list = []; + $response = $this->request('products?query=status:active', 'GET'); + if ($products = $response['products']) { + foreach ($products as $product) { + $list[$product['id']] = "{$product['name']} ({$product['pricing_schema']['short_format']})"; + } + } + return $list; + } + + /** + * @param int $id + * + * @return array + */ + public function getPlanItems($id) + { + $list = []; + $response = $this->request("plans/{$id}", 'GET'); + if ($plan = $response['plan']) { + foreach ($plan['plan_items'] as $item) { + if (isset($item['product'])) { + $list[] = $item['product']['id']; + } + } + } + return $list; + } + + /** + * @param Mage_Sales_Model_Order $order + * + * @return array + */ + public function buildPlanItemsForSubscription($order) + { + $list = []; + $orderItems = $order->getItemsCollection(); + $orderSubtotal = $order->getQuote()->getSubtotal(); + $orderDiscount = $order->getDiscountAmount() * -1; + $discount = null; + if (!empty($orderDiscount)) { + $discountPercentage = $orderDiscount * 100 / $orderSubtotal; + $discountPercentage = number_format(floor($discountPercentage * 100) / 100, 2); + $discount = [[ + 'discount_type' => 'percentage', + 'percentage' => $discountPercentage + ]]; + } + foreach ($orderItems as $item) { + $product = Mage::getModel('catalog/product')->load($item->getProductId()); + if ($product->getTypeID() !== 'subscription') { + throw new \Exception("O produto {$item->getName()} não é uma assinatura."); + return false; + } + $productVindiId = $this->findOrCreateProduct(array('sku' => $item->getSku(), 'name' => $item->getName())); + for ($i = 1; $i <= $item->getQtyOrdered(); $i++) { + $list[] = [ + 'product_id' => $productVindiId, + 'pricing_schema' => ['price' => $item->getPrice()], + 'discounts' => $discount, + ]; + } + } + // Create product for shipping + $productVindiId = $this->findOrCreateProduct(array('sku' => 'frete', 'name' => 'Frete')); + $list[] = [ + 'product_id' => $productVindiId, + 'pricing_schema' => ['price' => $order->getShippingAmount()], + ]; + return $list; + } + + /** + * @return array + */ + public function getPlans() + { + $list = $this->cache()->load('vindi_plans'); + if (($list === false) || !count($list = unserialize($list))) { + $list = []; + $response = $this->request('plans?query=status:active', 'GET'); + if ($plans = $response['plans']) { + foreach ($plans as $plan) { + $list[$plan['id']] = $plan['name']; + } + } + $this->cache()->save(serialize($list), 'vindi_plans', ['vindi_cache'], 10 * 60); // 10 minutes + } + return $list; + } + + public function getPlanInstallments($id) + { + $response = $this->request("plans/{$id}", 'GET'); + $plan = $response['plan']; + $installments = $plan['installments']; + return $installments; + } + + /** + * Make an API request to create a Product. + * + * @param array $body (name, code, status, pricing_schema (price)) + * + * @return array|bool|mixed + */ + public function createProduct($body) + { + if ($response = $this->request('products', 'POST', $body)) { + return $response['product']['id']; + } + return false; + } + + /** + * Make an API request to retrieve an existing Product. + * + * @param string $code + * + * @return array|bool|mixed + */ + public function findProductByCode($code) + { + $response = $this->request("products?query=code%3D{$code}", 'GET'); + if ($response && (1 === count($response['products'])) && isset($response['products'][0]['id'])) { + return $response['products'][0]['id']; + } + return false; + } + + /** + * Make an API request to retrieve the Unique Payment Product or to create it if not found. + * + * @return array|bool|mixed + */ + public function findOrCreateUniquePaymentProduct() + { + $productId = $this->findProductByCode('mag-pagtounico'); + if (false === $productId) { + return $this->createProduct([ + 'name' => 'Pagamento Único (não remover)', + 'code' => 'mag-pagtounico', + 'status' => 'active', + 'pricing_schema' => [ + 'price' => 0, + ], + ]); + } + return $productId; + } + + /** + * Make an API request to retrieve a Product or to create it if not found. + * @param array $product + * + * @return array|bool|mixed + */ + public function findOrCreateProduct($product) + { + // + $productId = $this->findProductByCode($product['sku']); + if (false === $productId) { + return $this->createProduct([ + 'name' => $product['name'], + 'code' => $product['sku'], + 'status' => 'active', + 'pricing_schema' => [ + 'price' => 0, + ], + ]); + } + return $productId; + } + + /** + * Make an API request to retrieve information about the Merchant. + * + * @return array|bool|mixed + */ + public function getMerchant() + { + $merchant = $this->cache()->load('vindi_merchant'); + if ($merchant === false) { + $response = $this->request('merchant', 'GET'); + if (!$response || !isset($response['merchant'])) { + return false; + } + $merchant = $response['merchant']; + $this->cache()->save(serialize($merchant), 'vindi_merchant', ['vindi_cache'], 1 * 60 * 60); // 1 hour + } else { + $merchant = unserialize($merchant); + } + return $merchant; + } + + /** + * Check to see if Merchant Status is Trial. + * + * @return boolean + */ + public function isMerchantStatusTrial() + { + if ($merchant = $this->getMerchant()) { + return 'trial' === $merchant['status']; + } + return false; + } + + /** + * @param $billId + * + * @return array|bool + */ + public function getBill($billId) + { + $response = $this->request("bills/{$billId}", 'GET'); + if (!$response || !isset($response['bill'])) { + return false; + } + return $response['bill']; + } + + public function getDebitCardRedirectUrl($billId) + { + $bill = $this->request('bills/' . $billId, 'GET'); + $chargeId = $bill['bill']['charges'][0]['id']; + $charged = $this->request('charges/' . $chargeId . '/charge', 'POST', [ + 'id' => $bill['bill']['payment_profile']['id'] + ]); + return $charged['charge']['last_transaction']['gateway_response_fields']['authorization_url']; + } +} \ No newline at end of file diff --git a/app/code/Vindi/Payment/Model/Payment/CreditCard.php b/app/code/Vindi/Payment/Model/Payment/CreditCard.php new file mode 100644 index 00000000..88b1ba8d --- /dev/null +++ b/app/code/Vindi/Payment/Model/Payment/CreditCard.php @@ -0,0 +1,325 @@ +getInfoInstance(); + $quote = $info->getQuote(); + + $info->setAdditionalInformation('installments', $data->getCcInstallments()); + + if ($data->getCcChoice() === 'saved') { + $info->setAdditionalInformation('PaymentMethod', $this->_code) + ->setAdditionalInformation('use_saved_cc', true); + + return $this; + } + + $info->setCcType($data->getCcType()) + ->setCcOwner($data->getCcOwner()) + ->setCcLast4(substr($data->getCcNumber(), -4)) + ->setCcNumber($data->getCcNumber()) + ->setCcCid($data->getCcCid()) + ->setCcExpMonth($data->getCcExpMonth()) + ->setCcExpYear($data->getCcExpYear()) + ->setCcSsIssue($data->getCcSsIssue()) + ->setCcSsStartMonth($data->getCcSsStartMonth()) + ->setCcSsStartYear($data->getCcSsStartYear()) + ->setAdditionalInformation('PaymentMethod', $this->_code) + ->setAdditionalInformation('use_saved_cc', false); + + return $this; + } + + /** + * @param string $paymentAction + * @param object $stateObject + * + * @return bool|Mage_Payment_Model_Method_Abstract + */ + protected function processNewOrder($paymentAction, $stateObject) + { + $payment = $this->getInfoInstance(); + $order = $payment->getOrder(); + + $customer = Mage::getModel('customer/customer'); + + $customerId = $this->createCustomer($order, $customer); + $customerVindiId = $customer->getVindiUserCode(); + + if (!$payment->getAdditionalInformation('use_saved_cc')) { + $this->createPaymentProfile($customerId); + } else { + $this->assignDataFromPreviousPaymentProfile($customerVindiId); + } + + if ($this->isSingleOrder($order)) { + $result = $this->processSinglePayment($payment, $order, $customerId); + } else { + $result = $this->processSubscription($payment, $order, $customerId); + } + + if (!$result) { + return false; + } + + $billData = $this->api()->getBill($result); + $installments = $billData['installments']; + $response_fields = $billData['charges'][0]['last_transaction']['gateway_response_fields']; + $possible = ['nsu', 'proof_of_sale']; + $nsu = ''; + foreach ($possible as $nsu_field) { + if ($response_fields[$nsu_field]) { + $nsu = $response_fields[$nsu_field]; + } + } + + $this->getInfoInstance()->setAdditionalInformation( + [ + 'installments' => $installments, + 'nsu' => $nsu + ] + ); + + $stateObject->setStatus(Mage_Sales_Model_Order::STATE_PENDING_PAYMENT) + ->setState(Mage_Sales_Model_Order::STATE_PENDING_PAYMENT); + + return $this; + } + + /** + * @param int $customerId + * + * @return array|bool + */ + protected function createPaymentProfile($customerId) + { + $payment = $this->getInfoInstance(); + + $creditCardData = [ + 'holder_name' => $payment->getCcOwner(), + 'card_expiration' => str_pad($payment->getCcExpMonth(), 2, '0', STR_PAD_LEFT) + . '/' . $payment->getCcExpYear(), + 'card_number' => $payment->getCcNumber(), + 'card_cvv' => $payment->getCcCid() ?: '000', + 'customer_id' => $customerId, + 'payment_company_code' => $payment->getCcType(), + 'payment_method_code' => $this->getPaymentMethodCode() + ]; + + $paymentProfile = $this->api()->createCustomerPaymentProfile($creditCardData); + + if ($paymentProfile === false) { + Mage::throwException('Erro ao informar os dados de cartão de crédito. Verifique os dados e tente novamente!'); + + return false; + } + + $verifyMethod = Mage::getStoreConfig('vindi_subscription/general/verify_method'); + + if ($verifyMethod && !$this->verifyPaymentProfile($paymentProfile['payment_profile']['id'])) { + Mage::throwException('Não foi possível realizar a verificação do seu cartão de crédito!'); + return false; + } + return $paymentProfile; + } + + /** + * @param int $paymentProfileId + * + * @return array|bool + */ + public function verifyPaymentProfile($paymentProfileId) + { + $verify_status = $this->api()->verifyCustomerPaymentProfile($paymentProfileId); + return ($verify_status['transaction']['status'] === 'success'); + } + + /** + * @param int $customerVindiId + */ + protected function assignDataFromPreviousPaymentProfile($customerVindiId) + { + $api = Mage::helper('vindi_subscription/api'); + $savedCc = $api->getCustomerPaymentProfile($customerVindiId); + $info = $this->getInfoInstance(); + + $info->setCcType($savedCc['payment_company']['code']) + ->setCcOwner($savedCc['holder_name']) + ->setCcLast4($savedCc['card_number_last_four']) + ->setCcNumber($savedCc['card_number_last_four']) + ->setAdditionalInformation('use_saved_cc', true); + } + + /** + * Check whether payment method can be used + * + * @param Mage_Sales_Model_Quote|null $quote + * + * @return bool + */ + public function isAvailable($quote = null) + { + return Mage::getStoreConfig('payment/vindi_creditcard/active') + && Mage::helper('vindi_subscription')->getKey(); + } + + /** + * Validate payment method information object + * + * @return Mage_Payment_Model_Method_Abstract + */ + public function validate() + { + $info = $this->getInfoInstance(); + + $quote = $info->getQuote(); + + $maxInstallmentsNumber = Mage::getStoreConfig('payment/vindi_creditcard/max_installments_number'); + + if ($this->isSingleOrder($quote) && ($maxInstallmentsNumber > 1)) { + if (!$installments = $info->getAdditionalInformation('installments')) { + return $this->error('Você deve informar o número de parcelas.'); + } + + if ($installments > $maxInstallmentsNumber) { + return $this->error('O número de parcelas selecionado é inválido.'); + } + + $minInstallmentsValue = Mage::getStoreConfig('payment/vindi_creditcard/min_installment_value'); + $installmentValue = ceil($quote->getGrandTotal() / $installments * 100) / 100; + + if (($installmentValue < $minInstallmentsValue) && ($installments > 1)) { + return $this->error('O número de parcelas selecionado é inválido.'); + } + } + + if ($info->getAdditionalInformation('use_saved_cc')) { + return $this; + } + + $availableTypes = $this->api()->getCreditCardTypes(); + + $ccNumber = $info->getCcNumber(); + + // remove credit card non-numbers + $ccNumber = preg_replace('/\D/', '', $ccNumber); + + $info->setCcNumber($ccNumber); + + if (!$this->_validateExpDate($info->getCcExpYear(), $info->getCcExpMonth())) { + return $this->error(Mage::helper('payment')->__('Incorrect credit card expiration date.')); + } + + if (!array_key_exists($info->getCcType(), $availableTypes)) { + return $this->error(Mage::helper('payment')->__('Credit card type is not allowed for this payment method.')); + } + + return $this; + } + + /** + * @param string $errorMsg + * + * @return bool + * @throws \Mage_Core_Exception + */ + private function error($errorMsg) + { + Mage::throwException($errorMsg); + + return false; + } + + /** + * @return string + */ + protected function getPaymentMethodCode() + { + // TODO fix it to proper method code + return 'credit_card'; + } +} diff --git a/app/code/Vindi/Payment/Model/Payment/Vindi.php b/app/code/Vindi/Payment/Model/Payment/Vindi.php index cc3c19d1..b75a61a2 100644 --- a/app/code/Vindi/Payment/Model/Payment/Vindi.php +++ b/app/code/Vindi/Payment/Model/Payment/Vindi.php @@ -3,6 +3,10 @@ namespace Vindi\Payment\Model\Payment; +use Magento\Framework\DataObject; +use Magento\Quote\Api\Data\CartInterface; +use Vindi\Payment\Model\Api; + class Vindi extends \Magento\Payment\Model\Method\AbstractMethod { @@ -11,7 +15,308 @@ class Vindi extends \Magento\Payment\Model\Method\AbstractMethod public function isAvailable( \Magento\Quote\Api\Data\CartInterface $quote = null - ) { + ) + { return parent::isAvailable($quote); } + + /** + * @var bool + */ + protected $_isGateway = true; + + /** + * @var bool + */ + protected $_canAuthorize = true; + + /** + * @var bool + */ + protected $_canCapture = true; + + /** + * @var bool + */ + protected $_canCapturePartial = false; + + /** + * @var bool + */ + protected $_canRefund = false; + + /** + * @var bool + */ + protected $_canVoid = false; + + /** + * @var bool + */ + protected $_canUseInternal = true; + + /** + * @var bool + */ + protected $_canUseCheckout = true; + + /** + * @var bool + */ + protected $_canUseForMultishipping = false; + + /** + * @var bool + */ + protected $_isInitializeNeeded = true; + + /** + * @var bool + */ + protected $_canSaveCc = false; + + /** + * @var string + */ + protected $_formBlockType = 'vindi_subscription/form_cc'; + + /** + * @var string + */ + protected $_infoBlockType = 'vindi_subscription/info_cc'; + + /** + * Assign data to info model instance + * + * @param mixed $data + * + * @return Mage_Payment_Model_Method_Abstract + */ + public function assignData(DataObject $data) + { + if (!($data instanceof Varien_Object)) { + $data = new Varien_Object($data); + } + $info = $this->getInfoInstance(); + $quote = $info->getQuote(); + + $info->setAdditionalInformation('installments', $data->getCcInstallments()); + + if ($data->getCcChoice() === 'saved') { + $info->setAdditionalInformation('PaymentMethod', $this->_code) + ->setAdditionalInformation('use_saved_cc', true); + + return $this; + } + + $info->setCcType($data->getCcType()) + ->setCcOwner($data->getCcOwner()) + ->setCcLast4(substr($data->getCcNumber(), -4)) + ->setCcNumber($data->getCcNumber()) + ->setCcCid($data->getCcCid()) + ->setCcExpMonth($data->getCcExpMonth()) + ->setCcExpYear($data->getCcExpYear()) + ->setCcSsIssue($data->getCcSsIssue()) + ->setCcSsStartMonth($data->getCcSsStartMonth()) + ->setCcSsStartYear($data->getCcSsStartYear()) + ->setAdditionalInformation('PaymentMethod', $this->_code) + ->setAdditionalInformation('use_saved_cc', false); + + return $this; + } + + /** + * @param string $paymentAction + * @param object $stateObject + * + * @return bool|Mage_Payment_Model_Method_Abstract + */ + protected function processNewOrder($paymentAction, $stateObject) + { + $payment = $this->getInfoInstance(); + $order = $payment->getOrder(); + + $customer = Mage::getModel('customer/customer'); + + $customerId = $this->createCustomer($order, $customer); + $customerVindiId = $customer->getVindiUserCode(); + + if (!$payment->getAdditionalInformation('use_saved_cc')) { + $this->createPaymentProfile($customerId); + } else { + $this->assignDataFromPreviousPaymentProfile($customerVindiId); + } + + if ($this->isSingleOrder($order)) { + $result = $this->processSinglePayment($payment, $order, $customerId); + } else { + $result = $this->processSubscription($payment, $order, $customerId); + } + + if (!$result) { + return false; + } + + $billData = $this->api()->getBill($result); + $installments = $billData['installments']; + $response_fields = $billData['charges'][0]['last_transaction']['gateway_response_fields']; + $possible = ['nsu', 'proof_of_sale']; + $nsu = ''; + foreach ($possible as $nsu_field) { + if ($response_fields[$nsu_field]) { + $nsu = $response_fields[$nsu_field]; + } + } + + $this->getInfoInstance()->setAdditionalInformation( + [ + 'installments' => $installments, + 'nsu' => $nsu + ] + ); + + $stateObject->setStatus(Mage_Sales_Model_Order::STATE_PENDING_PAYMENT) + ->setState(Mage_Sales_Model_Order::STATE_PENDING_PAYMENT); + + return $this; + } + + /** + * @param int $customerId + * + * @return array|bool + */ + protected function createPaymentProfile($customerId) + { + $payment = $this->getInfoInstance(); + + $creditCardData = [ + 'holder_name' => $payment->getCcOwner(), + 'card_expiration' => str_pad($payment->getCcExpMonth(), 2, '0', STR_PAD_LEFT) + . '/' . $payment->getCcExpYear(), + 'card_number' => $payment->getCcNumber(), + 'card_cvv' => $payment->getCcCid() ?: '000', + 'customer_id' => $customerId, + 'payment_company_code' => $payment->getCcType(), + 'payment_method_code' => $this->getPaymentMethodCode() + ]; + + $paymentProfile = $this->api()->createCustomerPaymentProfile($creditCardData); + + if ($paymentProfile === false) { + Mage::throwException('Erro ao informar os dados de cartão de crédito. Verifique os dados e tente novamente!'); + + return false; + } + + $verifyMethod = Mage::getStoreConfig('vindi_subscription/general/verify_method'); + + if ($verifyMethod && !$this->verifyPaymentProfile($paymentProfile['payment_profile']['id'])) { + Mage::throwException('Não foi possível realizar a verificação do seu cartão de crédito!'); + return false; + } + return $paymentProfile; + } + + /** + * @param int $paymentProfileId + * + * @return array|bool + */ + public function verifyPaymentProfile($paymentProfileId) + { + $verify_status = $this->api()->verifyCustomerPaymentProfile($paymentProfileId); + return ($verify_status['transaction']['status'] === 'success'); + } + + /** + * @param int $customerVindiId + */ + protected function assignDataFromPreviousPaymentProfile($customerVindiId) + { + $api = Mage::helper('vindi_subscription/api'); + $savedCc = $api->getCustomerPaymentProfile($customerVindiId); + $info = $this->getInfoInstance(); + + $info->setCcType($savedCc['payment_company']['code']) + ->setCcOwner($savedCc['holder_name']) + ->setCcLast4($savedCc['card_number_last_four']) + ->setCcNumber($savedCc['card_number_last_four']) + ->setAdditionalInformation('use_saved_cc', true); + } + + /** + * Validate payment method information object + * + * @return Mage_Payment_Model_Method_Abstract + */ + public function validate() + { + $info = $this->getInfoInstance(); + + $quote = $info->getQuote(); + + $maxInstallmentsNumber = Mage::getStoreConfig('payment/vindi_creditcard/max_installments_number'); + + if ($this->isSingleOrder($quote) && ($maxInstallmentsNumber > 1)) { + if (!$installments = $info->getAdditionalInformation('installments')) { + return $this->error('Você deve informar o número de parcelas.'); + } + + if ($installments > $maxInstallmentsNumber) { + return $this->error('O número de parcelas selecionado é inválido.'); + } + + $minInstallmentsValue = Mage::getStoreConfig('payment/vindi_creditcard/min_installment_value'); + $installmentValue = ceil($quote->getGrandTotal() / $installments * 100) / 100; + + if (($installmentValue < $minInstallmentsValue) && ($installments > 1)) { + return $this->error('O número de parcelas selecionado é inválido.'); + } + } + + if ($info->getAdditionalInformation('use_saved_cc')) { + return $this; + } + + $availableTypes = $this->api()->getCreditCardTypes(); + + $ccNumber = $info->getCcNumber(); + + // remove credit card non-numbers + $ccNumber = preg_replace('/\D/', '', $ccNumber); + + $info->setCcNumber($ccNumber); + + if (!$this->_validateExpDate($info->getCcExpYear(), $info->getCcExpMonth())) { + return $this->error(Mage::helper('payment')->__('Incorrect credit card expiration date.')); + } + + if (!array_key_exists($info->getCcType(), $availableTypes)) { + return $this->error(Mage::helper('payment')->__('Credit card type is not allowed for this payment method.')); + } + + return $this; + } + + /** + * @param string $errorMsg + * + * @return bool + * @throws \Mage_Core_Exception + */ + private function error($errorMsg) + { + Mage::throwException($errorMsg); + + return false; + } + + /** + * @return string + */ + protected function getPaymentMethodCode() + { + return 'credit_card'; + } } diff --git a/app/code/Vindi/Payment/etc/adminhtml/system.xml b/app/code/Vindi/Payment/etc/adminhtml/system.xml index 18e6dc33..7ee963c0 100644 --- a/app/code/Vindi/Payment/etc/adminhtml/system.xml +++ b/app/code/Vindi/Payment/etc/adminhtml/system.xml @@ -1,33 +1,53 @@ - +
- + Magento\Config\Model\Config\Source\Yesno - + - + + + + Magento\Config\Model\Config\Source\Yesno + + + + + + Magento\Sales\Model\Config\Source\Order\Status\NewStatus - + Magento\Payment\Model\Config\Source\Allspecificcountries - + Magento\Directory\Model\Config\Source\Country 1 - + - + diff --git a/app/code/Vindi/Payment/etc/config.xml b/app/code/Vindi/Payment/etc/config.xml index 17583699..334d01b2 100644 --- a/app/code/Vindi/Payment/etc/config.xml +++ b/app/code/Vindi/Payment/etc/config.xml @@ -1,5 +1,6 @@ - + diff --git a/app/code/Vindi/Payment/etc/module.xml b/app/code/Vindi/Payment/etc/module.xml index d9645236..a0b5b47b 100644 --- a/app/code/Vindi/Payment/etc/module.xml +++ b/app/code/Vindi/Payment/etc/module.xml @@ -1,4 +1,5 @@ - + diff --git a/app/code/Vindi/Payment/etc/payment.xml b/app/code/Vindi/Payment/etc/payment.xml index cbe2c415..6d8e26e9 100644 --- a/app/code/Vindi/Payment/etc/payment.xml +++ b/app/code/Vindi/Payment/etc/payment.xml @@ -1,5 +1,6 @@ - + diff --git a/app/code/Vindi/Payment/view/frontend/layout/checkout_index_index.xml b/app/code/Vindi/Payment/view/frontend/layout/checkout_index_index.xml index 01dbadc4..b25e49d5 100644 --- a/app/code/Vindi/Payment/view/frontend/layout/checkout_index_index.xml +++ b/app/code/Vindi/Payment/view/frontend/layout/checkout_index_index.xml @@ -1,5 +1,6 @@ - + @@ -16,10 +17,14 @@ - Vindi_Payment/js/view/payment/vindi + + Vindi_Payment/js/view/payment/vindi + - true + true + diff --git a/app/code/Vindi/Payment/view/frontend/web/template/payment/cc-form.html b/app/code/Vindi/Payment/view/frontend/web/template/payment/cc-form.html new file mode 100644 index 00000000..fdf6e030 --- /dev/null +++ b/app/code/Vindi/Payment/view/frontend/web/template/payment/cc-form.html @@ -0,0 +1,107 @@ +
+ + +
+
+
+
    + +
  • +
  • + +
+ +
+
+
+ +
+ +
+
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+
+
+
+ +
+ +
+ +
+ + + +
+
+
+ +
\ No newline at end of file diff --git a/app/code/Vindi/Payment/view/frontend/web/template/payment/vindi.html b/app/code/Vindi/Payment/view/frontend/web/template/payment/vindi.html index cebbb9ac..4a4545be 100644 --- a/app/code/Vindi/Payment/view/frontend/web/template/payment/vindi.html +++ b/app/code/Vindi/Payment/view/frontend/web/template/payment/vindi.html @@ -21,9 +21,14 @@ + +
+ +
+
- +
@@ -43,4 +48,3 @@
- \ No newline at end of file From 4df926c29bf580fb11838e4d077f8f83c42b1aa9 Mon Sep 17 00:00:00 2001 From: leonardo albuquerque Date: Tue, 24 Jul 2018 18:28:57 -0300 Subject: [PATCH 06/46] =?UTF-8?q?#11177=20iniciado=20cria=C3=A7=C3=A3o=20d?= =?UTF-8?q?a=20op=C3=A7=C3=A3o=20no=20carrinho?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/code/Vindi/Payment/i18n/pt_BR.csv | 1 + .../payment/method-renderer/vindi-method.js | 2 +- .../web/template/payment/cc-form.html | 23 ++++++++++--------- 3 files changed, 14 insertions(+), 12 deletions(-) create mode 100644 app/code/Vindi/Payment/i18n/pt_BR.csv diff --git a/app/code/Vindi/Payment/i18n/pt_BR.csv b/app/code/Vindi/Payment/i18n/pt_BR.csv new file mode 100644 index 00000000..c5ef7807 --- /dev/null +++ b/app/code/Vindi/Payment/i18n/pt_BR.csv @@ -0,0 +1 @@ +'Credit Card Number', 'Cartão de Crédito' \ No newline at end of file diff --git a/app/code/Vindi/Payment/view/frontend/web/js/view/payment/method-renderer/vindi-method.js b/app/code/Vindi/Payment/view/frontend/web/js/view/payment/method-renderer/vindi-method.js index 51ab10f0..222cea6e 100644 --- a/app/code/Vindi/Payment/view/frontend/web/js/view/payment/method-renderer/vindi-method.js +++ b/app/code/Vindi/Payment/view/frontend/web/js/view/payment/method-renderer/vindi-method.js @@ -1,6 +1,6 @@ define( [ - 'Magento_Checkout/js/view/payment/default' + 'Magento_Checkout/js/view/payment/default', ], function (Component) { 'use strict'; diff --git a/app/code/Vindi/Payment/view/frontend/web/template/payment/cc-form.html b/app/code/Vindi/Payment/view/frontend/web/template/payment/cc-form.html index fdf6e030..63f5ceb0 100644 --- a/app/code/Vindi/Payment/view/frontend/web/template/payment/cc-form.html +++ b/app/code/Vindi/Payment/view/frontend/web/template/payment/cc-form.html @@ -1,7 +1,8 @@
- -
+ Credit Card Information + +
    @@ -23,8 +24,8 @@
-
From 51e58514807f64be81dd2cae41b3933008c7b1a3 Mon Sep 17 00:00:00 2001 From: leonardo albuquerque Date: Tue, 14 Aug 2018 15:57:25 -0300 Subject: [PATCH 18/46] =?UTF-8?q?corrigido=20chamada=20da=20fun=C3=A7?= =?UTF-8?q?=C3=A3o=20createCustomer=20fix=20#30?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Model/Payment/Customer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Model/Payment/Customer.php b/Model/Payment/Customer.php index af6364e4..98b1aaa4 100644 --- a/Model/Payment/Customer.php +++ b/Model/Payment/Customer.php @@ -46,7 +46,7 @@ public function findOrCreate($order) 'address' => $address ]; - $customerId = $this->api->createCustomer($customerVindi); + $customerId = $this->createCustomer($customerVindi); if ($customerId === false) { $this->messageManager->addErrorMessage(__('Fail while registering the user. Verify data and try again')); @@ -65,7 +65,7 @@ public function findOrCreate($order) */ public function createCustomer($body) { - if ($response = $this->request('customers', 'POST', $body)) { + if ($response = $this->api->request('customers', 'POST', $body)) { return $response['customer']['id']; } From 329d88ea9f8f8ff463be265d9bea9617c964a95a Mon Sep 17 00:00:00 2001 From: Cristhian Silveira Silva Date: Fri, 26 Oct 2018 17:51:55 -0300 Subject: [PATCH 19/46] validation for existence of some payment method and validation of filling the token field in the configurations of the module --- Model/Payment/Api.php | 3 +++ Model/Payment/PaymentMethod.php | 6 ++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Model/Payment/Api.php b/Model/Payment/Api.php index 555ac623..462a8860 100644 --- a/Model/Payment/Api.php +++ b/Model/Payment/Api.php @@ -28,6 +28,9 @@ public function __construct( public function request($endpoint, $method = 'POST', $data = [], $dataToLog = null) { + if (!$this->apiKey) { + return false; + } $url = $this->base_path . $endpoint; $body = json_encode($data); $requestId = number_format(microtime(true), 2, '', ''); diff --git a/Model/Payment/PaymentMethod.php b/Model/Payment/PaymentMethod.php index d8e81a48..da77a6d8 100644 --- a/Model/Payment/PaymentMethod.php +++ b/Model/Payment/PaymentMethod.php @@ -20,8 +20,10 @@ public function getCreditCardTypes() $methods = $this->get(); $types = []; - foreach ($methods['credit_card'] as $type) { - $types[$type['code']] = $type['name']; + if ($methods) { + foreach ($methods['credit_card'] as $type) { + $types[$type['code']] = $type['name']; + } } return $types; From c37b3c5b901d0231e8afa6c91b875a6a37fdb62e Mon Sep 17 00:00:00 2001 From: Gabriel Ranghetti Date: Fri, 17 May 2019 13:59:26 -0300 Subject: [PATCH 20/46] fix ApiKeyValidator Exception Phrase --- Model/Config/Backend/ApiKeyValidator.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Model/Config/Backend/ApiKeyValidator.php b/Model/Config/Backend/ApiKeyValidator.php index 197aef81..52506cea 100644 --- a/Model/Config/Backend/ApiKeyValidator.php +++ b/Model/Config/Backend/ApiKeyValidator.php @@ -63,7 +63,7 @@ public function beforeSave() if ($value) { if (!$apiKey) { throw new \Magento\Framework\Exception\LocalizedException( - sprintf(__("The api key was not set on the module basic configuration")) + __("The api key was not set on the module basic configuration") ); } @@ -71,7 +71,7 @@ public function beforeSave() if (isset($data['merchant']['status']) && $data['merchant']['status'] != 'active') { throw new \Magento\Framework\Exception\LocalizedException( - sprintf(__("The api key is invalid or the merchant is inactive")) + __("The api key is invalid or the merchant is inactive") ); } } From da953907733778431628c9140698608b129ee083 Mon Sep 17 00:00:00 2001 From: Maico Date: Fri, 26 Jul 2019 17:39:22 -0300 Subject: [PATCH 21/46] =?UTF-8?q?Envia=20valores=20de=20desconto=20e=20acr?= =?UTF-8?q?=C3=A9scimos=20para=20a=20Vindi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Model/Payment/Product.php | 70 ++++++++++++++++++++++++++++++++++----- 1 file changed, 61 insertions(+), 9 deletions(-) diff --git a/Model/Payment/Product.php b/Model/Payment/Product.php index 10b7db10..c8586e0d 100644 --- a/Model/Payment/Product.php +++ b/Model/Payment/Product.php @@ -17,6 +17,7 @@ public function __construct( public function findOrCreateProducts($order) { + $list = []; foreach ($order->getItems() as $item) { $productType = $item->getProduct()->getTypeId(); $vindiProductId = $this->findOrCreateProduct($item->getSku(), $item->getName(), $productType); @@ -27,20 +28,17 @@ public function findOrCreateProducts($order) if (false === $itemPrice) continue; - $list[] = [ + array_push($list, [ 'product_id' => $vindiProductId, 'amount' => $itemPrice - ]; + ]); } } - if ($order->getShippingAmount() > 0) { - $shippingId = $this->findOrCreateProduct('frete', 'frete'); - $list[] = [ - 'product_id' => $shippingId, - 'amount' => $order->getShippingAmount() - ]; - } + $list = $this->buildTax($list, $order); + $list = $this->buildDiscount($list, $order); + $list = $this->buildShipping($list, $order); + return $list; } @@ -52,6 +50,60 @@ private function getItemPrice($item, $productType) return $item->getPrice(); } + /** + * @param array $list + * @param $order + * @return array + */ + private function buildTax(array $list, $order) + { + if ($order->getTaxAmount() > 0) { + $productId = $this->findOrCreateProduct('taxa', 'taxa'); + array_push($list, [ + 'product_id' => $productId, + 'amount' => $order->getTaxAmount() + ]); + } + + return $list; + } + + /** + * @param $list + * @param $order + * @return array + */ + private function buildDiscount(array $list, $order) + { + if ($order->getDiscountAmount() < 0) { + $productId = $this->findOrCreateProduct('cupom', 'cupom'); + array_push($list, [ + 'product_id' => $productId, + 'amount' => $order->getDiscountAmount() + ]); + } + + return $list; + } + + /** + * @param array $list + * @param $order + * @return array + */ + private function buildShipping(array $list, $order) + { + if ($order->getShippingAmount() > 0) { + $productId = $this->findOrCreateProduct('frete', 'frete'); + array_push($list, [ + 'product_id' => $productId, + 'amount' => $order->getShippingAmount() + ]); + } + + return $list; + } + private function findOrCreateProduct($itemSku, $itemName, $itemType = 'simple') { $itemName = $itemType == 'configurable' ? $itemSku : $itemName; From 795c32af57e96099f82eeec7de6d290c756a4ae2 Mon Sep 17 00:00:00 2001 From: Maico da Silva Date: Mon, 29 Jul 2019 09:06:17 -0300 Subject: [PATCH 22/46] Update Model/Payment/Product.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Laerte Guimarães <31661772+laerte-guimaraes@users.noreply.github.com> --- Model/Payment/Product.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Model/Payment/Product.php b/Model/Payment/Product.php index c8586e0d..0118f7fc 100644 --- a/Model/Payment/Product.php +++ b/Model/Payment/Product.php @@ -58,7 +58,7 @@ private function getItemPrice($item, $productType) private function buildTax(array $list, $order) { if ($order->getTaxAmount() > 0) { - $productId = $this->findOrCreateProduct('taxa', 'taxa'); + $productId = $this->findOrCreateProduct('taxa', 'Taxa'); array_push($list, [ 'product_id' => $productId, 'amount' => $order->getTaxAmount() From 021ceccb10af5705a777821088281deaf338912f Mon Sep 17 00:00:00 2001 From: Maico da Silva Date: Mon, 29 Jul 2019 09:06:31 -0300 Subject: [PATCH 23/46] Update Model/Payment/Product.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Laerte Guimarães <31661772+laerte-guimaraes@users.noreply.github.com> --- Model/Payment/Product.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Model/Payment/Product.php b/Model/Payment/Product.php index 0118f7fc..6cb822dd 100644 --- a/Model/Payment/Product.php +++ b/Model/Payment/Product.php @@ -76,7 +76,7 @@ private function buildTax(array $list, $order) private function buildDiscount(array $list, $order) { if ($order->getDiscountAmount() < 0) { - $productId = $this->findOrCreateProduct('cupom', 'cupom'); + $productId = $this->findOrCreateProduct('cupom', 'Cupom de Desconto'); array_push($list, [ 'product_id' => $productId, 'amount' => $order->getDiscountAmount() From 3e0f7841690eea54b7db2d9aaec052f7733c5f02 Mon Sep 17 00:00:00 2001 From: Maico da Silva Date: Tue, 30 Jul 2019 10:51:37 -0300 Subject: [PATCH 24/46] Update Model/Payment/Product.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Laerte Guimarães <31661772+laerte-guimaraes@users.noreply.github.com> --- Model/Payment/Product.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Model/Payment/Product.php b/Model/Payment/Product.php index 6cb822dd..020a4c3c 100644 --- a/Model/Payment/Product.php +++ b/Model/Payment/Product.php @@ -25,7 +25,7 @@ public function findOrCreateProducts($order) for ($i = 0; $i < $item->getQtyOrdered(); $i++) { $itemPrice = $this->getItemPrice($item, $productType); - if (false === $itemPrice) + if (! $itemPrice) continue; array_push($list, [ From 88851a7cd2cefda710a845c99d3bd851d14363c9 Mon Sep 17 00:00:00 2001 From: Yauari Vieira Date: Thu, 15 Aug 2019 17:43:40 -0300 Subject: [PATCH 25/46] Inicio dos testes de cupons, taxas e frete --- Test/Unit/OrderTest.php | 160 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 Test/Unit/OrderTest.php diff --git a/Test/Unit/OrderTest.php b/Test/Unit/OrderTest.php new file mode 100644 index 00000000..20533ecb --- /dev/null +++ b/Test/Unit/OrderTest.php @@ -0,0 +1,160 @@ +objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->customerRepositoryInterface = $this->getMockBuilder(\Magento\Customer\Api\CustomerRepositoryInterface::class)->disableOriginalConstructor()->getMock(); + $this->managerInterface = $this->getMockBuilder(\Magento\Framework\Message\ManagerInterface::class)->disableOriginalConstructor()->getMock(); + } + + public function testOrderWithTax() + { + $vindiProductId = 'taxa'; + $amount = 1.00; + + $order = $this->createOrderMock($amount, 0.00, 0.00); + $list = $this->createVindiProductMock($vindiProductId)->findOrCreateProducts($order); + + $this->makeAssertions($list, $vindiProductId, $amount); + } + + public function testOrderWithDiscount() + { + $vindiProductId = 'cupom'; + $amount = -5.00; + + $order = $this->createOrderMock(0.00, $amount, 0.00); + $list = $this->createVindiProductMock($vindiProductId)->findOrCreateProducts($order); + + $this->makeAssertions($list, $vindiProductId, $amount); + } + + public function testOrderWithShipping() + { + $vindiProductId = 'frete'; + $amount = 10.00; + + $order = $this->createOrderMock(0.00, 0.00, $amount); + $list = $this->createVindiProductMock($vindiProductId)->findOrCreateProducts($order); + + $this->makeAssertions($list, $vindiProductId, $amount); + } + + private function makeAssertions($list, $vindiProductId, $amount) + { + $this->assertContains('fake_sku', $list[0]['product_id'], '', true); + $this->assertEquals('9.99', $list[0]['amount']); + + $this->assertEquals($vindiProductId, $list[1]['product_id']); + $this->assertEquals($amount, $list[1]['amount']); + + return true; + } + + private function createApiMock($desiredTestResponse = null) + { + $apiMock = $this->getMockBuilder(\Vindi\Payment\Model\Payment\Api::class) + ->disableOriginalConstructor() + ->getMock(); + + $apiMock->method('request') + ->willReturn( + [ + 'products' => [ + 0 => [ + 'id' => 'fake_sku_123' + ] + ], + 'product' => [ + 'id' => $desiredTestResponse + ] + ]); + + return $apiMock; + } + + private function createVindiProductMock($desiredTestResponse) + { + $product = $this->objectManager->getObject(\Vindi\Payment\Model\Payment\Product::class, [ + 'customerRepository' => $this->customerRepositoryInterface, + 'api' => $this->createApiMock($desiredTestResponse), + 'messageManager' => $this->managerInterface + ]); + + return $product; + } + + private function createOrderMock( + $orderTaxAmount = 0.00, $orderDiscountAmount = 0.00, $orderShippingAmount = 0.00, + $itemQty = 1, $itemType = 'simple', $itemPrice = 9.99 + ) + { + $orderMock = $this->getMockBuilder(\Magento\Sales\Model\Order::class) + ->disableOriginalConstructor() + ->getMock(); + + $items = [ + $this->createItemMock($itemQty, $itemType, $itemPrice) + ]; + + $orderMock->method('getItems') + ->willReturn($items); + + $orderMock->method('getTaxAmount') + ->willReturn($orderTaxAmount); + + $orderMock->method('getDiscountAmount') + ->willReturn($orderDiscountAmount); + + $orderMock->method('getShippingAmount') + ->willReturn($orderShippingAmount); + + return $orderMock; + } + + private function createItemMock($qty = 1, $type = 'simple', $price = 10.99) + { + $itemMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Item::class) + ->disableOriginalConstructor() + ->getMock(); + + $itemMock->method('getQtyOrdered') + ->willReturn($qty); + + $itemMock->method('getSku') + ->willReturn('FAKE_SKU_'. rand(1000, 10000)); + + $itemMock->method('getName') + ->willReturn('FAKE_NAME_'. rand(1000, 10000)); + + $itemMock->method('getPrice') + ->willReturn($price); + + $itemMock->method('getProduct') + ->willReturn($this->createProductMock($type)); + + return $itemMock; + } + + private function createProductMock($type) + { + $productMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) + ->disableOriginalConstructor() + ->getMock(); + + $productMock->method('getTypeId') + ->willReturn($type); + + return $productMock; + } + +} \ No newline at end of file From d753896ed0418c70f0839c94985664d8e79dd9ec Mon Sep 17 00:00:00 2001 From: Yauari Vieira Date: Fri, 16 Aug 2019 08:40:06 -0300 Subject: [PATCH 26/46] =?UTF-8?q?Corre=C3=A7=C3=B5es=20nos=20mocks=20das?= =?UTF-8?q?=20respostas=20esperadas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Test/Unit/OrderTest.php | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/Test/Unit/OrderTest.php b/Test/Unit/OrderTest.php index 20533ecb..9483831e 100644 --- a/Test/Unit/OrderTest.php +++ b/Test/Unit/OrderTest.php @@ -47,7 +47,7 @@ public function testOrderWithShipping() $list = $this->createVindiProductMock($vindiProductId)->findOrCreateProducts($order); $this->makeAssertions($list, $vindiProductId, $amount); - } + } private function makeAssertions($list, $vindiProductId, $amount) { @@ -66,18 +66,24 @@ private function createApiMock($desiredTestResponse = null) ->disableOriginalConstructor() ->getMock(); + $requestResponses = []; + + $requestResponses[] = [ + 'product' => [ + 'id' => 'fake_sku' + ] + ]; + + $requestResponses[] = [ + 'products' => [ + 0 => [ + 'id' => $desiredTestResponse + ] + ] + ]; + $apiMock->method('request') - ->willReturn( - [ - 'products' => [ - 0 => [ - 'id' => 'fake_sku_123' - ] - ], - 'product' => [ - 'id' => $desiredTestResponse - ] - ]); + ->willReturnOnConsecutiveCalls(false, $requestResponses[0], $requestResponses[1]); return $apiMock; } @@ -131,10 +137,10 @@ private function createItemMock($qty = 1, $type = 'simple', $price = 10.99) ->willReturn($qty); $itemMock->method('getSku') - ->willReturn('FAKE_SKU_'. rand(1000, 10000)); + ->willReturn('FAKE_SKU'); $itemMock->method('getName') - ->willReturn('FAKE_NAME_'. rand(1000, 10000)); + ->willReturn('FAKE_NAME'); $itemMock->method('getPrice') ->willReturn($price); From eeaf8593546df23c83cbb343fae48bfb03652645 Mon Sep 17 00:00:00 2001 From: Yauari Vieira Date: Fri, 16 Aug 2019 12:23:08 -0300 Subject: [PATCH 27/46] Trocar o nome da classe --- Test/Unit/OrderTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Test/Unit/OrderTest.php b/Test/Unit/OrderTest.php index 9483831e..4fb47180 100644 --- a/Test/Unit/OrderTest.php +++ b/Test/Unit/OrderTest.php @@ -1,8 +1,8 @@ Date: Fri, 16 Aug 2019 12:27:24 -0300 Subject: [PATCH 28/46] =?UTF-8?q?Testes=20nas=20mudan=C3=A7as=20de=20statu?= =?UTF-8?q?s=20para=20pedidos=20com=20boletos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Test/Unit/StatusTest.php | 158 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 Test/Unit/StatusTest.php diff --git a/Test/Unit/StatusTest.php b/Test/Unit/StatusTest.php new file mode 100644 index 00000000..8ba9405c --- /dev/null +++ b/Test/Unit/StatusTest.php @@ -0,0 +1,158 @@ +objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + + $this->context = $this->getMockBuilder(\Magento\Framework\App\Helper\Context::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->scopeConfigMock = $this->getMockBuilder(\Magento\Framework\App\Config\ScopeConfigInterface::class) + ->disableOriginalConstructor() + ->getMock(); + } + + public function testGetStatusToOrderCompleteWithNoStatusConfigured() + { + $this->scopeConfigMock->method('getValue') + ->willReturn(null); + + $this->context->method('getScopeConfig') + ->willReturn($this->scopeConfigMock); + + $helper = $this->objectManager->getObject(\Vindi\Payment\Helper\Data::class, [ + 'context' => $this->context + ]); + + $this->assertEquals(Order::STATE_PROCESSING, $helper->getStatusToOrderComplete()); + } + + public function testGetStatusToOrderCompleteWithPendingStatusConfigured() + { + $this->scopeConfigMock->method('getValue') + ->willReturn('pending'); + + $this->context->method('getScopeConfig') + ->willReturn($this->scopeConfigMock); + + $helper = $this->objectManager->getObject(\Vindi\Payment\Helper\Data::class, [ + 'context' => $this->context + ]); + + $this->assertEquals('pending', $helper->getStatusToOrderComplete()); + } + + public function testSetProcessingOrderStatusOnPlaceCreditCard() + { + $helperMock = $this->getMockBuilder(\Vindi\Payment\Helper\Data::class) + ->disableOriginalConstructor() + ->getMock(); + + $helperMock->method('getStatusToOrderComplete') + ->willReturn(Order::STATE_PROCESSING); + + $plugin = $this->objectManager->getObject(\Vindi\Payment\Plugin\SetOrderStatusOnPlace::class, [ + 'helperData' => $helperMock + ]); + + $paymentMock = $this->createPaymentMock(); + $result = $plugin->afterPlace($paymentMock, 'Expected Result'); + + $this->assertEquals('Expected Result', $result); + $this->assertEquals($paymentMock->getOrder()->getState(), 'new'); + $this->assertEquals(Order::STATE_PROCESSING, $paymentMock->getOrder()->getStatus()); + } + + public function testSetPendingOrderStatusOnPlaceCreditCard() + { + $helperMock = $this->getMockBuilder(\Vindi\Payment\Helper\Data::class) + ->disableOriginalConstructor() + ->getMock(); + + $helperMock->method('getStatusToOrderComplete') + ->willReturn('pending'); + + $plugin = $this->objectManager->getObject(\Vindi\Payment\Plugin\SetOrderStatusOnPlace::class, [ + 'helperData' => $helperMock + ]); + + $paymentMock = $this->createPaymentMock(); + $result = $plugin->afterPlace($paymentMock, 'Expected Result'); + + $this->assertEquals('Expected Result', $result); + $this->assertEquals($paymentMock->getOrder()->getState(), 'new'); + $this->assertEquals('pending', $paymentMock->getOrder()->getStatus()); + } + + public function testSetPendingOrderStatusOnPlaceSlip() + { + $helperMock = $this->getMockBuilder(\Vindi\Payment\Helper\Data::class) + ->disableOriginalConstructor() + ->getMock(); + + $helperMock->method('getStatusToOrderComplete') + ->willReturn('pending'); + + $plugin = $this->objectManager->getObject(\Vindi\Payment\Plugin\SetOrderStatusOnPlace::class, [ + 'helperData' => $helperMock + ]); + + $paymentMock = $this->createPaymentMock(); + $result = $plugin->afterPlace($paymentMock, 'Expected Result'); + + $this->assertEquals('Expected Result', $result); + $this->assertEquals($paymentMock->getOrder()->getState(), 'new'); + $this->assertEquals('pending', $paymentMock->getOrder()->getStatus()); + } + + private function createPaymentMock() + { + $paymentMock = $this->getMockBuilder(\Magento\Sales\Model\Order\Payment::class) + ->disableOriginalConstructor() + ->getMock(); + + $paymentMock->method('getOrder') + ->willReturn($this->createOrderMock()); + + $paymentMock->method('getMethod') + ->willReturnOnConsecutiveCalls( + \Vindi\Payment\Model\Payment\Vindi::CODE, + \Vindi\Payment\Model\Payment\Vindi::CODE, + \Vindi\Payment\Model\Payment\BankSlip::CODE + ); + + return $paymentMock; + } + + private function createOrderMock() + { + $orderMock = $this->getMockBuilder(\Magento\Sales\Model\Order::class) + ->disableOriginalConstructor() + ->setMethods(array('getState', 'setState', 'addCommentToStatusHistory')) + ->getMock(); + + $orderMock->method('getState') + ->willReturn('new'); + + $orderMock->method('setState') + ->willReturn($orderMock); + + $orderMock->method('addCommentToStatusHistory') + ->willReturn($orderMock); + + return $orderMock; + } + +} \ No newline at end of file From 36f9a349a1e402245a5bc576b0a1f6d7260db36b Mon Sep 17 00:00:00 2001 From: Yauari Vieira Date: Fri, 16 Aug 2019 14:45:25 -0300 Subject: [PATCH 29/46] Testes nos status dos pedidos de acordo com os meios de pagamento --- Test/Unit/StatusTest.php | 154 ++++++++++++++++++++------------------- 1 file changed, 79 insertions(+), 75 deletions(-) diff --git a/Test/Unit/StatusTest.php b/Test/Unit/StatusTest.php index 8ba9405c..5ddcf59d 100644 --- a/Test/Unit/StatusTest.php +++ b/Test/Unit/StatusTest.php @@ -8,113 +8,124 @@ class StatusTest extends \PHPUnit\Framework\TestCase { protected $objectManager; - protected $context; - protected $scopeConfigMock; + protected $paymentMock; public function setUp() { $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - - $this->context = $this->getMockBuilder(\Magento\Framework\App\Helper\Context::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->scopeConfigMock = $this->getMockBuilder(\Magento\Framework\App\Config\ScopeConfigInterface::class) - ->disableOriginalConstructor() - ->getMock(); + $this->paymentMock = $this->createPaymentMock(); } public function testGetStatusToOrderCompleteWithNoStatusConfigured() { - $this->scopeConfigMock->method('getValue') - ->willReturn(null); - - $this->context->method('getScopeConfig') - ->willReturn($this->scopeConfigMock); - - $helper = $this->objectManager->getObject(\Vindi\Payment\Helper\Data::class, [ - 'context' => $this->context - ]); - - $this->assertEquals(Order::STATE_PROCESSING, $helper->getStatusToOrderComplete()); + $this->assertEquals(Order::STATE_PROCESSING, $this->createHelperObjectManager(null)->getStatusToOrderComplete()); } public function testGetStatusToOrderCompleteWithPendingStatusConfigured() { - $this->scopeConfigMock->method('getValue') - ->willReturn('pending'); - - $this->context->method('getScopeConfig') - ->willReturn($this->scopeConfigMock); + $this->assertEquals('pending', $this->createHelperObjectManager('pending')->getStatusToOrderComplete()); + } - $helper = $this->objectManager->getObject(\Vindi\Payment\Helper\Data::class, [ - 'context' => $this->context - ]); + public function testSetProcessingOrderStatusOnPlaceCreditCard() + { + $this->paymentMock->method('getMethod') + ->willReturn( + \Vindi\Payment\Model\Payment\Vindi::CODE + ); + + $result = $this->createPluginObjectManager(Order::STATE_PROCESSING)->afterPlace($this->paymentMock, 'Expected Result'); - $this->assertEquals('pending', $helper->getStatusToOrderComplete()); + $this->assertEquals('Expected Result', $result); + $this->assertEquals($this->paymentMock->getOrder()->getState(), 'new'); + $this->assertEquals(Order::STATE_PROCESSING, $this->paymentMock->getOrder()->getStatus()); } - public function testSetProcessingOrderStatusOnPlaceCreditCard() + public function testSetPendingOrderStatusOnPlaceCreditCard() { - $helperMock = $this->getMockBuilder(\Vindi\Payment\Helper\Data::class) - ->disableOriginalConstructor() - ->getMock(); + $this->paymentMock->method('getMethod') + ->willReturn( + \Vindi\Payment\Model\Payment\Vindi::CODE + ); - $helperMock->method('getStatusToOrderComplete') - ->willReturn(Order::STATE_PROCESSING); + $result = $this->createPluginObjectManager('pending')->afterPlace($this->paymentMock, 'Expected Result'); - $plugin = $this->objectManager->getObject(\Vindi\Payment\Plugin\SetOrderStatusOnPlace::class, [ - 'helperData' => $helperMock - ]); + $this->assertEquals('Expected Result', $result); + $this->assertEquals($this->paymentMock->getOrder()->getState(), 'new'); + $this->assertEquals('pending', $this->paymentMock->getOrder()->getStatus()); + } + + public function testSetPendingOrderStatusOnPlaceSlip() + { + $this->paymentMock->method('getMethod') + ->willReturn( + \Vindi\Payment\Model\Payment\BankSlip::CODE + ); - $paymentMock = $this->createPaymentMock(); - $result = $plugin->afterPlace($paymentMock, 'Expected Result'); + $result = $this->createPluginObjectManager('pending')->afterPlace($this->paymentMock, 'Expected Result'); $this->assertEquals('Expected Result', $result); - $this->assertEquals($paymentMock->getOrder()->getState(), 'new'); - $this->assertEquals(Order::STATE_PROCESSING, $paymentMock->getOrder()->getStatus()); + $this->assertEquals($this->paymentMock->getOrder()->getState(), 'new'); + $this->assertEquals('pending', $this->paymentMock->getOrder()->getStatus()); } - public function testSetPendingOrderStatusOnPlaceCreditCard() - { - $helperMock = $this->getMockBuilder(\Vindi\Payment\Helper\Data::class) - ->disableOriginalConstructor() - ->getMock(); + public function testSetPendingOrderStatusOnPlaceSlip2() + { + $this->paymentMock->method('getMethod') + ->willReturn( + \Vindi\Payment\Model\Payment\BankSlip::CODE + ); - $helperMock->method('getStatusToOrderComplete') - ->willReturn('pending'); + $result = $this->createPluginObjectManager('other')->afterPlace($this->paymentMock, 'Expected Result'); - $plugin = $this->objectManager->getObject(\Vindi\Payment\Plugin\SetOrderStatusOnPlace::class, [ - 'helperData' => $helperMock - ]); + $this->assertEquals('Expected Result', $result); + $this->assertEquals($this->paymentMock->getOrder()->getState(), 'new'); + $this->assertEquals('pending', $this->paymentMock->getOrder()->getStatus()); + } - $paymentMock = $this->createPaymentMock(); - $result = $plugin->afterPlace($paymentMock, 'Expected Result'); + private function createHelperObjectManager($context) + { + return $this->objectManager->getObject(\Vindi\Payment\Helper\Data::class, [ + 'context' => $this->createContextMock($context) + ]); + } - $this->assertEquals('Expected Result', $result); - $this->assertEquals($paymentMock->getOrder()->getState(), 'new'); - $this->assertEquals('pending', $paymentMock->getOrder()->getStatus()); + private function createPluginObjectManager($status) + { + return $this->objectManager->getObject(\Vindi\Payment\Plugin\SetOrderStatusOnPlace::class, [ + 'helperData' => $this->createHelperMock($status) + ]); } - public function testSetPendingOrderStatusOnPlaceSlip() + private function createHelperMock($statusToOrderComplete) { $helperMock = $this->getMockBuilder(\Vindi\Payment\Helper\Data::class) ->disableOriginalConstructor() ->getMock(); $helperMock->method('getStatusToOrderComplete') - ->willReturn('pending'); + ->willReturn($statusToOrderComplete); + + return $helperMock; + } - $plugin = $this->objectManager->getObject(\Vindi\Payment\Plugin\SetOrderStatusOnPlace::class, [ - 'helperData' => $helperMock - ]); + private function createContextMock($expectedValue) + { + $contextMock = $this->getMockBuilder(\Magento\Framework\App\Helper\Context::class) + ->disableOriginalConstructor() + ->getMock(); + + $scopeConfigMock = $this->getMockBuilder(\Magento\Framework\App\Config\ScopeConfigInterface::class) + ->disableOriginalConstructor() + ->getMock(); - $paymentMock = $this->createPaymentMock(); - $result = $plugin->afterPlace($paymentMock, 'Expected Result'); - $this->assertEquals('Expected Result', $result); - $this->assertEquals($paymentMock->getOrder()->getState(), 'new'); - $this->assertEquals('pending', $paymentMock->getOrder()->getStatus()); + $scopeConfigMock->method('getValue') + ->willReturn($expectedValue); + + $contextMock->method('getScopeConfig') + ->willReturn($scopeConfigMock); + + return $contextMock; } private function createPaymentMock() @@ -126,13 +137,6 @@ private function createPaymentMock() $paymentMock->method('getOrder') ->willReturn($this->createOrderMock()); - $paymentMock->method('getMethod') - ->willReturnOnConsecutiveCalls( - \Vindi\Payment\Model\Payment\Vindi::CODE, - \Vindi\Payment\Model\Payment\Vindi::CODE, - \Vindi\Payment\Model\Payment\BankSlip::CODE - ); - return $paymentMock; } From 6da4ea7787edae46530be77846caef64dfb87c15 Mon Sep 17 00:00:00 2001 From: Yauari Vieira Date: Thu, 22 Aug 2019 14:18:34 -0300 Subject: [PATCH 30/46] Ajustes nos testes para conformidade com PR 55 --- Test/Unit/StatusTest.php | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/Test/Unit/StatusTest.php b/Test/Unit/StatusTest.php index 5ddcf59d..46fbb141 100644 --- a/Test/Unit/StatusTest.php +++ b/Test/Unit/StatusTest.php @@ -37,7 +37,7 @@ public function testSetProcessingOrderStatusOnPlaceCreditCard() $this->assertEquals('Expected Result', $result); $this->assertEquals($this->paymentMock->getOrder()->getState(), 'new'); - $this->assertEquals(Order::STATE_PROCESSING, $this->paymentMock->getOrder()->getStatus()); + $this->assertEquals('pending', $this->paymentMock->getOrder()->getStatus()); } public function testSetPendingOrderStatusOnPlaceCreditCard() @@ -68,20 +68,6 @@ public function testSetPendingOrderStatusOnPlaceSlip() $this->assertEquals('pending', $this->paymentMock->getOrder()->getStatus()); } - public function testSetPendingOrderStatusOnPlaceSlip2() - { - $this->paymentMock->method('getMethod') - ->willReturn( - \Vindi\Payment\Model\Payment\BankSlip::CODE - ); - - $result = $this->createPluginObjectManager('other')->afterPlace($this->paymentMock, 'Expected Result'); - - $this->assertEquals('Expected Result', $result); - $this->assertEquals($this->paymentMock->getOrder()->getState(), 'new'); - $this->assertEquals('pending', $this->paymentMock->getOrder()->getStatus()); - } - private function createHelperObjectManager($context) { return $this->objectManager->getObject(\Vindi\Payment\Helper\Data::class, [ From 135228333b10df940741cabf33e2e564ff4a5978 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laerte=20Guimar=C3=A3es?= <31661772+laerte-guimaraes@users.noreply.github.com> Date: Thu, 29 Aug 2019 13:01:23 -0300 Subject: [PATCH 31/46] =?UTF-8?q?Insere=20informa=C3=A7=C3=B5es=20de=20Tes?= =?UTF-8?q?te?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CONTRIBUTING.md | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0b537532..e4140b00 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,12 +17,9 @@ Nós valorizamos muito as [**contribuições por Pull Requests (PR)**](https://g - **Clareza** - Além de uma boa descrição sobre a motivação e a solução proposta é possível incluir imagens ou animações que demonstrem quaisquer modificações visuais na interface. Exemplo de **Motivação** com uma **Solução Proposta**: -> Motivação - +> #### Motivação > Fazer com que o pedido seja cancelado, caso o pagamento seja reprovado na primeira tentativa (compras avulsas ou primeiro ciclo de uma assinatura), mas atualmente o cliente recebe a informação que o pedido foi registrado com sucesso, e posteriormente recebe a informação de falha no pagamento no Magento. - -> Solução proposta - +> #### Solução proposta > Adicionar o cancelamento automático de faturas na Vindi após a recusa de uma transação no Magento2, exceto: compras via Boleto ou pendente de revisões do Antifraude. - **Foco** - Um PR deve possuir um único objetivo bem definido. Evite mais de um viés (bug-fix, feature, refactoring) no mesmo PR. @@ -58,6 +55,19 @@ Obs.: Gostamos muito do [PSR-1](https://www.php-fig.org/psr/psr-1/) e [PSR-2](ht 4. [Abra um Pull Request](https://help.github.com/articles/using-pull-requests/) com uma motivação e solução proposta bem claras. +## Qualidade do código + +Para garantir o controle da qualidade do código, disponibilizamos alguns testes via [PHPUnit](https://phpunit.de/) em [Test/Unit](https://github.com/vindi/vindi-magento2/tree/master/Test/Unit). + +#### Se você nunca utilizou o composer, seja bem vindo :tada: :smile: [Aqui está o link do composer](https://getcomposer.org/download/), depois instale as dependências do composer.json. + +#### Se você nunca rodou testes funcionais com PHPUnit, seja bem vindo :tada: :smile: [Aqui está o link da documentação oficial](https://phpunit.readthedocs.io/pt_BR/latest). + +### Rodando os Testes + +``` bash +./vendor/bin/phpunit -c dev/tests/unit/phpunit.xml.dist app/code/Vindi/Payment +``` ## Revisão da Comunidade From 4b9ef6f9bd8f4db92d6a0c87231c263ebab157c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laerte=20Guimar=C3=A3es?= <31661772+laerte-guimaraes@users.noreply.github.com> Date: Thu, 29 Aug 2019 13:07:24 -0300 Subject: [PATCH 32/46] Ajusta link de download --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ebccc1d1..d30608be 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ A integração do módulo da Vindi permite criação e gestão de planos e assin #### Via [git](https://github.com) - Vá até o diretório raíz do Magento e adicione o módulo -> `git clone git@github.com:vindi/vindi-magento2.git app/code/Vindi/Payment/` +> `git clone https://github.com/vindi/vindi-magento2.git app/code/Vindi/Payment/` - Atualize os módulos disponíveis do Magento > `bin/magento setup:upgrade` - O módulo **Vindi_Payment** deverá ser exibido na lista de módulos do Magento From d117f48b5bc37fbab75595572530be2af6c1ab2a Mon Sep 17 00:00:00 2001 From: Maico Date: Sat, 23 May 2020 18:45:11 -0300 Subject: [PATCH 33/46] Atualizando o status da assinatura no Magento --- Helper/WebHookHandlers/Subscription.php | 30 +++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/Helper/WebHookHandlers/Subscription.php b/Helper/WebHookHandlers/Subscription.php index a98d65fb..51fb4c37 100644 --- a/Helper/WebHookHandlers/Subscription.php +++ b/Helper/WebHookHandlers/Subscription.php @@ -6,6 +6,7 @@ use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Sales\Api\Data\OrderInterface; use Magento\Sales\Api\OrderRepositoryInterface; +use Magento\Sales\Model\OrderFactory; use Psr\Log\LoggerInterface; /** @@ -26,21 +27,28 @@ class Subscription * @var SearchCriteriaBuilder */ private $searchCriteriaBuilder; + /** + * @var OrderFactory + */ + private $orderFactory; /** * Subscription constructor. * @param OrderRepositoryInterface $orderRepository * @param SearchCriteriaBuilder $searchCriteriaBuilder + * @param OrderFactory $orderFactory * @param LoggerInterface $logger */ public function __construct( OrderRepositoryInterface $orderRepository, SearchCriteriaBuilder $searchCriteriaBuilder, + OrderFactory $orderFactory, LoggerInterface $logger ) { $this->logger = $logger; $this->orderRepository = $orderRepository; $this->searchCriteriaBuilder = $searchCriteriaBuilder; + $this->orderFactory = $orderFactory; } /** @@ -62,6 +70,7 @@ public function created($data) /** * @param $data * @return bool + * @throws Exception */ public function canceled($data) { @@ -72,6 +81,8 @@ public function canceled($data) $order->addCommentToStatusHistory(__('The subscription was canceled')->getText()); $this->orderRepository->save($order); + $this->cancel($order->getIncrementId()); + return true; } @@ -114,4 +125,23 @@ private function getOrder($incrementId) return false; } + + /** + * @param $incrementId + * @throws Exception + */ + private function cancel($incrementId) + { + $orderFactory = $this->orderFactory->create(); + $order = $orderFactory->loadByIncrementId($incrementId); + + $order->cancel(); + + if (!$order->canCancel()) { + $order->setState(\Magento\Sales\Model\Order::STATE_CLOSED) + ->setStatus(\Magento\Sales\Model\Order::STATE_CLOSED); + } + + $order->save(); + } } From 981ef7b826e58523fd52571f0328e929d754bba1 Mon Sep 17 00:00:00 2001 From: Tharssis Araujo Date: Tue, 4 Jan 2022 10:05:00 -0300 Subject: [PATCH 34/46] Vdk9LYXc | 3kcRcQOr - Exibir metodo de pagamento Pix no Magento --- Model/Payment/AbstractMethod.php | 83 ++++++++++++-- Model/Payment/PaymentMethod.php | 30 ++++- Model/Payment/Pix.php | 108 ++++++++++++++++++ etc/adminhtml/system.xml | 13 +++ etc/config.xml | 11 +- etc/payment.xml | 6 +- i18n/pt_BR.csv | 1 + view/frontend/layout/checkout_index_index.xml | 4 + view/frontend/templates/info/pix.phtml | 10 ++ .../view/payment/method-renderer/vindi-pix.js | 18 +++ view/frontend/web/js/view/payment/vindi.js | 6 +- .../web/template/payment/vindi-pix.html | 46 ++++++++ 12 files changed, 320 insertions(+), 16 deletions(-) create mode 100644 Model/Payment/Pix.php create mode 100644 view/frontend/templates/info/pix.phtml create mode 100644 view/frontend/web/js/view/payment/method-renderer/vindi-pix.js create mode 100644 view/frontend/web/template/payment/vindi-pix.html diff --git a/Model/Payment/AbstractMethod.php b/Model/Payment/AbstractMethod.php index e231d8e0..045c8e9a 100644 --- a/Model/Payment/AbstractMethod.php +++ b/Model/Payment/AbstractMethod.php @@ -2,6 +2,7 @@ namespace Vindi\Payment\Model\Payment; + use Magento\Framework\Api\AttributeValueFactory; use Magento\Framework\Api\ExtensionAttributesFactory; use Magento\Framework\App\Config\ScopeConfigInterface; @@ -23,11 +24,14 @@ use Vindi\Payment\Api\PlanManagementInterface; use Vindi\Payment\Api\ProductManagementInterface; use Vindi\Payment\Api\SubscriptionInterface; +use Magento\Payment\Model\Method\AbstractMethod as OriginAbstractMethod; +use Vindi\Payment\Helper\Api; -abstract class AbstractMethod extends \Magento\Payment\Model\Method\AbstractMethod +abstract class AbstractMethod extends OriginAbstractMethod { + /** - * @var \Vindi\Payment\Helper\Api + * @var Api */ protected $api; @@ -65,23 +69,51 @@ abstract class AbstractMethod extends \Magento\Payment\Model\Method\AbstractMeth * @var TimezoneInterface */ protected $date; + /** * @var ProductManagementInterface */ private $productManagement; + /** * @var \Vindi\Payment\Helper\Data */ private $helperData; + /** * @var PlanManagementInterface */ private $planManagement; + /** * @var SubscriptionInterface */ private $subscriptionRepository; + /** + * @param Context $context + * @param Registry $registry + * @param ExtensionAttributesFactory $extensionFactory + * @param AttributeValueFactory $customAttributeFactory + * @param Data $paymentData + * @param ScopeConfigInterface $scopeConfig + * @param Logger $logger + * @param Api $api + * @param InvoiceService $invoiceService + * @param Customer $customer + * @param ProductManagementInterface $productManagement + * @param PlanManagementInterface $planManagement + * @param SubscriptionInterface $subscriptionRepository + * @param Bill $bill + * @param Profile $profile + * @param PaymentMethod $paymentMethod + * @param LoggerInterface $psrLogger + * @param TimezoneInterface $date + * @param \Vindi\Payment\Helper\Data $helperData + * @param AbstractResource|null $resource + * @param AbstractDb|null $resourceCollection + * @param array $data + */ public function __construct( Context $context, Registry $registry, @@ -90,7 +122,7 @@ public function __construct( Data $paymentData, ScopeConfigInterface $scopeConfig, Logger $logger, - \Vindi\Payment\Helper\Api $api, + Api $api, InvoiceService $invoiceService, Customer $customer, ProductManagementInterface $productManagement, @@ -206,6 +238,7 @@ public function capture(InfoInterface $payment, $amount) /** * @param \Magento\Framework\DataObject|InfoInterface $payment * @param float $amount + * * @throws LocalizedException * @return $this|string */ @@ -346,20 +379,50 @@ protected function handleBankSplitAdditionalInformation(InfoInterface $payment, /** * @param array $body * @param $bill + * * @return bool */ private function successfullyPaid(array $body, $bill) { - if ( - $body['payment_method_code'] === PaymentMethod::BANK_SLIP - || $body['payment_method_code'] === PaymentMethod::DEBIT_CARD - || $bill['status'] === Bill::PAID_STATUS - || $bill['status'] === Bill::REVIEW_STATUS - || reset($bill['charges'])['status'] === Bill::FRAUD_REVIEW_STATUS - ) { + if ($this->isValidPaymentMethodCode($body['payment_method_code']) || $this->isValidStatus($bill)) { return true; } return false; } + + /** + * @param $paymentMethodCode + * + * @return bool + */ + protected function isValidPaymentMethodCode($paymentMethodCode) + { + $paymentMethodsCode = [ + PaymentMethod::BANK_SLIP, + PaymentMethod::DEBIT_CARD, + PaymentMethod::PIX + ]; + + return in_array($paymentMethodCode , $paymentMethodsCode); + } + + /** + * @param $bill + * + * @return bool + */ + protected function isValidStatus($bill) + { + if (!$bill) return false; + + $billStatus = [ + Bill::PAID_STATUS, + Bill::REVIEW_STATUS + ]; + + $chargeStatus = reset($bill['charges'])['status'] === Bill::FRAUD_REVIEW_STATUS; + + return in_array($bill['status'], $billStatus) || $chargeStatus; + } } diff --git a/Model/Payment/PaymentMethod.php b/Model/Payment/PaymentMethod.php index 68a8f421..32f50485 100644 --- a/Model/Payment/PaymentMethod.php +++ b/Model/Payment/PaymentMethod.php @@ -2,22 +2,34 @@ namespace Vindi\Payment\Model\Payment; + +use Exception; +use Vindi\Payment\Helper\Api; + class PaymentMethod { + const BANK_SLIP = 'bank_slip'; + const PIX = 'pix'; const CREDIT_CARD = 'credit_card'; const DEBIT_CARD = 'debit_card'; + /** * @var \Vindi\Payment\Helper\Api */ private $api; - public function __construct(\Vindi\Payment\Helper\Api $api, \Magento\Payment\Model\CcConfig $ccConfig) + /** + * @param Api $api + */ + public function __construct(Api $api) { $this->api = $api; - $this->ccConfig = $ccConfig; } + /** + * @return array + */ public function getCreditCardTypes() { $methods = $this->get(); @@ -76,6 +88,12 @@ public function get() return $paymentMethods; } + /** + * @param $ccType + * + * @return bool + * @throws Exception + */ public function isCcTypeValid($ccType) { $validCreditCardTypes = $this->getCreditCardTypes(); @@ -93,6 +111,12 @@ public function isCcTypeValid($ccType) return false; } + /** + * @param $ccType + * + * @return mixed + * @throws Exception + */ private function getCcTypeFullName($ccType) { $fullNames = $this->getCreditCardTypes(); @@ -101,6 +125,6 @@ private function getCcTypeFullName($ccType) return $fullNames[$ccType]; } - throw new \Exception(__("Could Not Find Payment Credit Card Type")->getText()); + throw new Exception(__("Could Not Find Payment Credit Card Type")->getText()); } } diff --git a/Model/Payment/Pix.php b/Model/Payment/Pix.php new file mode 100644 index 00000000..caef9b2f --- /dev/null +++ b/Model/Payment/Pix.php @@ -0,0 +1,108 @@ +getInfoInstance(); + $info->setAdditionalInformation('installments', 1); + $info->save(); + + parent::assignData($data); + + return $this; + } + + /** + * @return string + */ + protected function getPaymentMethodCode() + { + return PaymentMethod::PIX; + } +} diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml index efa9b896..e39da97b 100644 --- a/etc/adminhtml/system.xml +++ b/etc/adminhtml/system.xml @@ -34,6 +34,19 @@ Magento\Config\Model\Config\Source\Yesno + + + + + Magento\Config\Model\Config\Source\Yesno + Vindi\Payment\Model\Config\Backend\ApiKeyValidator + + + + + - + @@ -19,6 +20,14 @@ authorize offline + + 0 + Vindi\Payment\Model\Payment\Pix + Vindi - Pix + 0 + authorize + offline + diff --git a/etc/payment.xml b/etc/payment.xml index 9dd6783a..6bd05360 100644 --- a/etc/payment.xml +++ b/etc/payment.xml @@ -1,5 +1,6 @@ - + @@ -12,5 +13,8 @@ 0 + + 0 + diff --git a/i18n/pt_BR.csv b/i18n/pt_BR.csv index 9d8a900d..3785bef3 100644 --- a/i18n/pt_BR.csv +++ b/i18n/pt_BR.csv @@ -72,6 +72,7 @@ "Print Url: %s","Imprimir: %s" "Print your Bankslip","Imprimir Boleto" "The bank slip will be sent to your e-mail.","O boleto bancário será enviado para o seu e-mail." +"Payment data will be displayed after placing the order.","Os dados para o pagamento, serão exibidos após finalizar o pedido." "indefinitely", "por tempo indefinido" "%1 times", "%1 vezes" "1 time", "1 vez" diff --git a/view/frontend/layout/checkout_index_index.xml b/view/frontend/layout/checkout_index_index.xml index 251859bf..cfbe52ea 100644 --- a/view/frontend/layout/checkout_index_index.xml +++ b/view/frontend/layout/checkout_index_index.xml @@ -30,6 +30,10 @@ false + + false + + diff --git a/view/frontend/templates/info/pix.phtml b/view/frontend/templates/info/pix.phtml new file mode 100644 index 00000000..e352ae87 --- /dev/null +++ b/view/frontend/templates/info/pix.phtml @@ -0,0 +1,10 @@ +canShowBankslipInfo()) : ?> +
+
escapeHtml($block->getMethod()->getTitle()) ?>
+
+
+

getPrintUrl() . '">'. $block->getPrintUrl() . '') ?>

+
+
+
+ diff --git a/view/frontend/web/js/view/payment/method-renderer/vindi-pix.js b/view/frontend/web/js/view/payment/method-renderer/vindi-pix.js new file mode 100644 index 00000000..6e4e4146 --- /dev/null +++ b/view/frontend/web/js/view/payment/method-renderer/vindi-pix.js @@ -0,0 +1,18 @@ +define( + [ + 'underscore', + 'Magento_Checkout/js/view/payment/default', + 'mage/translate', + 'jquery', + 'mageUtils' + ], + function (_, Component, $t, $, utils) { + 'use strict'; + return Component.extend({ + defaults: { + template: 'Vindi_Payment/payment/vindi-pix' + } + }); + } +); + diff --git a/view/frontend/web/js/view/payment/vindi.js b/view/frontend/web/js/view/payment/vindi.js index 3d859ceb..2f19c67e 100644 --- a/view/frontend/web/js/view/payment/vindi.js +++ b/view/frontend/web/js/view/payment/vindi.js @@ -16,8 +16,12 @@ define( { type: 'vindi_bankslip', component: 'Vindi_Payment/js/view/payment/method-renderer/vindi-bankslip' + }, + { + type: 'vindi_pix', + component: 'Vindi_Payment/js/view/payment/method-renderer/vindi-pix' } ); return Component.extend({}); } -); \ No newline at end of file +); diff --git a/view/frontend/web/template/payment/vindi-pix.html b/view/frontend/web/template/payment/vindi-pix.html new file mode 100644 index 00000000..66e68cba --- /dev/null +++ b/view/frontend/web/template/payment/vindi-pix.html @@ -0,0 +1,46 @@ + +
+
+ + +
+
+ + + +
+ + + +
+
+
+ + + +
+
+
+ +
+
+
+
From e54f4389a09d17451a8effbc2c84ff3d54de5811 Mon Sep 17 00:00:00 2001 From: Tharssis Araujo Date: Thu, 13 Jan 2022 14:46:03 -0300 Subject: [PATCH 35/46] DgJyEhpZ | Renderizar Qrcode --- Api/ConfigurationInterface.php | 20 +++++ Block/Onepage/Pix.php | 81 +++++++++++++++++++ Helper/Configuration.php | 21 +++++ Model/Payment/AbstractMethod.php | 6 ++ etc/adminhtml/system.xml | 14 +++- etc/config.xml | 5 ++ etc/di.xml | 9 ++- .../layout/checkout_onepage_success.xml | 9 ++- view/frontend/templates/onepage/pix.phtml | 30 +++++++ view/frontend/web/css/pix.css | 4 + 10 files changed, 193 insertions(+), 6 deletions(-) create mode 100644 Api/ConfigurationInterface.php create mode 100644 Block/Onepage/Pix.php create mode 100644 Helper/Configuration.php create mode 100644 view/frontend/templates/onepage/pix.phtml create mode 100644 view/frontend/web/css/pix.css diff --git a/Api/ConfigurationInterface.php b/Api/ConfigurationInterface.php new file mode 100644 index 00000000..7f9150d2 --- /dev/null +++ b/Api/ConfigurationInterface.php @@ -0,0 +1,20 @@ +checkoutSession = $checkoutSession; + $this->configuration = $configuration; + } + + /** + * @return bool + */ + public function canShowPix() + { + return $this->getOrder()->getPayment()->getMethod() === \Vindi\Payment\Model\Payment\Pix::CODE; + } + + /** + * @return string[] + */ + public function getQrCodePix() + { + return $this->getOrder()->getPayment()->getAdditionalInformation('qrcode_path'); + } + + /** + * @return string + */ + public function getQrCodeWarningMessage() + { + return $this->configuration->getQrCodeWarningMessage(); + } + + /** + * @return string[] + */ + public function getQrcodeOriginalPath() + { + return $this->getOrder()->getPayment()->getAdditionalInformation('qrcode_original_path'); + } + + /** + * @return \Magento\Sales\Model\Order + */ + protected function getOrder(): Order + { + return $this->checkoutSession->getLastRealOrder(); + } +} diff --git a/Helper/Configuration.php b/Helper/Configuration.php new file mode 100644 index 00000000..b91ce7e6 --- /dev/null +++ b/Helper/Configuration.php @@ -0,0 +1,21 @@ +scopeConfig->getValue(static::PATH_QR_CODE_WARNING_MESSAGE, $scopeType, $scopeCode); + return $result ?: ''; + } +} diff --git a/Model/Payment/AbstractMethod.php b/Model/Payment/AbstractMethod.php index 045c8e9a..ea2267b9 100644 --- a/Model/Payment/AbstractMethod.php +++ b/Model/Payment/AbstractMethod.php @@ -374,6 +374,12 @@ protected function handleBankSplitAdditionalInformation(InfoInterface $payment, $payment->setAdditionalInformation('print_url', $bill['charges'][0]['print_url']); $payment->setAdditionalInformation('due_at', $bill['charges'][0]['due_at']); } + + if ($body['payment_method_code'] === PaymentMethod::PIX) { + $payment->setAdditionalInformation('qrcode_original_path', $bill['charges'][0]['last_transaction']['gateway_response_fields']['qrcode_original_path']); + $payment->setAdditionalInformation('qrcode_path', $bill['charges'][0]['last_transaction']['gateway_response_fields']['qrcode_path']); + $payment->setAdditionalInformation('due_at', $bill['charges'][0]['due_at']); + } } /** diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml index e39da97b..a89faede 100644 --- a/etc/adminhtml/system.xml +++ b/etc/adminhtml/system.xml @@ -1,6 +1,7 @@ +
@@ -65,8 +66,7 @@ -
+
vindi Vindi_Payment::config_vindi_payment @@ -96,5 +96,15 @@
+ +
+ + + + + Message if the qr code is not resized. + + +
diff --git a/etc/config.xml b/etc/config.xml index 3e39b4c3..06d49743 100644 --- a/etc/config.xml +++ b/etc/config.xml @@ -36,5 +36,10 @@ pending + + + Seu navegador não da suporte a renderização do QRCode. Use o código do PIX para realizar o pagamento ou acesse o link abaixo para acessar o QR Code + + diff --git a/etc/di.xml b/etc/di.xml index ab49cde8..e382dc67 100644 --- a/etc/di.xml +++ b/etc/di.xml @@ -1,22 +1,25 @@ - + + - - + + vindi_subscription Vindi\Payment\Model\ResourceModel\Subscription\Collection + diff --git a/view/frontend/layout/checkout_onepage_success.xml b/view/frontend/layout/checkout_onepage_success.xml index e8882a25..c072b30a 100644 --- a/view/frontend/layout/checkout_onepage_success.xml +++ b/view/frontend/layout/checkout_onepage_success.xml @@ -1,8 +1,15 @@ - + + + + + + + diff --git a/view/frontend/templates/onepage/pix.phtml b/view/frontend/templates/onepage/pix.phtml new file mode 100644 index 00000000..eda4a14f --- /dev/null +++ b/view/frontend/templates/onepage/pix.phtml @@ -0,0 +1,30 @@ + + +canShowPix()) : ?> +
+ + getQrCodeWarningMessage() ?> + + +
+ + diff --git a/view/frontend/web/css/pix.css b/view/frontend/web/css/pix.css new file mode 100644 index 00000000..4ed406c3 --- /dev/null +++ b/view/frontend/web/css/pix.css @@ -0,0 +1,4 @@ +.qr-code { + width: 200px; + height: 200px; +} From abaaa14ad3520fd276ef3b638ac7e8a647a3f9a5 Mon Sep 17 00:00:00 2001 From: Tharssis Araujo Date: Mon, 17 Jan 2022 15:29:13 -0300 Subject: [PATCH 36/46] =?UTF-8?q?BU12Gcwm=20|=20Criar=20op=C3=A7=C3=A3o=20?= =?UTF-8?q?de=20copiar=20e=20colar=20c=C3=B3digo=20Pix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Block/Onepage/Pix.php | 17 +++++++-- i18n/pt_BR.csv | 4 +++ .../layout/checkout_onepage_success.xml | 2 +- view/frontend/templates/onepage/pix.phtml | 29 ++++++++++----- .../frontend/web/js/view/onepage/vindi-pix.js | 35 +++++++++++++++++++ .../web/template/onepage/vindi-pix.html | 10 ++++++ 6 files changed, 85 insertions(+), 12 deletions(-) create mode 100644 view/frontend/web/js/view/onepage/vindi-pix.js create mode 100644 view/frontend/web/template/onepage/vindi-pix.html diff --git a/Block/Onepage/Pix.php b/Block/Onepage/Pix.php index d2c0a80b..61dcc79a 100644 --- a/Block/Onepage/Pix.php +++ b/Block/Onepage/Pix.php @@ -4,6 +4,7 @@ use Magento\Checkout\Model\Session; +use Magento\Framework\Serialize\Serializer\Json; use Magento\Framework\View\Element\Template; use Magento\Framework\View\Element\Template\Context; use Magento\Sales\Model\Order; @@ -23,20 +24,28 @@ class Pix extends Template protected $configuration; /** + * @var Json + */ + protected $json; + + /** + * @param ConfigurationInterface $configuration * @param Session $checkoutSession * @param Context $context - * @param ConfigurationInterface $configuration + * @param Json $json * @param array $data */ public function __construct( ConfigurationInterface $configuration, Session $checkoutSession, Context $context, + Json $json, array $data = [] ) { parent::__construct($context, $data); $this->checkoutSession = $checkoutSession; $this->configuration = $configuration; + $this->json = $json; } /** @@ -64,11 +73,13 @@ public function getQrCodeWarningMessage() } /** - * @return string[] + * @return bool|string */ public function getQrcodeOriginalPath() { - return $this->getOrder()->getPayment()->getAdditionalInformation('qrcode_original_path'); + + $qrcodeOriginalPath = $this->getOrder()->getPayment()->getAdditionalInformation('qrcode_original_path'); + return $this->json->serialize($qrcodeOriginalPath); } /** diff --git a/i18n/pt_BR.csv b/i18n/pt_BR.csv index 3785bef3..8eb5be7f 100644 --- a/i18n/pt_BR.csv +++ b/i18n/pt_BR.csv @@ -118,3 +118,7 @@ "You canceled the Subscription.","Você cancelou a assinatura." "Vindi Plan","Plano Vindi" "Create New Plan","Criar Novo Plano" +"Open QR Code","Abrir QR Code" +"QR Code warning message","Mensagem de aviso QR Code" +"Message if the qr code is not resized.","Mensagem se o QR Code não for redimensionado." +"Copy QR Code key","Copiar chave QR Code" diff --git a/view/frontend/layout/checkout_onepage_success.xml b/view/frontend/layout/checkout_onepage_success.xml index c072b30a..d896c68c 100644 --- a/view/frontend/layout/checkout_onepage_success.xml +++ b/view/frontend/layout/checkout_onepage_success.xml @@ -9,7 +9,7 @@ - +
diff --git a/view/frontend/templates/onepage/pix.phtml b/view/frontend/templates/onepage/pix.phtml index eda4a14f..ea6f4c62 100644 --- a/view/frontend/templates/onepage/pix.phtml +++ b/view/frontend/templates/onepage/pix.phtml @@ -7,6 +7,7 @@ use Vindi\Payment\Block\Onepage\Pix; canShowPix()) : ?>
+ getQrCodeWarningMessage() ?>
- + +
+ +
+ + + diff --git a/view/frontend/web/js/view/onepage/vindi-pix.js b/view/frontend/web/js/view/onepage/vindi-pix.js new file mode 100644 index 00000000..51c50fda --- /dev/null +++ b/view/frontend/web/js/view/onepage/vindi-pix.js @@ -0,0 +1,35 @@ +define( + [ + 'jquery', + 'uiComponent' + ], + function ($, Component) { + 'use strict'; + + const elemVindiPixButtonCopy = '.vindi-pix-button-copy'; + + return Component.extend({ + defaults: { + template: 'Vindi_Payment/onepage/vindi-pix' + }, + + /** @inheritdoc */ + initialize: function () { + this._super(); + }, + + copyQrCodeKey: function () { + const value = this?.qrCodeKey; + + navigator.clipboard.writeText(value).then(function() { + //@todo application condition frontend + console.log("success", value); + }, function() { + //@todo application condition frontend + console.log("fail"); + }); + } + }); + } +); + diff --git a/view/frontend/web/template/onepage/vindi-pix.html b/view/frontend/web/template/onepage/vindi-pix.html new file mode 100644 index 00000000..5728894c --- /dev/null +++ b/view/frontend/web/template/onepage/vindi-pix.html @@ -0,0 +1,10 @@ + + +
+ +
From 325e6806d1a7d0b662ceedb5c6860d32c65c2538 Mon Sep 17 00:00:00 2001 From: Tharssis Araujo Date: Wed, 19 Jan 2022 13:36:45 -0300 Subject: [PATCH 37/46] updated class name configuration --- ...Interface.php => PixConfigurationInterface.php} | 2 +- Block/Onepage/Pix.php | 14 +++++++------- Helper/{Configuration.php => PixConfiguration.php} | 4 ++-- etc/di.xml | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) rename Api/{ConfigurationInterface.php => PixConfigurationInterface.php} (91%) rename Helper/{Configuration.php => PixConfiguration.php} (77%) diff --git a/Api/ConfigurationInterface.php b/Api/PixConfigurationInterface.php similarity index 91% rename from Api/ConfigurationInterface.php rename to Api/PixConfigurationInterface.php index 7f9150d2..689e2115 100644 --- a/Api/ConfigurationInterface.php +++ b/Api/PixConfigurationInterface.php @@ -5,7 +5,7 @@ use Magento\Store\Model\ScopeInterface; -interface ConfigurationInterface +interface PixConfigurationInterface { const PATH_QR_CODE_WARNING_MESSAGE = 'checkout/vindi_pix/qr-code-warning-message'; diff --git a/Block/Onepage/Pix.php b/Block/Onepage/Pix.php index 61dcc79a..25721622 100644 --- a/Block/Onepage/Pix.php +++ b/Block/Onepage/Pix.php @@ -8,7 +8,7 @@ use Magento\Framework\View\Element\Template; use Magento\Framework\View\Element\Template\Context; use Magento\Sales\Model\Order; -use Vindi\Payment\Api\ConfigurationInterface; +use Vindi\Payment\Api\PixConfigurationInterface; class Pix extends Template { @@ -19,9 +19,9 @@ class Pix extends Template protected $checkoutSession; /** - * @var ConfigurationInterface + * @var PixConfigurationInterface */ - protected $configuration; + protected $pixConfiguration; /** * @var Json @@ -29,14 +29,14 @@ class Pix extends Template protected $json; /** - * @param ConfigurationInterface $configuration + * @param PixConfigurationInterface $pixConfiguration * @param Session $checkoutSession * @param Context $context * @param Json $json * @param array $data */ public function __construct( - ConfigurationInterface $configuration, + PixConfigurationInterface $pixConfiguration, Session $checkoutSession, Context $context, Json $json, @@ -44,7 +44,7 @@ public function __construct( ) { parent::__construct($context, $data); $this->checkoutSession = $checkoutSession; - $this->configuration = $configuration; + $this->pixConfiguration = $pixConfiguration; $this->json = $json; } @@ -69,7 +69,7 @@ public function getQrCodePix() */ public function getQrCodeWarningMessage() { - return $this->configuration->getQrCodeWarningMessage(); + return $this->pixConfiguration->getQrCodeWarningMessage(); } /** diff --git a/Helper/Configuration.php b/Helper/PixConfiguration.php similarity index 77% rename from Helper/Configuration.php rename to Helper/PixConfiguration.php index b91ce7e6..572758a7 100644 --- a/Helper/Configuration.php +++ b/Helper/PixConfiguration.php @@ -4,10 +4,10 @@ use Magento\Store\Model\ScopeInterface; -use Vindi\Payment\Api\ConfigurationInterface; +use Vindi\Payment\Api\PixConfigurationInterface; use Magento\Framework\App\Helper\AbstractHelper; -class Configuration extends AbstractHelper implements ConfigurationInterface +class PixConfiguration extends AbstractHelper implements PixConfigurationInterface { /** diff --git a/etc/di.xml b/etc/di.xml index e382dc67..10ae0399 100644 --- a/etc/di.xml +++ b/etc/di.xml @@ -11,7 +11,7 @@ - + From c45361ea7629397f234f3a2b7aedc12f25b2d870 Mon Sep 17 00:00:00 2001 From: Tharssis Araujo Date: Fri, 21 Jan 2022 09:55:18 -0300 Subject: [PATCH 38/46] =?UTF-8?q?PViog04y=20|=20Ajustar=20as=20mensagens?= =?UTF-8?q?=20das=20p=C3=A1ginas=20de=20Checkout=20para=20o=20PIX?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Api/PixConfigurationInterface.php | 18 ++++++++ Block/Onepage/Pix.php | 9 +++- Helper/PixConfiguration.php | 18 ++++++++ Model/Pix/ConfigProvider.php | 44 +++++++++++++++++++ etc/adminhtml/system.xml | 8 ++++ etc/config.xml | 4 +- etc/frontend/di.xml | 6 ++- etc/module.xml | 4 +- i18n/pt_BR.csv | 6 ++- view/frontend/templates/onepage/pix.phtml | 36 ++++++++------- .../view/payment/method-renderer/vindi-pix.js | 5 +++ .../web/template/onepage/vindi-pix.html | 10 ++++- .../web/template/payment/vindi-pix.html | 2 +- 13 files changed, 145 insertions(+), 25 deletions(-) create mode 100644 Model/Pix/ConfigProvider.php diff --git a/Api/PixConfigurationInterface.php b/Api/PixConfigurationInterface.php index 689e2115..66851055 100644 --- a/Api/PixConfigurationInterface.php +++ b/Api/PixConfigurationInterface.php @@ -8,8 +8,26 @@ interface PixConfigurationInterface { + const PATH_INFO_MESSAGE = 'checkout/vindi_pix/info_message'; + const PATH_INFO_MESSAGE_ONEPAGE_SUCCESS = 'checkout/vindi_pix/info_message_onepage_success'; const PATH_QR_CODE_WARNING_MESSAGE = 'checkout/vindi_pix/qr-code-warning-message'; + /** + * @param string $scopeType + * @param string|null $scopeCode + * + * @return string + */ + public function getInfoMessage(string $scopeType = ScopeInterface::SCOPE_STORE, string $scopeCode = null); + + /** + * @param string $scopeType + * @param string|null $scopeCode + * + * @return string + */ + public function getInfoMessageOnepageSuccess(string $scopeType = ScopeInterface::SCOPE_STORE, string $scopeCode = null); + /** * @param string $scopeType * @param string|null $scopeCode diff --git a/Block/Onepage/Pix.php b/Block/Onepage/Pix.php index 25721622..f8ee56af 100644 --- a/Block/Onepage/Pix.php +++ b/Block/Onepage/Pix.php @@ -72,12 +72,19 @@ public function getQrCodeWarningMessage() return $this->pixConfiguration->getQrCodeWarningMessage(); } + /** + * @return string + */ + public function getInfoMessageOnepageSuccess() + { + return $this->pixConfiguration->getInfoMessageOnepageSuccess(); + } + /** * @return bool|string */ public function getQrcodeOriginalPath() { - $qrcodeOriginalPath = $this->getOrder()->getPayment()->getAdditionalInformation('qrcode_original_path'); return $this->json->serialize($qrcodeOriginalPath); } diff --git a/Helper/PixConfiguration.php b/Helper/PixConfiguration.php index 572758a7..329f007a 100644 --- a/Helper/PixConfiguration.php +++ b/Helper/PixConfiguration.php @@ -10,6 +10,24 @@ class PixConfiguration extends AbstractHelper implements PixConfigurationInterface { + /** + * @inheritDoc + */ + public function getInfoMessage(string $scopeType = ScopeInterface::SCOPE_STORE, string $scopeCode = null) + { + $result = $this->scopeConfig->getValue(static::PATH_INFO_MESSAGE, $scopeType, $scopeCode); + return $result ?: ''; + } + + /** + * @inheritDoc + */ + public function getInfoMessageOnepageSuccess(string $scopeType = ScopeInterface::SCOPE_STORE, string $scopeCode = null) + { + $result = $this->scopeConfig->getValue(static::PATH_INFO_MESSAGE_ONEPAGE_SUCCESS, $scopeType, $scopeCode); + return $result ?: ''; + } + /** * @inheritDoc */ diff --git a/Model/Pix/ConfigProvider.php b/Model/Pix/ConfigProvider.php new file mode 100644 index 00000000..f28e32dc --- /dev/null +++ b/Model/Pix/ConfigProvider.php @@ -0,0 +1,44 @@ +pixConfiguration = $pixConfiguration; + } + + /** + * {@inheritdoc} + */ + public function getConfig() + { + return [ + 'payment' => [ + 'vindi_pix' => [ + 'info_message' => $this->pixConfiguration->getInfoMessage(), + ] + ] + ]; + } +} diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml index a89faede..5fffa1a0 100644 --- a/etc/adminhtml/system.xml +++ b/etc/adminhtml/system.xml @@ -100,6 +100,14 @@
+ + + Message when selecting the payment method on the checkout screen. + + + + Message that will be presented to the customer on the success screen, after completing the order. + Message if the qr code is not resized. diff --git a/etc/config.xml b/etc/config.xml index 06d49743..6163b745 100644 --- a/etc/config.xml +++ b/etc/config.xml @@ -38,7 +38,9 @@ - Seu navegador não da suporte a renderização do QRCode. Use o código do PIX para realizar o pagamento ou acesse o link abaixo para acessar o QR Code + Os dados para o pagamento, serão exibidos após finalizar o pedido. + Seu pedido foi concluído, abaixo segue as informações do PIX para realizar o pagamento. + Seu navegador não da suporte a renderização do QRCode. Use o código do PIX para realizar o pagamento ou acesse o link abaixo para acessar o QR Code. diff --git a/etc/frontend/di.xml b/etc/frontend/di.xml index 957dab45..0f26c252 100644 --- a/etc/frontend/di.xml +++ b/etc/frontend/di.xml @@ -1,10 +1,12 @@ - + Vindi\Payment\Model\ConfigProvider + Vindi\Payment\Model\Pix\ConfigProvider - \ No newline at end of file + diff --git a/etc/module.xml b/etc/module.xml index cf6d3d03..c79c5720 100644 --- a/etc/module.xml +++ b/etc/module.xml @@ -1,9 +1,11 @@ - + + + diff --git a/i18n/pt_BR.csv b/i18n/pt_BR.csv index 8eb5be7f..ce6fbf24 100644 --- a/i18n/pt_BR.csv +++ b/i18n/pt_BR.csv @@ -120,5 +120,9 @@ "Create New Plan","Criar Novo Plano" "Open QR Code","Abrir QR Code" "QR Code warning message","Mensagem de aviso QR Code" -"Message if the qr code is not resized.","Mensagem se o QR Code não for redimensionado." +"Payment method PIX message","Mensagem do método de pagamento PIX" +"Message when selecting the payment method on the checkout screen.","Mensagem ao selecionar o método de pagamento na tela de checkout." +"Message on onepage success","Mensagem na página de sucesso" +"Message that will be presented to the customer on the success screen, after completing the order.","Mensagem que será apresentado ao cliente na tela de sucesso, após finalizar o pedido." "Copy QR Code key","Copiar chave QR Code" +"Message if the qr code is not resized.","Mensagem se o QR Code não for redimensionado." diff --git a/view/frontend/templates/onepage/pix.phtml b/view/frontend/templates/onepage/pix.phtml index ea6f4c62..46190998 100644 --- a/view/frontend/templates/onepage/pix.phtml +++ b/view/frontend/templates/onepage/pix.phtml @@ -6,23 +6,27 @@ use Vindi\Payment\Block\Onepage\Pix; ?> canShowPix()) : ?> -
+
+

+ getInfoMessageOnepageSuccess() ?> +

+ +

+ getQrCodeWarningMessage() ?> +

+ +
- - getQrCodeWarningMessage() ?> - - -
- -
- +
+ +
diff --git a/view/frontend/web/js/view/info/vindi-pix.js b/view/frontend/web/js/view/info/vindi-pix.js new file mode 100644 index 00000000..029ae684 --- /dev/null +++ b/view/frontend/web/js/view/info/vindi-pix.js @@ -0,0 +1,16 @@ +define( + [ + 'jquery', + 'Vindi_Payment/js/view/onepage/model/vindi-pix-copy-paste' + ], + function ($, Component) { + 'use strict'; + + return Component.extend({ + defaults: { + template: 'Vindi_Payment/info/vindi-pix' + }, + }); + } +); + diff --git a/view/frontend/web/js/view/onepage/model/vindi-pix-copy-paste.js b/view/frontend/web/js/view/onepage/model/vindi-pix-copy-paste.js new file mode 100644 index 00000000..19f7540b --- /dev/null +++ b/view/frontend/web/js/view/onepage/model/vindi-pix-copy-paste.js @@ -0,0 +1,26 @@ +define( + [ + 'jquery', + 'uiComponent' + ], + function ($, Component) { + 'use strict'; + + const elemVindiPixButtonCopy = '.vindi-pix-button-copy'; + + return Component.extend({ + + copyQrCodeKey: function () { + const value = this?.qrCodeKey; + + navigator.clipboard.writeText(value).then(function() { + //@todo application condition frontend + console.log("success", value); + }, function() { + //@todo application condition frontend + console.log("fail"); + }); + } + }); + } +); diff --git a/view/frontend/web/js/view/onepage/vindi-pix.js b/view/frontend/web/js/view/onepage/vindi-pix.js index 51c50fda..86a4d9a4 100644 --- a/view/frontend/web/js/view/onepage/vindi-pix.js +++ b/view/frontend/web/js/view/onepage/vindi-pix.js @@ -1,34 +1,15 @@ define( [ 'jquery', - 'uiComponent' + 'Vindi_Payment/js/view/onepage/model/vindi-pix-copy-paste' ], function ($, Component) { 'use strict'; - const elemVindiPixButtonCopy = '.vindi-pix-button-copy'; - return Component.extend({ defaults: { template: 'Vindi_Payment/onepage/vindi-pix' }, - - /** @inheritdoc */ - initialize: function () { - this._super(); - }, - - copyQrCodeKey: function () { - const value = this?.qrCodeKey; - - navigator.clipboard.writeText(value).then(function() { - //@todo application condition frontend - console.log("success", value); - }, function() { - //@todo application condition frontend - console.log("fail"); - }); - } }); } ); diff --git a/view/frontend/web/template/info/vindi-pix.html b/view/frontend/web/template/info/vindi-pix.html new file mode 100644 index 00000000..42d17321 --- /dev/null +++ b/view/frontend/web/template/info/vindi-pix.html @@ -0,0 +1,16 @@ + + +
+
+
+
+ +
+
+
+
From 8831d3ef71e592d29fe8ef2415ffe7667fcb50d5 Mon Sep 17 00:00:00 2001 From: Tharssis Araujo Date: Thu, 27 Jan 2022 08:12:48 -0300 Subject: [PATCH 40/46] =?UTF-8?q?Processar=20mensagens=20de=20erros=20e=20?= =?UTF-8?q?sucesso=20API=20-=20apresenta=C3=A7=C3=A3o=20para=20customer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Model/Payment/AbstractMethod.php | 24 +++++++++++++++++------- Model/Payment/Bill.php | 19 +++++++++++++++++-- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/Model/Payment/AbstractMethod.php b/Model/Payment/AbstractMethod.php index ea2267b9..33b2ec12 100644 --- a/Model/Payment/AbstractMethod.php +++ b/Model/Payment/AbstractMethod.php @@ -27,6 +27,11 @@ use Magento\Payment\Model\Method\AbstractMethod as OriginAbstractMethod; use Vindi\Payment\Helper\Api; +/** + * Class AbstractMethod + * + * @package \Vindi\Payment\Model\Payment + */ abstract class AbstractMethod extends OriginAbstractMethod { @@ -390,11 +395,7 @@ protected function handleBankSplitAdditionalInformation(InfoInterface $payment, */ private function successfullyPaid(array $body, $bill) { - if ($this->isValidPaymentMethodCode($body['payment_method_code']) || $this->isValidStatus($bill)) { - return true; - } - - return false; + return $this->isValidPaymentMethodCode($body['payment_method_code']) || $this->isValidStatus($bill) || $this->isWaitingPaymentMethodResponse($bill); } /** @@ -406,13 +407,22 @@ protected function isValidPaymentMethodCode($paymentMethodCode) { $paymentMethodsCode = [ PaymentMethod::BANK_SLIP, - PaymentMethod::DEBIT_CARD, - PaymentMethod::PIX + PaymentMethod::DEBIT_CARD ]; return in_array($paymentMethodCode , $paymentMethodsCode); } + /** + * @param $bill + * + * @return bool + */ + protected function isWaitingPaymentMethodResponse($bill) + { + return reset($bill['charges'])['last_transaction']['status'] === Bill::WAITING_STATUS; + } + /** * @param $bill * diff --git a/Model/Payment/Bill.php b/Model/Payment/Bill.php index 1ee1d29b..4fc26679 100644 --- a/Model/Payment/Bill.php +++ b/Model/Payment/Bill.php @@ -2,14 +2,29 @@ namespace Vindi\Payment\Model\Payment; +use Vindi\Payment\Helper\Api; + +/** + * Class Bill + * @package Vindi\Payment\Model\Payment + */ class Bill { - private $api; + const PAID_STATUS = 'paid'; const REVIEW_STATUS = 'review'; const FRAUD_REVIEW_STATUS = 'fraud_review'; + const WAITING_STATUS = 'waiting'; - public function __construct(\Vindi\Payment\Helper\Api $api) + /** + * @var Api + */ + private $api; + + /** + * @param Api $api + */ + public function __construct(Api $api) { $this->api = $api; } From b8702714c5d4428fa16c2c0abbdf339554bdbfba Mon Sep 17 00:00:00 2001 From: Tharssis Araujo Date: Mon, 31 Jan 2022 11:58:48 -0300 Subject: [PATCH 41/46] =?UTF-8?q?N2wIEOxd=20|=20Cancelar=20transa=C3=A7?= =?UTF-8?q?=C3=A3o=20Pix?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Block/Info/Pix.php | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/Block/Info/Pix.php b/Block/Info/Pix.php index dc1fe0d7..cb9b8369 100644 --- a/Block/Info/Pix.php +++ b/Block/Info/Pix.php @@ -76,7 +76,10 @@ public function getOrder() */ public function canShowPixInfo() { - return $this->getOrder()->getPayment()->getMethod() === \Vindi\Payment\Model\Payment\Pix::CODE; + $paymentMethod = $this->getOrder()->getPayment()->getMethod() === \Vindi\Payment\Model\Payment\Pix::CODE; + $timestampMaxDays = strtotime($this->getMaxDaysToPayment()); + + return $paymentMethod && $this->isValidToPayment($timestampMaxDays); } /** @@ -112,7 +115,30 @@ public function getQrcodeOriginalPath() */ public function getDaysToKeepWaitingPayment() { - $timestamp = strtotime($this->getOrder()->getPayment()->getAdditionalInformation('max_days_to_keep_waiting_payment')); - return date('d/m/Y H:m:s', $timestamp); + $timestampMaxDays = strtotime($this->getMaxDaysToPayment()); + return date('d/m/Y H:m:s', $timestampMaxDays); + } + + /** + * @param $timestampMaxDays + * + * @return bool + */ + protected function isValidToPayment($timestampMaxDays) + { + if (!$timestampMaxDays) { + return false; + } + + return $timestampMaxDays >= strtotime("now"); + } + + /** + * @return mixed + * @throws \Magento\Framework\Exception\LocalizedException + */ + protected function getMaxDaysToPayment() + { + return $this->getOrder()->getPayment()->getAdditionalInformation('max_days_to_keep_waiting_payment'); } } From f25efbee76c28f580361ed4e5206b2435ccbee73 Mon Sep 17 00:00:00 2001 From: Tharssis Araujo Date: Mon, 31 Jan 2022 12:23:36 -0300 Subject: [PATCH 42/46] =?UTF-8?q?ajustes=20para=20mostrar=20informa=C3=A7?= =?UTF-8?q?=C3=B5es=20do=20m=C3=A9todo=20de=20pagamento?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Model/Payment/AbstractMethod.php | 8 +++++--- i18n/pt_BR.csv | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Model/Payment/AbstractMethod.php b/Model/Payment/AbstractMethod.php index 33b2ec12..e02d064b 100644 --- a/Model/Payment/AbstractMethod.php +++ b/Model/Payment/AbstractMethod.php @@ -276,8 +276,8 @@ protected function processPayment(InfoInterface $payment, $amount) } if ($bill = $this->bill->create($body)) { - $this->handleBankSplitAdditionalInformation($payment, $body, $bill); if ($this->successfullyPaid($body, $bill)) { + $this->handleBankSplitAdditionalInformation($payment, $body, $bill); $order->setVindiBillId($bill['id']); return $bill['id']; } @@ -322,8 +322,8 @@ private function handleSubscriptionOrder(InfoInterface $payment, OrderItemInterf if ($responseData = $this->subscriptionRepository->create($body)) { $bill = $responseData['bill']; - $this->handleBankSplitAdditionalInformation($payment, $body, $bill); if ($this->successfullyPaid($body, $bill)) { + $this->handleBankSplitAdditionalInformation($payment, $body, $bill); $order->setVindiBillId($bill['id']); $order->setVindiSubscriptionId($responseData['subscription']['id']); return $bill['id']; @@ -395,7 +395,9 @@ protected function handleBankSplitAdditionalInformation(InfoInterface $payment, */ private function successfullyPaid(array $body, $bill) { - return $this->isValidPaymentMethodCode($body['payment_method_code']) || $this->isValidStatus($bill) || $this->isWaitingPaymentMethodResponse($bill); + return $this->isValidPaymentMethodCode($body['payment_method_code']) + || $this->isValidStatus($bill) + || $this->isWaitingPaymentMethodResponse($bill); } /** diff --git a/i18n/pt_BR.csv b/i18n/pt_BR.csv index ce6fbf24..3a536830 100644 --- a/i18n/pt_BR.csv +++ b/i18n/pt_BR.csv @@ -120,7 +120,7 @@ "Create New Plan","Criar Novo Plano" "Open QR Code","Abrir QR Code" "QR Code warning message","Mensagem de aviso QR Code" -"Payment method PIX message","Mensagem do método de pagamento PIX" +"PIX Payment method message","Mensagem do método de pagamento PIX" "Message when selecting the payment method on the checkout screen.","Mensagem ao selecionar o método de pagamento na tela de checkout." "Message on onepage success","Mensagem na página de sucesso" "Message that will be presented to the customer on the success screen, after completing the order.","Mensagem que será apresentado ao cliente na tela de sucesso, após finalizar o pedido." From edb9c6f154087dc55a70b0a7a1e25ee1ee3cdec0 Mon Sep 17 00:00:00 2001 From: Tharssis Araujo Date: Tue, 8 Feb 2022 08:41:34 -0300 Subject: [PATCH 43/46] Criar Assinatura Pix --- .../ui_component/vindi_payment_subscription_listing.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/view/adminhtml/ui_component/vindi_payment_subscription_listing.xml b/view/adminhtml/ui_component/vindi_payment_subscription_listing.xml index 25aa842c..0cce8689 100644 --- a/view/adminhtml/ui_component/vindi_payment_subscription_listing.xml +++ b/view/adminhtml/ui_component/vindi_payment_subscription_listing.xml @@ -84,6 +84,10 @@ bank_slip Boleto Bancário + + pix + Pix + select From 13effea2b95a49c7c4803ecc0037d1443fb91310 Mon Sep 17 00:00:00 2001 From: Tharssis Araujo Date: Fri, 11 Feb 2022 15:01:16 -0300 Subject: [PATCH 44/46] updated i18n --- i18n/pt_BR.csv | 2 ++ 1 file changed, 2 insertions(+) diff --git a/i18n/pt_BR.csv b/i18n/pt_BR.csv index 94162e3c..f3c6ede3 100644 --- a/i18n/pt_BR.csv +++ b/i18n/pt_BR.csv @@ -127,3 +127,5 @@ "Copy QR Code key","Copiar chave QR Code" "Message if the qr code is not resized.","Mensagem se o QR Code não for redimensionado." "Pay up: %s","Pague até: %s" +"Enabled document","Ativar documento" +"When enabled, it will only be possible to finalize the order with the document informed when selecting the payment method. When disabled, the client will not be asked for the document, but it will still be necessary to send the document when creating the order in VINDI, otherwise it will be rejected by the API.","Quando habilitado, só será possível finalizar o pedido com o documento informado ao selecionar o método de pagamento. Quando desabilitado, não será solicitado ao cliente o documento, porém ainda será necessário o envio do documento ao criar o pedido na VINDI, caso contrário será rejeitado pela API." From 47f6269ac9cd97f6350e5cf28ef69a17f5d4975d Mon Sep 17 00:00:00 2001 From: Tharssis Araujo Date: Mon, 14 Feb 2022 11:43:35 -0300 Subject: [PATCH 45/46] Transacionar Pix: Magento x Vindi --- Api/PixConfigurationInterface.php | 9 ++++ Helper/PixConfiguration.php | 8 ++++ Model/Payment/Customer.php | 48 +++++++++++++++++-- Model/Pix/ConfigProvider.php | 1 + Observer/DataAssignObserver.php | 6 ++- etc/adminhtml/system.xml | 7 +++ etc/events.xml | 8 ++-- view/frontend/requirejs-config.js | 5 ++ view/frontend/web/js/libs/jquery.mask.min.js | 19 ++++++++ view/frontend/web/js/model/document.js | 19 ++++++++ view/frontend/web/js/model/validate.js | 43 +++++++++++++++++ .../view/payment/method-renderer/vindi-pix.js | 48 +++++++++++++++++-- .../web/template/payment/vindi-pix.html | 44 +++++++++++++++++ 13 files changed, 252 insertions(+), 13 deletions(-) create mode 100644 view/frontend/requirejs-config.js create mode 100644 view/frontend/web/js/libs/jquery.mask.min.js create mode 100644 view/frontend/web/js/model/document.js create mode 100644 view/frontend/web/js/model/validate.js diff --git a/Api/PixConfigurationInterface.php b/Api/PixConfigurationInterface.php index 66851055..5496f81d 100644 --- a/Api/PixConfigurationInterface.php +++ b/Api/PixConfigurationInterface.php @@ -8,10 +8,19 @@ interface PixConfigurationInterface { + const PATH_ENABLED_DOCUMENT = 'payment/vindi_pix/enabled_document'; const PATH_INFO_MESSAGE = 'checkout/vindi_pix/info_message'; const PATH_INFO_MESSAGE_ONEPAGE_SUCCESS = 'checkout/vindi_pix/info_message_onepage_success'; const PATH_QR_CODE_WARNING_MESSAGE = 'checkout/vindi_pix/qr-code-warning-message'; + /** + * @param string $scopeType + * @param string|null $scopeCode + * + * @return bool + */ + public function isEnabledDocument(string $scopeType = ScopeInterface::SCOPE_STORE, string $scopeCode = null); + /** * @param string $scopeType * @param string|null $scopeCode diff --git a/Helper/PixConfiguration.php b/Helper/PixConfiguration.php index 329f007a..af79dad1 100644 --- a/Helper/PixConfiguration.php +++ b/Helper/PixConfiguration.php @@ -10,6 +10,14 @@ class PixConfiguration extends AbstractHelper implements PixConfigurationInterface { + /** + * @inheritDoc + */ + public function isEnabledDocument(string $scopeType = ScopeInterface::SCOPE_STORE, string $scopeCode = null) + { + return $this->scopeConfig->isSetFlag(static::PATH_ENABLED_DOCUMENT, $scopeType, $scopeCode); + } + /** * @inheritDoc */ diff --git a/Model/Payment/Customer.php b/Model/Payment/Customer.php index 21260a28..677eeb2a 100644 --- a/Model/Payment/Customer.php +++ b/Model/Payment/Customer.php @@ -2,19 +2,38 @@ namespace Vindi\Payment\Model\Payment; + +use Magento\Customer\Api\CustomerRepositoryInterface; +use Magento\Framework\Message\ManagerInterface; +use Magento\Sales\Model\Order; +use Vindi\Payment\Helper\Api; + class Customer { + + /** + * @param CustomerRepositoryInterface $customerRepository + * @param Api $api + * @param ManagerInterface $messageManager + */ public function __construct( - \Magento\Customer\Api\CustomerRepositoryInterface $customerRepository, - \Vindi\Payment\Helper\Api $api, - \Magento\Framework\Message\ManagerInterface $messageManager + CustomerRepositoryInterface $customerRepository, + Api $api, + ManagerInterface $messageManager ) { $this->customerRepository = $customerRepository; $this->api = $api; $this->messageManager = $messageManager; } - public function findOrCreate($order) + /** + * @param Order $order + * + * @return array|bool|mixed + * @throws \Magento\Framework\Exception\LocalizedException + * @throws \Magento\Framework\Exception\NoSuchEntityException + */ + public function findOrCreate(Order $order) { $billing = $order->getBillingAddress(); $customer = null; @@ -43,7 +62,7 @@ public function findOrCreate($order) $customerVindi = [ 'name' => $billing->getFirstname() . ' ' . $billing->getLastname(), 'email' => $billing->getEmail(), - 'registry_code' => $order->getData('customer_taxvat') ?: '', + 'registry_code' => $this->getDocumentGuest($order), 'code' => $customer ? $customer->getId() : '', 'phones' => $this->formatPhone($billing->getTelephone()), 'address' => $address @@ -95,6 +114,11 @@ public function findVindiCustomer($query) return false; } + /** + * @param $phone + * + * @return string|null + */ public function formatPhone($phone) { $digits = strlen('55' . preg_replace('/^0|\D+/', '', $phone)); @@ -105,4 +129,18 @@ public function formatPhone($phone) return array_key_exists($digits, $phone_types) ? $phone_types[$digits] : null; } + + /** + * @param \Magento\Sales\Model\Order $order + * + * @return mixed|string + */ + protected function getDocumentGuest(Order $order) + { + if($document = $order->getData('customer_taxvat')) { + return $document; + } + + return $order->getPayment()->getAdditionalInformation('document') ?: ''; + } } diff --git a/Model/Pix/ConfigProvider.php b/Model/Pix/ConfigProvider.php index f28e32dc..57957ae7 100644 --- a/Model/Pix/ConfigProvider.php +++ b/Model/Pix/ConfigProvider.php @@ -36,6 +36,7 @@ public function getConfig() return [ 'payment' => [ 'vindi_pix' => [ + 'enabledDocument' => $this->pixConfiguration->isEnabledDocument(), 'info_message' => $this->pixConfiguration->getInfoMessage(), ] ] diff --git a/Observer/DataAssignObserver.php b/Observer/DataAssignObserver.php index 711246f4..41dc9b52 100644 --- a/Observer/DataAssignObserver.php +++ b/Observer/DataAssignObserver.php @@ -1,6 +1,7 @@ + + + Magento\Config\Model\Config\Source\Yesno + Vindi\Payment\Model\Config\Backend\ApiKeyValidator + When enabled, it will only be possible to finalize the order with the document informed when selecting the payment method. When disabled, the client will not be asked for the document, but it will still be necessary to send the document when creating the order in VINDI, otherwise it will be rejected by the API. + diff --git a/etc/events.xml b/etc/events.xml index 214d82b4..f0849e44 100644 --- a/etc/events.xml +++ b/etc/events.xml @@ -1,8 +1,10 @@ - - + + + - \ No newline at end of file + diff --git a/view/frontend/requirejs-config.js b/view/frontend/requirejs-config.js new file mode 100644 index 00000000..d4b42ba6 --- /dev/null +++ b/view/frontend/requirejs-config.js @@ -0,0 +1,5 @@ +const config = { + paths: { + 'jQueryMask': 'Vindi_Payment/js/libs/jquery.mask.min' + }, +} diff --git a/view/frontend/web/js/libs/jquery.mask.min.js b/view/frontend/web/js/libs/jquery.mask.min.js new file mode 100644 index 00000000..986b8391 --- /dev/null +++ b/view/frontend/web/js/libs/jquery.mask.min.js @@ -0,0 +1,19 @@ +// jQuery Mask Plugin v1.14.15 +// github.com/igorescobar/jQuery-Mask-Plugin +var $jscomp={scope:{},findInternal:function(a,l,d){a instanceof String&&(a=String(a));for(var p=a.length,h=0;hd?g=10*e:f>=g&&f!==d?c.maskDigitPosMapOld[g]||(f=g,g=g-(l-h)-a,c.maskDigitPosMap[g]&&(g=f)):g>f&& + (g=g+(h-l)+m)}return g},behaviour:function(f){f=f||window.event;c.invalid=[];var e=b.data("mask-keycode");if(-1===a.inArray(e,m.byPassKeys)){var e=c.getMasked(),g=c.getCaret();setTimeout(function(){c.setCaret(c.calculateCaretPosition())},a.jMaskGlobals.keyStrokeCompensation);c.val(e);c.setCaret(g);return c.callbacks(f)}},getMasked:function(a,b){var g=[],d=void 0===b?c.val():b+"",n=0,h=e.length,q=0,l=d.length,k=1,r="push",p=-1,t=0,y=[],v,z;f.reverse?(r="unshift",k=-1,v=0,n=h-1,q=l-1,z=function(){return-1< + n&&-1
+
+ + +
+
+ +
+ + +
+
+
+
+ + + +
+
+
+
+
+
+
+ +
+