From 01c9e90a9a26b91ed097f04a554865192e8be589 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Wed, 6 Mar 2024 00:56:08 +0530 Subject: [PATCH 01/67] Magic integration --- Controller/OneClick/CompleteOrder.php | 527 ++++++++++++++++++ Controller/OneClick/PlaceOrder.php | 296 ++++++++++ Controller/OneClick/StateMap.php | 80 +++ Model/CartConverter.php | 63 +++ Model/CustomerConsent.php | 62 +++ Model/QuoteBuilder.php | 77 +++ Model/QuoteBuilder/ItemBuilder.php | 133 +++++ Model/Resolver/CouponList.php | 116 ++++ etc/adminhtml/system.xml | 25 + etc/config.xml | 3 + etc/schema.graphqls | 10 + view/frontend/layout/catalog_product_view.xml | 9 + view/frontend/layout/checkout_cart_index.xml | 9 + view/frontend/templates/oneclick/buynow.phtml | 63 +++ .../templates/oneclick/magiccart.phtml | 65 +++ view/frontend/web/css/magic.css | 13 + view/frontend/web/js/magic-buy-now.js | 193 +++++++ view/frontend/web/js/magic-cart.js | 199 +++++++ 18 files changed, 1943 insertions(+) create mode 100644 Controller/OneClick/CompleteOrder.php create mode 100644 Controller/OneClick/PlaceOrder.php create mode 100644 Controller/OneClick/StateMap.php create mode 100644 Model/CartConverter.php create mode 100644 Model/CustomerConsent.php create mode 100644 Model/QuoteBuilder.php create mode 100644 Model/QuoteBuilder/ItemBuilder.php create mode 100644 Model/Resolver/CouponList.php create mode 100644 view/frontend/layout/catalog_product_view.xml create mode 100644 view/frontend/layout/checkout_cart_index.xml create mode 100644 view/frontend/templates/oneclick/buynow.phtml create mode 100644 view/frontend/templates/oneclick/magiccart.phtml create mode 100644 view/frontend/web/css/magic.css create mode 100644 view/frontend/web/js/magic-buy-now.js create mode 100644 view/frontend/web/js/magic-cart.js diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php new file mode 100644 index 00000000..a08a475f --- /dev/null +++ b/Controller/OneClick/CompleteOrder.php @@ -0,0 +1,527 @@ +request = $request; + $this->resultJsonFactory = $jsonFactory; + $this->cartManagement = $cartManagement; + $this->priceHelper = $priceHelper; + $this->config = $config; + $this->rzp = $paymentMethod->setAndGetRzpApiInstance(); + $this->logger = $logger; + $this->productRepository = $productRepository; + $this->quoteItem = $quoteItem; + $this->quoteIdMaskFactory = $quoteIdMaskFactory; + $this->quoteIdMaskResourceModel = $quoteIdMaskResourceModel; + $this->storeManager = $storeManager; + $this->cartRepositoryInterface = $cartRepositoryInterface; + $this->order = $order; + $this->invoiceService = $invoiceService; + $this->invoiceSender = $invoiceSender; + $this->transaction = $transaction; + $this->orderSender = $orderSender; + $this->checkoutSession = $checkoutSession; + $this->collectionFactory = $collectionFactory; + $this->stateNameMap = $stateNameMap; + $this->cartConverter = $cartConverter; + $this->customerConsent = $customerConsent; + $this->resultRedirectFactory = $context->getResultFactory();; + $this->orderStatus = static::STATUS_PROCESSING; + $this->authorizeCommand = new AuthorizeCommand(); + $this->captureCommand = new CaptureCommand(); + } + + public function execute() + { + $params = $this->request->getParams(); + + $resultJson = $this->resultJsonFactory->create(); + + $rzpOrderId = $params['razorpay_order_id']; + $rzpPaymentId = $params['razorpay_payment_id']; + + $rzpOrderData = $this->rzp->order->fetch($rzpOrderId); + $rzpPaymentData = $this->rzp->payment->fetch($rzpPaymentId); + + $cartId = isset($rzpOrderData->notes) ? $rzpOrderData->notes->cart_id : null; + $email = $rzpOrderData->customer_details->email ?? null; + + $quote = $this->cartRepositoryInterface->get($cartId); + + $this->updateQuote($quote, $rzpOrderData, $rzpPaymentData); + + $quoteId = $rzpOrderData->notes->cart_mask_id; + + // Set customer to quote + $customerCartId = $this->cartConverter->convertGuestCartToCustomer($cartId); + $this->logger->info('graphQL: customerCartId ' . $customerCartId); + + $isCustomerConsentSet = false; + if($isCustomerConsentSet === true) + { + // Subscribe news letter based on customer consent data + $subscribeNewsLetter = $this->customerConsent->subscribeCustomer($customerCartId, $email); + $this->logger->info('graphQL: subscribed ' . $subscribeNewsLetter); + } + + $orderId = $this->cartManagement->placeOrder($cartId); + $order = $this->order->load($orderId); + + $order->setEmailSent(0); + if ($order) + { + if ($order->getStatus() === 'pending') + { + $order->setState(static::STATUS_PROCESSING)->setStatus($this->orderStatus); + + $this->logger->info('graphQL: Order Status Updated to ' . $this->orderStatus); + } + + if(!empty($rzpOrderData->offers)) + { + $discountAmount = $order->getDiscountAmount(); + + $codFee = $rzpOrderData->cod_fee; + $totalPaid = $rzpPaymentData->amount; + + $rzpPromotionAmount = 0; + + foreach($rzpOrderData->promotions as $promotion) + { + if (empty($promotion['code']) === false) + { + $rzpPromotionAmount = $promotion['value']; + } + } + + $offerDiff = $rzpOrderData->line_items_total + $rzpOrderData->shipping_fee + $codFee - $totalPaid - $rzpPromotionAmount; + + if($offerDiff > 0) + { + $offerDiscount = ($offerDiff/100); + // abs is used here as discount amount is returned as minus from order object. + $newDiscountAmount = abs($discountAmount) + $offerDiscount; + + $this->logger->info('graphQL: offerDiscount ' . $offerDiscount); + $this->logger->info('graphQL: newDiscountAmount ' . $newDiscountAmount); + $this->logger->info('graphQL: offerDiff ' . $offerDiff); + $this->logger->info('graphQL: codFee ' . $codFee); + $this->logger->info('graphQL: discountAmount ' . $discountAmount); + + $this->updateDiscountAmount($orderId, $newDiscountAmount, $offerDiscount, $totalPaid); + + } + } + + $payment = $order->getPayment(); + + $payment->setLastTransId($rzpPaymentId) + ->setTransactionId($rzpPaymentId) + ->setIsTransactionClosed(true) + ->setShouldCloseParentTransaction(true); + + $payment->setParentTransactionId($payment->getTransactionId()); + + if ($this->config->getPaymentAction() === \Razorpay\Magento\Model\PaymentMethod::ACTION_AUTHORIZE_CAPTURE) + { + $payment->addTransactionCommentsToOrder( + "$rzpPaymentId", + $this->captureCommand->execute( + $payment, + $order->getGrandTotal(), + $order + ), + "" + ); + } + else + { + $payment->addTransactionCommentsToOrder( + "$rzpPaymentId", + $this->authorizeCommand->execute( + $payment, + $order->getGrandTotal(), + $order + ), + "" + ); + } + + $transaction = $payment->addTransaction(\Magento\Sales\Model\Order\Payment\Transaction::TYPE_AUTH, null, true, ""); + + $transaction->setIsClosed(true); + + $transaction->save(); + + $this->logger->info('Payment authorized completed for id : '. $order->getIncrementId()); + + if ($order->canInvoice() && $this->config->canAutoGenerateInvoice() + && $rzpOrderData->status === 'paid') + { + $invoice = $this->invoiceService->prepareInvoice($order); + $invoice->setRequestedCaptureCase(\Magento\Sales\Model\Order\Invoice::CAPTURE_ONLINE); + $invoice->setTransactionId($rzpPaymentId); + $invoice->register(); + $invoice->save(); + + $this->logger->info('graphQL: Created Invoice for ' + . 'order_id ' . $rzpOrderId . ', ' + . 'rzp_payment_id ' . $rzpPaymentId); + + $transactionSave = $this->transaction + ->addObject($invoice) + ->addObject($invoice->getOrder()); + $transactionSave->save(); + + $this->invoiceSender->send($invoice); + + $order->addStatusHistoryComment( + __('Notified customer about invoice #%1.', $invoice->getId()) + )->setIsCustomerNotified(true); + + $this->logger->info('Invoice generated for id : '. $order->getIncrementId()); + } + else if($rzpOrderData->status === 'paid' and + ($order->canInvoice() === false or + $this->config->canAutoGenerateInvoice() === false)) + { + $this->logger->info('Invoice generation not possible for id : '. $order->getIncrementId()); + } + + try + { + $this->checkoutSession->setRazorpayMailSentOnSuccess(true); + $this->orderSender->send($order); + $this->checkoutSession->unsRazorpayMailSentOnSuccess(); + } + catch (\Magento\Framework\Exception\MailException $e) + { + $this->logger->critical('graphQL: ' + . 'Razorpay Error:' . $e->getMessage()); + + throw new GraphQlInputException(__('Razorpay Error: %1.', $e->getMessage())); + } + catch (\Exception $e) + { + $this->logger->critical('graphQL: ' + . 'Error:' . $e->getMessage()); + + throw new GraphQlInputException(__('Error: %1.', $e->getMessage())); + } + + $this + ->checkoutSession + ->setLastSuccessQuoteId($order->getQuoteId()) + ->setLastQuoteId($order->getQuoteId()) + ->clearHelperData(); + if (empty($order) === false) + { + $this + ->checkoutSession + ->setLastOrderId($order->getId()) + ->setLastRealOrderId($order->getIncrementId()) + ->setLastOrderStatus($order->getStatus()); + } + + $order->save(); + + $result = [ + 'status' => 'success' + ]; + + return $resultJson->setData($result); + + } + } + + public function updateDiscountAmount($orderId, $newDiscountAmount, $offerAmount, $totalPaid) + { + try { + // Load the order + $order = $this->order->load($orderId); + + // Update discount amount + $order->setDiscountAmount($newDiscountAmount); + $order->setBaseDiscountAmount($newDiscountAmount); + + $totalBaseGrandTotal = $order->getBaseGrandTotal(); + $totalGrandTotal = $order->getGrandTotal(); + + $order->setBaseGrandTotal($totalBaseGrandTotal - $offerAmount); + $order->setGrandTotal($totalGrandTotal - $offerAmount); + + $order->setTotalPaid($totalPaid/100); + + $comment = __('Razorpay offer applied ₹%1.', $offerAmount); + + // Remove "Pending Payment COD" from the comment + $comment = str_replace('Pending Payment COD', '', $comment); + + $order->addStatusHistoryComment( + $comment + )->setIsCustomerNotified(true); + + return true; + } catch (\Exception $e) { + // Handle exception + return false; + } + } + + protected function updateQuote($quote, $rzpOrderData, $rzpPaymentData) + { + $carrierCode = $rzpOrderData->notes->carrier_code ?? 'freeshipping'; + $methodCode = $rzpOrderData->notes->method_code ?? 'freeshipping'; + + $email = $rzpOrderData->customer_details->email ?? ''; + + $quote->setCustomerEmail($email); + + $shippingCountry = $rzpOrderData->customer_details->shipping_address->country; + $shippingState = $rzpOrderData->customer_details->shipping_address->state; + + $billingingCountry = $rzpOrderData->customer_details->billing_address->country; + $billingingState = $rzpOrderData->customer_details->billing_address->state; + + $shippingRegionCode = $this->getRegionCode($shippingCountry, $shippingState); + $billingRegionCode = $this->getRegionCode($billingingCountry, $billingingState); + + $shipping = $this->getAddress($rzpOrderData->customer_details->shipping_address, $shippingRegionCode, $email); + $billing = $this->getAddress($rzpOrderData->customer_details->billing_address, $billingRegionCode, $email); + + $quote->getBillingAddress()->addData($billing['address']); + $quote->getShippingAddress()->addData($shipping['address']); + + $shippingMethod = 'NA'; + if(empty($carrierCode) === false && empty($methodCode) === false) + { + $shippingMethod = $carrierCode ."_". $methodCode; + } + + $shippingAddress=$quote->getShippingAddress(); + $shippingAddress->setCollectShippingRates(true) + ->collectShippingRates() + ->setShippingMethod($shippingMethod); + + // Todo: Loop through promotions and fetch the discount data. + if(isset($rzpOrderData->promotions[0]->code) == true) + { + $quote->setCouponCode($rzpOrderData->promotions[0]->code); + } + + if($rzpPaymentData->method === 'cod') + { + $paymentMethod = static::COD; + } + else + { + $paymentMethod = static::RAZORPAY; + } + + $quote->setPaymentMethod($paymentMethod); + $quote->setInventoryProcessed(false); + // Set Sales Order Payment + $quote->getPayment()->importData(['method' => $paymentMethod]); + + $quote->save(); + + } + + protected function getRegionCode($country, $state) + { + $magentoStateName = $this->stateNameMap->getMagentoStateName($country, $state); + + $this->logger->info('graphQL: Magento state name:' . $magentoStateName); + + $regionCode = $this->collectionFactory->create() + ->addRegionNameFilter($magentoStateName) + ->getFirstItem() + ->toArray(); + + return $regionCode['code'] ?? 'NA'; + + } + + protected function getAddress($rzpAddress, $regionCode, $email) + { + $name = explode(' ', $rzpAddress->name); + + return [ + 'email' => $email, //buyer email id + 'address' =>[ + 'firstname' => $name[0], //address Details + 'lastname' => empty($name[1]) === false ? $name[1] : '.', + 'street' => $rzpAddress->line1, + 'city' => $rzpAddress->city, + 'country_id' => strtoupper($rzpAddress->country), + 'region' => $regionCode, + 'postcode' => $rzpAddress->zipcode, + 'telephone' => $rzpAddress->contact, + 'save_in_address_book' => 1 + ] + ]; + } + + protected function validateSignature($request) + { + if (empty($request['error']) === false) + { + $this + ->logger + ->critical("Validate: Payment Failed or error from gateway"); + $this + ->messageManager + ->addError(__('Payment Failed')); + throw new \Exception("Payment Failed or error from gateway"); + } + + $this->logger->info('razorpay_payment_id = '. $request['razorpay_payment_id']); + $this->logger->info('razorpay_order_id = '. $request['razorpay_order_id']); + $this->logger->info('razorpay_signature = '. $request['razorpay_signature']); + + + $attributes = array( + 'razorpay_payment_id' => $request['razorpay_payment_id'], + 'razorpay_order_id' => $request['razorpay_order_id'], + 'razorpay_signature' => $request['razorpay_signature'], + ); + + $this + ->rzp + ->utility + ->verifyPaymentSignature($attributes); + } + +} \ No newline at end of file diff --git a/Controller/OneClick/PlaceOrder.php b/Controller/OneClick/PlaceOrder.php new file mode 100644 index 00000000..c6e7d341 --- /dev/null +++ b/Controller/OneClick/PlaceOrder.php @@ -0,0 +1,296 @@ +request = $request; + $this->resultJsonFactory = $jsonFactory; + $this->cartManagement = $cartManagement; + $this->config = $config; + $this->rzp = $paymentMethod->setAndGetRzpApiInstance(); + $this->logger = $logger; + $this->quoteBuilderFactory = $quoteBuilderFactory; + $this->productRepository = $productRepository; + $this->maskedQuoteIdInterface = $maskedQuoteIdInterface; + $this->quoteIdMaskFactory = $quoteIdMaskFactory; + $this->quoteIdMaskResourceModel = $quoteIdMaskResourceModel; + $this->storeManager = $storeManager; + $this->cart = $cart; + $this->checkoutSession = $checkoutSession; + $this->resourceConnection = $resourceConnection; + $this->sequenceManager = $sequenceManager; + } + + public function execute() + { + $params = $this->request->getParams(); + + if(isset($params['page']) && $params['page'] == 'cart') + { + $cartItems = $this->cart->getQuote()->getAllVisibleItems(); + $quoteId = $this->cart->getQuote()->getId(); + $totals = $this->cart->getQuote()->getTotals(); + + $quote = $this->checkoutSession->getQuote(); + $customerId = $quote->getCustomerId(); + + // Set customer as guest to update the quote during checkout journey. + if($customerId) + { + $this->logger->info('graphQL: customer: ' . json_encode($customerId)); + + $connection = $this->resourceConnection->getConnection(); + $tableName = $this->resourceConnection->getTableName('quote'); + + $connection->update($tableName, ['customer_id' => null, 'customer_is_guest' => 1], ['entity_id = ?' => $quoteId]); + } + } + else + { + /** @var QuoteBuilder $quoteBuilder */ + $quoteBuilder = $this->quoteBuilderFactory->create(); + $quote = $quoteBuilder->createQuote(); + $quoteId = $quote->getId(); + $totals = $quote->getTotals(); + $cartItems = $quote->getAllVisibleItems(); + } + + $resultJson = $this->resultJsonFactory->create(); + + try + { + $maskedId = $this->maskedQuoteIdInterface->execute($quoteId); + + if ($maskedId === '') { + $quoteIdMask = $this->quoteIdMaskFactory->create(); + $quoteIdMask->setQuoteId($quoteId); + $this->quoteIdMaskResourceModel->save($quoteIdMask); + $maskedId = $this->maskedQuoteIdInterface->execute($quoteId); + } + $this->storeManager->getStore()->getBaseCurrencyCode(); + + $totalAmount = 0; + $lineItems = []; + + foreach ($cartItems as $quoteItem) { + + $store = $this->storeManager->getStore(); + $productId = $quoteItem->getProductId(); + $product = $this->productRepository->getById($productId); + + $productImageUrl = $store->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) . 'catalog/product' .$product->getImage(); + $productUrl = $product->getProductUrl(); + + $lineItems[] = [ + 'type' => 'e-commerce', + 'sku' => $quoteItem->getSku(), + 'variant_id' => $quoteItem->getProductId(), + 'price' => $quoteItem->getPrice()*100, + 'offer_price' => $quoteItem->getPrice()*100, + 'tax_amount' => 0, + 'quantity' => $quoteItem->getQty(), + 'name' => $quoteItem->getName(), + 'description' => $quoteItem->getName(), + 'image_url' => $productImageUrl, + 'product_url' => $productUrl, + ]; + + $totalAmount += ($quoteItem->getQty() * $quoteItem->getPrice()) * 100; + } + + } catch (LocalizedException $e) { + return $resultJson->setData([ + 'status' => 'error', + 'message' => __($e->getMessage()), + ]); + } catch (\Exception $e) { + return $resultJson->setData([ + 'status' => 'error', + 'message' => __('An error occurred on the server. Please try again.'), + ]); + } + + $storeScope = \Magento\Store\Model\ScopeInterface::SCOPE_STORE; + + $paymentAction = $this->config->getValue('payment/razorpay/rzp_payment_action', $storeScope); + $paymentCapture = 1; + if ($paymentAction === 'authorize') + { + $paymentCapture = 0; + } + + $orderNumber = $this->getLastOrderId($quote); + + $razorpay_order = $this->rzp->order->create([ + 'amount' => $totalAmount, + 'receipt' => (string)$quote->getReservedOrderId() ?? 'order pending', + 'currency' => $this->storeManager->getStore()->getBaseCurrencyCode(), + 'payment_capture' => $paymentCapture, + 'app_offer' => 0, + 'notes' => [ + 'cart_mask_id' => $maskedId, + 'cart_id' => $quoteId + ], + 'line_items_total' => $totalAmount, + 'line_items' => $lineItems + ]); + + if (null !== $razorpay_order && !empty($razorpay_order->id)) + { + $this->logger->info('graphQL: Razorpay Order ID: ' . $razorpay_order->id); + + $result = [ + 'status' => 'success', + 'rzp_order_id' => $razorpay_order->id, + 'message' => 'Razorpay Order created successfully' + ]; + } + else + { + $this->logger->critical('graphQL: Razorpay Order not generated. Something went wrong'); + + $result = [ + 'status' => 'error', + 'message' => "Razorpay Order not generated. Something went wrong", + ]; + } + + return $resultJson->setData($result); + + } + + public function getLastOrderId($quote) + { + try { + $sequence = $this->sequenceManager->getSequence( + \Magento\Sales\Model\Order::ENTITY, + $quote->getStoreId() + ); + + // Generate a reserved order ID using the sequence + $reservedOrderId = $sequence->getNextValue(); + + // Check if the order and quote are available + if ($reservedOrderId) { + // Save the order ID in the quote for future reference + $quote->setReservedOrderId($reservedOrderId); + } + + $quote->save(); + + return $reservedOrderId; + } catch (\Exception $e) { + // Handle exception if needed + return 'order pending'; + } + } +} \ No newline at end of file diff --git a/Controller/OneClick/StateMap.php b/Controller/OneClick/StateMap.php new file mode 100644 index 00000000..f4043410 --- /dev/null +++ b/Controller/OneClick/StateMap.php @@ -0,0 +1,80 @@ +getStateNameIN(strtoupper($stateName)); + break; + + default: + $magentoStateName = $stateName; + break; + } + return $magentoStateName; + } + + //Fetching the state name on Magento using the state name for India + function getStateNameIN($stateName) + { + $stateCodeMap = [ + 'ANDAMAN&NICOBARISLANDS' => 'Andaman and Nicobar', + 'ANDAMANANDNICOBARISLANDS' => 'Andaman and Nicobar', + 'ANDHRAPRADESH' => 'Andhra Pradesh', + 'ARUNACHALPRADESH' => 'Arunachal Pradesh', + 'ASSAM' => 'Assam', + 'BIHAR' => 'Bihar', + 'CHANDIGARH' => 'Chandigarh', + 'CHATTISGARH' => 'Chhattisgarh', + 'CHHATTISGARH' => 'Chhattisgarh', + 'DADRA&NAGARHAVELI' => 'Dadra and Nagar Haveli', + 'DADRAANDNAGARHAVELI' => 'Dadra and Nagar Haveli', + 'DAMAN&DIU' => 'Daman and Diu', + 'DAMANANDDIU' => 'Daman and Diu', + 'DELHI' => 'Delhi', + 'GOA' => 'Goa', + 'GUJARAT' => 'Gujarat', + 'HARYANA' => 'Haryana', + 'HIMACHALPRADESH' => 'Himachal Pradesh', + 'JAMMU&KASHMIR' => 'Jammu and Kashmir', + 'JAMMUANDKASHMIR' => 'Jammu and Kashmir', + 'JAMMUKASHMIR' => 'Jammu and Kashmir', + 'JHARKHAND' => 'Jharkhand', + 'KARNATAKA' => 'Karnataka', + 'KERALA' => 'Kerala', + 'LAKSHADWEEP' => 'Lakshadweep', + 'LAKSHADEEP' => 'Lakshadweep', + 'LADAKH' => 'Ladakh', + 'MADHYAPRADESH' => 'Madhya Pradesh', + 'MAHARASHTRA' => 'Maharashtra', + 'MANIPUR' => 'Manipur', + 'MEGHALAYA' => 'Meghalaya', + 'MIZORAM' => 'Mizoram', + 'NAGALAND' => 'Nagaland', + 'ODISHA' => 'Orissa', + 'PONDICHERRY' => 'Pondicherry', + 'PUNJAB' => 'Punjab', + 'RAJASTHAN' => 'Rajasthan', + 'SIKKIM' => 'Sikkim', + 'TAMILNADU' => 'Tamil Nadu', + 'TRIPURA' => 'Tripura', + 'TELANGANA' => 'Telangana', + 'UTTARPRADESH' => 'Uttar Pradesh', + 'UTTARAKHAND' => 'Uttarakhand', + 'WESTBENGAL' => 'West Bengal', + ]; + + $trimmedStateName = str_replace(' ', '', $stateName); + + $magentoStateName = $stateCodeMap[$trimmedStateName] ?? $stateName; + + return $magentoStateName; + } +} diff --git a/Model/CartConverter.php b/Model/CartConverter.php new file mode 100644 index 00000000..83336954 --- /dev/null +++ b/Model/CartConverter.php @@ -0,0 +1,63 @@ +customerSession = $customerSession; + $this->cartRepository = $cartRepository; + } + + /** + * Convert a guest cart to a logged-in customer cart during order placement. + * + * @param int $guestQuoteId + * @return bool + */ + public function convertGuestCartToCustomer($guestQuoteId) + { + + $customerId = $this->customerSession->getCustomerId(); + + if($customerId) + { + try { + // Load the guest quote by ID + $guestQuote = $this->cartRepository->get($guestQuoteId); + + // Set customer details to the quote + $guestQuote->setCustomerId($customerId); + $guestQuote->setCustomerIsGuest(0); // Set customer as not a guest + + // Save the quote + $this->cartRepository->save($guestQuote); + + // Set the customer ID in the customer session + $this->customerSession->setCustomerId($customerId); + + return $customerId; + } catch (\Exception $e) { + // Handle the exception + return "false"; + } + } + } +} diff --git a/Model/CustomerConsent.php b/Model/CustomerConsent.php new file mode 100644 index 00000000..a689381d --- /dev/null +++ b/Model/CustomerConsent.php @@ -0,0 +1,62 @@ +subscriberFactory = $subscriberFactory; + $this->storeManager = $storeManager; + } + + /** + * Subscribe customer to newsletter. + * + * @param int $customerId + * @param strig $customerEmail + * @return bool + */ + public function subscribeCustomer($customerId, $customerEmail) + { + try { + $store = $this->storeManager->getStore(); + $storeId = $store->getStoreId(); + + /** @var \Magento\Newsletter\Model\Subscriber $subscriber */ + $subscriber = $this->subscriberFactory->create(); + + $subscriber->setStoreId($storeId) + ->setCustomerId($customerId) + ->setSubscriberEmail($customerEmail) + ->setSubscriberStatus(\Magento\Newsletter\Model\Subscriber::STATUS_SUBSCRIBED); + + $subscriber->save(); + + return true; + } catch (\Exception $e) { + // Handle the exception + return false; + } + } +} diff --git a/Model/QuoteBuilder.php b/Model/QuoteBuilder.php new file mode 100644 index 00000000..e9bf877e --- /dev/null +++ b/Model/QuoteBuilder.php @@ -0,0 +1,77 @@ +quoteFactory = $quoteFactory; + $this->storeManager = $storeManager; + $this->session = $session; + $this->itemBuilderFactory = $itemBuilderFactory; + } + + /** + * @return \Magento\Quote\Model\Quote + */ + public function createQuote() + { + /** @var \Magento\Quote\Model\Quote $quote */ + $quote = $this->quoteFactory->create(); + $quote->setStoreId($this->storeManager->getStore()->getId()); + + // $quote->setCustomer($this->session->getCustomerDataObject()); + $quote->setCustomerIsGuest(1); + + /** @var ItemBuilder $itemBuilder */ + $itemBuilder = $this->itemBuilderFactory->create(['quote' => $quote]); + $itemBuilder->addItems(); + + // if (!$quote->isVirtual()) { + // $quote->setShippingAddress($this->addressBuilder->getShippingAddress()); + // $this->shippingMethodBuilder->setShippingMethod($quote); + // } + + $quote->setTotalsCollectedFlag(false)->collectTotals()->save(); + + return $quote; + } +} \ No newline at end of file diff --git a/Model/QuoteBuilder/ItemBuilder.php b/Model/QuoteBuilder/ItemBuilder.php new file mode 100644 index 00000000..2bdbabad --- /dev/null +++ b/Model/QuoteBuilder/ItemBuilder.php @@ -0,0 +1,133 @@ +request = $request; + $this->quote = $quote; + $this->resolver = $resolver; + $this->productRepository = $productRepository; + $this->storeManager = $storeManager; + $this->requestInfoFilter = $requestInfoFilter; + } + + /** + * @throws \Magento\Framework\Exception\LocalizedException + */ + public function addItems() + { + $params = $this->request->getParams(); + + if (isset($params['qty'])) { + $params['qty'] = $params['qty']; + } + + $product = $this->initProduct(); + + if (!$product) { + throw new \Magento\Framework\Exception\LocalizedException( + __('We found an invalid request for adding product to quote.') + ); + } + + $requestInfo = $this->getProductRequest($params); + + $this->quote->addProduct($product, $requestInfo); + } + + /** + * @return bool|\Magento\Catalog\Api\Data\ProductInterface + */ + protected function initProduct() + { + $productId = (int)$this->request->getParam('product'); + if ($productId) { + $storeId = $this->storeManager->getStore()->getId(); + try { + return $this->productRepository->getById($productId, false, $storeId); + } catch (NoSuchEntityException $e) { + return false; + } + } + return false; + } + + /** + * @param $params + * @return \Magento\Framework\DataObject + * @throws \Magento\Framework\Exception\LocalizedException + */ + protected function getProductRequest($params) + { + if ($params instanceof \Magento\Framework\DataObject) { + $request = $params; + } elseif (is_numeric($params)) { + $request = new \Magento\Framework\DataObject(['qty' => $params]); + } elseif (is_array($params)) { + $request = new \Magento\Framework\DataObject($params); + } else { + throw new \Magento\Framework\Exception\LocalizedException( + __('We found an invalid request for adding product to quote.') + ); + } + $this->requestInfoFilter->filter($request); + + return $request; + } +} \ No newline at end of file diff --git a/Model/Resolver/CouponList.php b/Model/Resolver/CouponList.php new file mode 100644 index 00000000..f8e0b27e --- /dev/null +++ b/Model/Resolver/CouponList.php @@ -0,0 +1,116 @@ +ruleCollectionFactory = $ruleCollectionFactory; + $this->couponModel = $couponModel; + $this->ruleFactory = $ruleFactory; + } + + /** + * @inheritdoc + */ + public function resolve( + Field $field, + $context, + ResolveInfo $info, + array $value = null, + array $args = null + ) { + $appliedCoupons = []; + + $ruleCollection = $this->ruleCollectionFactory->create(); + + // Add filters to include only active and non-expired rules + $ruleCollection->addFieldToFilter('is_active', 1); + + $ruleCollection->addFieldToFilter('to_date', [['gteq' => $currentDate], ['null' => true]]); + + $ruleCollection->addFieldToFilter('conditions_serialized', ['nlike' => '%"shipping_method"%']); + + $ruleCollection->addFieldToFilter('conditions_serialized', ['nlike' => '%"payment_method"%']); + + foreach ($ruleCollection as $rule) { + $couponCollection = $this->couponModel->getCollection() + ->addFieldToFilter('rule_id', $rule->getId()); + + foreach ($couponCollection as $coupon) { + $appliedCoupons[] = [ + 'title' => $this->getCouponCodeByRuleId($rule->getId()), + 'discountAmount' => $this->calculateDiscountAmount($rule), + 'description' => $rule->getDescription() ?: '', + ]; + } + } + + return $appliedCoupons; + } + + /** + * Calculate discount amount for a rule + * + * @param \Magento\SalesRule\Model\Rule $rule + * @return float|null + */ + private function calculateDiscountAmount($rule) + { + // You may need to adjust this calculation based on your specific rule configuration + $discountAmount = $rule->getDiscountAmount(); + + // Apply additional logic if needed + // ... + + return $discountAmount; + } + + /** + * Fetch the coupon code by rule ID + * + * @param int $ruleId + * @return string|null + */ + public function getCouponCodeByRuleId($ruleId) + { + $couponCollection = $this->couponModel->getCollection() + ->addFieldToFilter('rule_id', $ruleId); + + /** @var Coupon $coupon */ + $coupon = $couponCollection->getFirstItem(); + + if ($coupon->getId()) { + return $coupon->getCode(); + } + + return null; + } +} \ No newline at end of file diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml index 9f2cae98..f847602c 100644 --- a/etc/adminhtml/system.xml +++ b/etc/adminhtml/system.xml @@ -83,6 +83,7 @@ required-entry payment/razorpay/key_secret + Magento\Sales\Model\Config\Source\Order\Status\NewStatus @@ -108,6 +109,30 @@ required-entry + + + Magento\Config\Model\Config\Source\Yesno + payment/razorpay/activate_magic + + + + + Magento\Config\Model\Config\Source\Yesno + payment/razorpay/activate_magic_buy_now + + 1 + + + + + + Magento\Config\Model\Config\Source\Yesno + payment/razorpay/activate_magic_mini_cart + + 1 + + + Magento\Config\Model\Config\Source\Yesno diff --git a/etc/config.xml b/etc/config.xml index 095d94f3..290c6f3a 100644 --- a/etc/config.xml +++ b/etc/config.xml @@ -21,6 +21,9 @@ 30 0 processing + 0 + 0 + 0 1 0 diff --git a/etc/schema.graphqls b/etc/schema.graphqls index 34286810..0d5a1e79 100644 --- a/etc/schema.graphqls +++ b/etc/schema.graphqls @@ -31,3 +31,13 @@ type SetRzpPaymentDetailsForOrderOutput { type ResetCart { success: Boolean! } + +type Coupon { + title: String + discountAmount: Float + description: String +} + +type Query { + getCoupons: [Coupon] @resolver(class: "Razorpay\\Magento\\Model\\Resolver\\CouponList") @doc(description: "Get the list of coupons") +} diff --git a/view/frontend/layout/catalog_product_view.xml b/view/frontend/layout/catalog_product_view.xml new file mode 100644 index 00000000..f4dff8a9 --- /dev/null +++ b/view/frontend/layout/catalog_product_view.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/view/frontend/layout/checkout_cart_index.xml b/view/frontend/layout/checkout_cart_index.xml new file mode 100644 index 00000000..d55425a1 --- /dev/null +++ b/view/frontend/layout/checkout_cart_index.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/view/frontend/templates/oneclick/buynow.phtml b/view/frontend/templates/oneclick/buynow.phtml new file mode 100644 index 00000000..026c2e48 --- /dev/null +++ b/view/frontend/templates/oneclick/buynow.phtml @@ -0,0 +1,63 @@ +get(\Magento\Store\Model\StoreManagerInterface::class); + $scopeConfig = $objectManager->get(ScopeConfigInterface::class); + + $code = 'razorpay'; + $magicActiveField = 'activate_magic'; + $buynowActiveField = 'activate_magic_buy_now'; + $keyField = 'key_id'; + + $isMagicEnabled = $scopeConfig->getValue('payment/' . $code . '/' . $magicActiveField, \Magento\Store\Model\ScopeInterface::SCOPE_STORE); + $isBuynowEnabled = $scopeConfig->getValue('payment/' . $code . '/' . $buynowActiveField, \Magento\Store\Model\ScopeInterface::SCOPE_STORE); + $rzpKey = $scopeConfig->getValue('payment/' . $code . '/' . $keyField, \Magento\Store\Model\ScopeInterface::SCOPE_STORE); + +?> + + + + + + + + + + + + diff --git a/view/frontend/templates/oneclick/magiccart.phtml b/view/frontend/templates/oneclick/magiccart.phtml new file mode 100644 index 00000000..0e23b2c2 --- /dev/null +++ b/view/frontend/templates/oneclick/magiccart.phtml @@ -0,0 +1,65 @@ +get(\Magento\Store\Model\StoreManagerInterface::class); +$scopeConfig = $objectManager->get(ScopeConfigInterface::class); + +$code = 'razorpay'; +$magicActiveField = 'activate_magic'; +$keyField = 'key_id'; + +$isMagicEnabled = $scopeConfig->getValue('payment/' . $code . '/' . $magicActiveField, \Magento\Store\Model\ScopeInterface::SCOPE_STORE); +$rzpKey = $scopeConfig->getValue('payment/' . $code . '/' . $keyField, \Magento\Store\Model\ScopeInterface::SCOPE_STORE); + +$cartData = $objectManager->create('Magento\Checkout\Model\Cart')->getQuote()->getAllVisibleItems(); +$cartDataCount = count( $cartData ); + +?> + 0) :?> + +
+ ", + "callbackURL": "getUrl('razorpay/oneclick/completeorder') ?>", + "key": "" + } + + }' + class="isDisabled()) ? ' disabled' : '' ?>" + + isDisabled()) :?> + + disabled="disabled" + + > + +
+ + + + + + diff --git a/view/frontend/web/css/magic.css b/view/frontend/web/css/magic.css new file mode 100644 index 00000000..9cde1ec4 --- /dev/null +++ b/view/frontend/web/css/magic.css @@ -0,0 +1,13 @@ +#cart-occ-template{ + width: 100%; +} +.action.primary.checkout{ + display: none; +} +#product-oneclick-button{ + padding: 17px 26px; + margin-bottom: 10px; +} +.fieldset.coupon{ + display: none; +} \ No newline at end of file diff --git a/view/frontend/web/js/magic-buy-now.js b/view/frontend/web/js/magic-buy-now.js new file mode 100644 index 00000000..121e3c1e --- /dev/null +++ b/view/frontend/web/js/magic-buy-now.js @@ -0,0 +1,193 @@ +define([ + 'jquery', + 'mage/translate', + 'Magento_Ui/js/modal/alert', + 'Magento_Checkout/js/model/full-screen-loader', + 'mage/url', + 'underscore', + 'mage/cookies' +], function ($, $t, alert, fullScreenLoader, url, _) { + "use strict"; + + $.widget('pmclain.oneClickButton', { + options: { + addToFormSelector: '#product_addtocart_form', + submitUrl: '', + callbackURL: '', + key: '', + actionSelector: '.actions', + buttonTemplateSelector: '#occ-template', + buttonSelector: '#product-oneclick-button', + confirmationSelector: '#one-click-confirmation' + }, + + cookie: 'occ_status', + cookieEnabled: 'enabled', + cookieDisabled: 'disabled', + + _create: function () { + this._initButton(); + }, + + _initButton: function () { + var self = this; + + switch ($.mage.cookies.get(this.cookie)) { + case this.cookieEnabled: + this._createButton(); + break; + case this.cookieDisabled: + break; + default: + self._createButton(); + } + }, + + initObservable: function() { + var self = this._super(); //Resolves UI Error on Checkout + + $.getScript("https://checkout.razorpay.com/v1/magic-checkout.js", function() { + self.razorpayDataFrameLoaded = true; + }); + + return self; + }, + + _createButton: function () { + var button = $(this.options.buttonTemplateSelector).html(); + this._parent().find(this.options.actionSelector).prepend(button); + this._bind(); + }, + + _bind: function () { + var self = this; + this._parent().find(self.options.buttonSelector).on('click touch', function() { + if (self._parent().valid()) { + self._buyNow(); + } + }); + }, + + _parent: function () { + return $(this.options.addToFormSelector); + }, + + _buyNow: function () { + var self = this; + self._disableButton(); + + fullScreenLoader.startLoader(); + + $.ajax({ + url: self.options.submitUrl, + data: self._parent().serialize(), + type: 'POST', + dataType: 'json', + showLoader: true, + success: function (data) { + console.log("*******") + console.log(data) + + self.renderIframe(data); + }, + error: function (request) { + self._orderError(request); + self.enableButton(); + } + }) + }, + + orderSuccess: function (data) { + var self = this; + self.enableButton(); + fullScreenLoader.startLoader(); + + $.ajax({ + url: self.options.callbackURL, + data: data, + type: 'POST', + dataType: 'json', + showLoader: true, + success: function (data) { + console.log("Payment complete data") + console.log(data) + var successUrl = url.build('checkout/onepage/success', {}) + console.log(successUrl) + window.location.href = successUrl; + }, + error: function (error) { + console.log("Payment complete fail") + console.log(error) + } + }) + }, + + renderIframe: function(data) { + var self = this; + + var options = { + key: self.options.key, + name: 'Razorpay', + amount: data.totalAmount, + handler: function (data) { + fullScreenLoader.startLoader(); + + self.orderSuccess(data); + }, + order_id: data.rzp_order_id, + modal: { + ondismiss: function(data) { + //reset the cart + // self.resetCart(data); + // fullScreenLoader.stopLoader(); + // self.isPaymentProcessing.reject("Payment Closed"); + // self.isPlaceOrderActionAllowed(true); + self.enableButton(); + + } + }, + notes: { + }, + // callback_url : self.options.callbackURL, + prefill: { + name: '', + contact: '', + email: '' + }, + _: { + integration: 'magento', + // integration_version: '', + // integration_parent_version: data.maze_version, + integration_type: 'plugin', + } + }; + + // if (data.quote_currency !== 'INR') + // { + // options.display_currency = data.quote_currency; + // options.display_amount = data.quote_amount; + // } + + this.rzp = new Razorpay(options); + + this.rzp.open(); + }, + + _orderError: function (request) { + console.log(request); + this.enableButton(); + }, + + _disableButton: function () { + var button = this._parent().find(this.options.buttonSelector); + button.addClass('disabled'); + }, + + enableButton: function () { + var button = this._parent().find(this.options.buttonSelector); + button.removeClass('disabled'); + } + }); + + return $.pmclain.oneClickButton; +}); \ No newline at end of file diff --git a/view/frontend/web/js/magic-cart.js b/view/frontend/web/js/magic-cart.js new file mode 100644 index 00000000..193cbc8d --- /dev/null +++ b/view/frontend/web/js/magic-cart.js @@ -0,0 +1,199 @@ +define([ + 'jquery', + 'mage/translate', + 'Magento_Ui/js/modal/alert', + 'Magento_Checkout/js/model/full-screen-loader', + 'mage/url', + 'underscore', + 'mage/cookies' +], function ($, $t, alert, fullScreenLoader, url, _) { + "use strict"; + + $.widget('pmclain.oneClickButton', { + options: { + addToFormSelector: '#cart-occ-div', + submitUrl: '', + callbackURL: '', + key: '', + actionSelector: '.action', + buttonTemplateSelector: '#cart-occ-div', + buttonSelector: '#cart-occ-template', + confirmationSelector: '#one-click-confirmation' + }, + + cookie: 'occ_status', + cookieEnabled: 'enabled', + cookieDisabled: 'disabled', + + _create: function () { + this._initButton(); + }, + + _initButton: function () { + var self = this; + + switch ($.mage.cookies.get(this.cookie)) { + case this.cookieEnabled: + this._createButton(); + break; + case this.cookieDisabled: + break; + default: + self._createButton(); + } + }, + + initObservable: function() { + var self = this._super(); //Resolves UI Error on Checkout + + $.getScript("https://checkout.razorpay.com/v1/magic-checkout.js", function() { + self.razorpayDataFrameLoaded = true; + }); + + return self; + }, + + _createButton: function () { + var button = $(this.options.buttonTemplateSelector).html(); + this._bind(); + }, + + _bind: function () { + var self = this; + console.log(self.options.buttonSelector) + this._parent().find(self.options.buttonSelector).on('click touch', function() { + // if (self._parent().valid()) { + self._cartCheckout(); + // } + }); + }, + + _parent: function () { + return $(this.options.addToFormSelector); + }, + + _cartCheckout: function () { + var self = this; + self._disableButton(); + + fullScreenLoader.startLoader(); + + $.ajax({ + url: self.options.submitUrl, + data: { 'page' : 'cart'}, + type: 'POST', + dataType: 'json', + showLoader: true, + success: function (data) { + console.log(data) + self.renderIframe(data); + }, + error: function (request) { + self._orderError(request); + self.enableButton(); + } + }) + }, + + orderSuccess: function (data) { + var self = this; + self.enableButton(); + fullScreenLoader.startLoader(); + + $.ajax({ + url: self.options.callbackURL, + data: data, + type: 'POST', + dataType: 'json', + showLoader: true, + success: function (data) { + // debugger; + console.log("Payment complete data") + console.log(data) + var successUrl = url.build('checkout/onepage/success', {}) + console.log(successUrl) + + window.location.href = successUrl; + }, + error: function (error) { + console.log("Payment complete fail") + } + }) + }, + + renderIframe: function(data) { + // debugger; + var self = this; + + var options = { + key: self.options.key, + name: 'Razorpay', + amount: data.totalAmount, + handler: function (data) { + + console.log("data in handler", data) + fullScreenLoader.startLoader(); + + self.orderSuccess(data); + }, + order_id: data.rzp_order_id, + modal: { + ondismiss: function(data) { + //reset the cart + self.resetCart(data); + // fullScreenLoader.stopLoader(); + // self.isPaymentProcessing.reject("Payment Closed"); + // self.isPlaceOrderActionAllowed(true); + self.enableButton(); + + } + }, + notes: { + }, + // callback_url : self.options.callbackURL, + prefill: { + name: '', + contact: '', + email: '' + }, + _: { + integration: 'magento', + // integration_version: '', + // integration_parent_version: data.maze_version, + integration_type: 'plugin', + } + }; + + // if (data.quote_currency !== 'INR') + // { + // options.display_currency = data.quote_currency; + // options.display_amount = data.quote_amount; + // } + + this.rzp = new Razorpay(options); + + this.rzp.open(); + }, + + _orderError: function (request) { + console.log(request); + this.enableButton(); + }, + + _disableButton: function () { + var button = this._parent().find(this.options.buttonSelector); + button.addClass('disabled'); + // button.find('span').text($t('One Click Checkout')); + // button.attr('title', $t('One Click Checkout')); + }, + + enableButton: function () { + var button = this._parent().find(this.options.buttonSelector); + button.removeClass('disabled'); + // button.find('span').text($t('One Click Checkout')); + // button.attr('title', $t('One Click Checkout')); + } + }); + + return $.pmclain.oneClickButton; +}); \ No newline at end of file From 1d3b68ac553ecd72758445dc32ef6fd35e43fbcc Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Wed, 6 Mar 2024 08:16:59 +0530 Subject: [PATCH 02/67] Commented devstack mode --- view/frontend/templates/oneclick/buynow.phtml | 4 ++-- view/frontend/templates/oneclick/magiccart.phtml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/view/frontend/templates/oneclick/buynow.phtml b/view/frontend/templates/oneclick/buynow.phtml index 026c2e48..a9fa9f41 100644 --- a/view/frontend/templates/oneclick/buynow.phtml +++ b/view/frontend/templates/oneclick/buynow.phtml @@ -38,7 +38,7 @@ - --> --> From b81cc2fdb1a03f0d6ec07a1ce757c2d1b59544c7 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Wed, 6 Mar 2024 09:25:32 +0530 Subject: [PATCH 03/67] Button fix --- Model/Resolver/CouponList.php | 2 ++ view/frontend/layout/catalog_product_view.xml | 4 +-- view/frontend/templates/oneclick/buynow.phtml | 31 ++++++++++--------- view/frontend/web/css/magic.css | 3 ++ 4 files changed, 24 insertions(+), 16 deletions(-) diff --git a/Model/Resolver/CouponList.php b/Model/Resolver/CouponList.php index f8e0b27e..b500db5f 100644 --- a/Model/Resolver/CouponList.php +++ b/Model/Resolver/CouponList.php @@ -51,6 +51,8 @@ public function resolve( $ruleCollection = $this->ruleCollectionFactory->create(); + $currentDate = (new \DateTime())->format(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT); + // Add filters to include only active and non-expired rules $ruleCollection->addFieldToFilter('is_active', 1); diff --git a/view/frontend/layout/catalog_product_view.xml b/view/frontend/layout/catalog_product_view.xml index f4dff8a9..636cc7ca 100644 --- a/view/frontend/layout/catalog_product_view.xml +++ b/view/frontend/layout/catalog_product_view.xml @@ -2,8 +2,8 @@ - - + + \ No newline at end of file diff --git a/view/frontend/templates/oneclick/buynow.phtml b/view/frontend/templates/oneclick/buynow.phtml index a9fa9f41..1a502e96 100644 --- a/view/frontend/templates/oneclick/buynow.phtml +++ b/view/frontend/templates/oneclick/buynow.phtml @@ -24,18 +24,6 @@ ?> - + + --> + +
+ ", + "sku": "getProduct()->getSku(); ?>", + "callbackURL": "getUrl('razorpay/oneclick/completeorder') ?>", + "key": "" + } + }' + > + +
--> diff --git a/view/frontend/web/template/magic/minicart.html b/view/frontend/web/template/magic/minicart.html new file mode 100644 index 00000000..41cc19db --- /dev/null +++ b/view/frontend/web/template/magic/minicart.html @@ -0,0 +1,98 @@ + +
+ + + + + +
+ +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + +
+
+ + + +
+
    + +
+
+
+ + + + +

+
+
+ + + +
+
+
+
+ +
+
+ + + +
+
+ +
+ +
+
+ From 357e03b247f758d35db2ad098e6d5db82ac20c43 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Tue, 12 Mar 2024 15:32:27 +0530 Subject: [PATCH 07/67] Removed dummy button --- view/frontend/web/template/magic/minicart.html | 1 - 1 file changed, 1 deletion(-) diff --git a/view/frontend/web/template/magic/minicart.html b/view/frontend/web/template/magic/minicart.html index 41cc19db..a0215764 100644 --- a/view/frontend/web/template/magic/minicart.html +++ b/view/frontend/web/template/magic/minicart.html @@ -18,7 +18,6 @@
-
+
+ + +
From 3128b8bcb832b45b02c37e1b588f0938aaac6a10 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Wed, 13 Mar 2024 13:59:30 +0530 Subject: [PATCH 09/67] Added cart empty check condition for minicart --- .../frontend/web/template/magic/minicart.html | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/view/frontend/web/template/magic/minicart.html b/view/frontend/web/template/magic/minicart.html index 8cfda996..8e988a7e 100644 --- a/view/frontend/web/template/magic/minicart.html +++ b/view/frontend/web/template/magic/minicart.html @@ -78,15 +78,17 @@
-
- - -
+ +
+ + +
+
From 0a14050e69c535242a20274acd213f53e2316f38 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Thu, 14 Mar 2024 12:18:25 +0530 Subject: [PATCH 10/67] Bug fix for auto discount --- Controller/OneClick/PlaceOrder.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Controller/OneClick/PlaceOrder.php b/Controller/OneClick/PlaceOrder.php index c6e7d341..03b6bf45 100644 --- a/Controller/OneClick/PlaceOrder.php +++ b/Controller/OneClick/PlaceOrder.php @@ -190,12 +190,19 @@ public function execute() $productImageUrl = $store->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) . 'catalog/product' .$product->getImage(); $productUrl = $product->getProductUrl(); + $offerPrice = $quoteItem->getPrice() * 100; + // Check if the item has applied discounts + if ($quoteItem->getDiscountAmount()) { + // Get the discount amount applied to the item + $offerPrice = abs($quoteItem->getDiscountAmount()) * 100; + } + $lineItems[] = [ 'type' => 'e-commerce', 'sku' => $quoteItem->getSku(), 'variant_id' => $quoteItem->getProductId(), 'price' => $quoteItem->getPrice()*100, - 'offer_price' => $quoteItem->getPrice()*100, + 'offer_price' => $offerPrice, 'tax_amount' => 0, 'quantity' => $quoteItem->getQty(), 'name' => $quoteItem->getName(), @@ -204,8 +211,8 @@ public function execute() 'product_url' => $productUrl, ]; - $totalAmount += ($quoteItem->getQty() * $quoteItem->getPrice()) * 100; } + $totalAmount = $quote->getGrandTotal(); } catch (LocalizedException $e) { return $resultJson->setData([ From c95eaa1432ae759e316c40b5a563260bda9f67d9 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Mon, 18 Mar 2024 13:17:35 +0530 Subject: [PATCH 11/67] Refactoring the code and handled auto coupon --- Controller/OneClick/CompleteOrder.php | 215 +++++++++--------- Controller/OneClick/PlaceOrder.php | 113 ++++----- Model/Config.php | 18 ++ view/frontend/templates/oneclick/buynow.phtml | 54 ++--- .../templates/oneclick/magiccart.phtml | 22 +- view/frontend/web/js/magic-buy-now.js | 15 +- view/frontend/web/js/magic-cart.js | 22 +- 7 files changed, 226 insertions(+), 233 deletions(-) diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index a08a475f..ebb46bc5 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -93,8 +93,8 @@ class CompleteOrder extends Action protected $_order = null; protected const STATUS_PROCESSING = 'processing'; - protected const COD = 'cashondelivery'; - protected const RAZORPAY = 'razorpay'; + protected const COD = 'cashondelivery'; + protected const RAZORPAY = 'razorpay'; /** * CompleteOrder constructor. @@ -108,38 +108,39 @@ class CompleteOrder extends Action * @param ProductRepositoryInterface $productRepository */ public function __construct( - Context $context, - Http $request, - JsonFactory $jsonFactory, - CartManagementInterface $cartManagement, - Data $priceHelper, - PaymentMethod $paymentMethod, - \Razorpay\Magento\Model\Config $config, - \Psr\Log\LoggerInterface $logger, - ProductRepositoryInterface $productRepository, - Item $quoteItem, - QuoteIdMaskFactory $quoteIdMaskFactory, - QuoteIdMaskResourceModel $quoteIdMaskResourceModel, - StoreManagerInterface $storeManager, - \Magento\Quote\Api\CartRepositoryInterface $cartRepositoryInterface, - \Magento\Sales\Model\Order $order, - \Magento\Sales\Model\Service\InvoiceService $invoiceService, + Context $context, + Http $request, + JsonFactory $jsonFactory, + CartManagementInterface $cartManagement, + Data $priceHelper, + PaymentMethod $paymentMethod, + \Razorpay\Magento\Model\Config $config, + \Psr\Log\LoggerInterface $logger, + ProductRepositoryInterface $productRepository, + Item $quoteItem, + QuoteIdMaskFactory $quoteIdMaskFactory, + QuoteIdMaskResourceModel $quoteIdMaskResourceModel, + StoreManagerInterface $storeManager, + \Magento\Quote\Api\CartRepositoryInterface $cartRepositoryInterface, + \Magento\Sales\Model\Order $order, + \Magento\Sales\Model\Service\InvoiceService $invoiceService, \Magento\Sales\Model\Order\Email\Sender\InvoiceSender $invoiceSender, - \Magento\Framework\DB\Transaction $transaction, - \Magento\Sales\Model\Order\Email\Sender\OrderSender $orderSender, - \Magento\Checkout\Model\Session $checkoutSession, - CollectionFactory $collectionFactory, - StateMap $stateNameMap, - CartConverter $cartConverter, - CustomerConsent $customerConsent - ) { + \Magento\Framework\DB\Transaction $transaction, + \Magento\Sales\Model\Order\Email\Sender\OrderSender $orderSender, + \Magento\Checkout\Model\Session $checkoutSession, + CollectionFactory $collectionFactory, + StateMap $stateNameMap, + CartConverter $cartConverter, + CustomerConsent $customerConsent + ) + { parent::__construct($context); $this->request = $request; $this->resultJsonFactory = $jsonFactory; $this->cartManagement = $cartManagement; $this->priceHelper = $priceHelper; $this->config = $config; - $this->rzp = $paymentMethod->setAndGetRzpApiInstance(); + $this->rzp = $paymentMethod->setAndGetRzpApiInstance(); $this->logger = $logger; $this->productRepository = $productRepository; $this->quoteItem = $quoteItem; @@ -148,17 +149,17 @@ public function __construct( $this->storeManager = $storeManager; $this->cartRepositoryInterface = $cartRepositoryInterface; $this->order = $order; - $this->invoiceService = $invoiceService; - $this->invoiceSender = $invoiceSender; - $this->transaction = $transaction; - $this->orderSender = $orderSender; - $this->checkoutSession = $checkoutSession; - $this->collectionFactory = $collectionFactory; - $this->stateNameMap = $stateNameMap; + $this->invoiceService = $invoiceService; + $this->invoiceSender = $invoiceSender; + $this->transaction = $transaction; + $this->orderSender = $orderSender; + $this->checkoutSession = $checkoutSession; + $this->collectionFactory = $collectionFactory; + $this->stateNameMap = $stateNameMap; $this->cartConverter = $cartConverter; $this->customerConsent = $customerConsent; $this->resultRedirectFactory = $context->getResultFactory();; - $this->orderStatus = static::STATUS_PROCESSING; + $this->orderStatus = static::STATUS_PROCESSING; $this->authorizeCommand = new AuthorizeCommand(); $this->captureCommand = new CaptureCommand(); } @@ -189,8 +190,7 @@ public function execute() $this->logger->info('graphQL: customerCartId ' . $customerCartId); $isCustomerConsentSet = false; - if($isCustomerConsentSet === true) - { + if ($isCustomerConsentSet === true) { // Subscribe news letter based on customer consent data $subscribeNewsLetter = $this->customerConsent->subscribeCustomer($customerCartId, $email); $this->logger->info('graphQL: subscribed ' . $subscribeNewsLetter); @@ -198,19 +198,29 @@ public function execute() $orderId = $this->cartManagement->placeOrder($cartId); $order = $this->order->load($orderId); - + $order->setEmailSent(0); - if ($order) - { - if ($order->getStatus() === 'pending') - { - $order->setState(static::STATUS_PROCESSING)->setStatus($this->orderStatus); + if ($order) { + // Return to failure page if payment is failed. + if ($rzpPaymentData->status === 'failed') { + $result = [ + 'status' => 'failed' + ]; + + return $resultJson->setData($result); + } + + if ($order->getStatus() === 'pending') { + if ($rzpPaymentData->status === 'pending' && $rzpPaymentData->method === 'cod') { + $order->setStatus(\Magento\Sales\Model\Order::STATE_PENDING_PAYMENT)->setStatus($this->orderStatus); + } else { + $order->setState(\Magento\Sales\Model\Order::STATE_PROCESSING)->setStatus($this->orderStatus); + } $this->logger->info('graphQL: Order Status Updated to ' . $this->orderStatus); } - if(!empty($rzpOrderData->offers)) - { + if (!empty($rzpOrderData->offers)) { $discountAmount = $order->getDiscountAmount(); $codFee = $rzpOrderData->cod_fee; @@ -218,19 +228,16 @@ public function execute() $rzpPromotionAmount = 0; - foreach($rzpOrderData->promotions as $promotion) - { - if (empty($promotion['code']) === false) - { + foreach ($rzpOrderData->promotions as $promotion) { + if (empty($promotion['code']) === false) { $rzpPromotionAmount = $promotion['value']; } } $offerDiff = $rzpOrderData->line_items_total + $rzpOrderData->shipping_fee + $codFee - $totalPaid - $rzpPromotionAmount; - if($offerDiff > 0) - { - $offerDiscount = ($offerDiff/100); + if ($offerDiff > 0) { + $offerDiscount = ($offerDiff / 100); // abs is used here as discount amount is returned as minus from order object. $newDiscountAmount = abs($discountAmount) + $offerDiscount; @@ -248,14 +255,13 @@ public function execute() $payment = $order->getPayment(); $payment->setLastTransId($rzpPaymentId) - ->setTransactionId($rzpPaymentId) - ->setIsTransactionClosed(true) - ->setShouldCloseParentTransaction(true); + ->setTransactionId($rzpPaymentId) + ->setIsTransactionClosed(true) + ->setShouldCloseParentTransaction(true); $payment->setParentTransactionId($payment->getTransactionId()); - if ($this->config->getPaymentAction() === \Razorpay\Magento\Model\PaymentMethod::ACTION_AUTHORIZE_CAPTURE) - { + if ($this->config->getPaymentAction() === \Razorpay\Magento\Model\PaymentMethod::ACTION_AUTHORIZE_CAPTURE) { $payment->addTransactionCommentsToOrder( "$rzpPaymentId", $this->captureCommand->execute( @@ -265,9 +271,7 @@ public function execute() ), "" ); - } - else - { + } else { $payment->addTransactionCommentsToOrder( "$rzpPaymentId", $this->authorizeCommand->execute( @@ -285,11 +289,10 @@ public function execute() $transaction->save(); - $this->logger->info('Payment authorized completed for id : '. $order->getIncrementId()); + $this->logger->info('Payment authorized completed for id : ' . $order->getIncrementId()); if ($order->canInvoice() && $this->config->canAutoGenerateInvoice() - && $rzpOrderData->status === 'paid') - { + && $rzpOrderData->status === 'paid') { $invoice = $this->invoiceService->prepareInvoice($order); $invoice->setRequestedCaptureCase(\Magento\Sales\Model\Order\Invoice::CAPTURE_ONLINE); $invoice->setTransactionId($rzpPaymentId); @@ -297,8 +300,8 @@ public function execute() $invoice->save(); $this->logger->info('graphQL: Created Invoice for ' - . 'order_id ' . $rzpOrderId . ', ' - . 'rzp_payment_id ' . $rzpPaymentId); + . 'order_id ' . $rzpOrderId . ', ' + . 'rzp_payment_id ' . $rzpPaymentId); $transactionSave = $this->transaction ->addObject($invoice) @@ -311,32 +314,25 @@ public function execute() __('Notified customer about invoice #%1.', $invoice->getId()) )->setIsCustomerNotified(true); - $this->logger->info('Invoice generated for id : '. $order->getIncrementId()); - } - else if($rzpOrderData->status === 'paid' and - ($order->canInvoice() === false or - $this->config->canAutoGenerateInvoice() === false)) - { - $this->logger->info('Invoice generation not possible for id : '. $order->getIncrementId()); + $this->logger->info('Invoice generated for id : ' . $order->getIncrementId()); + } else if ($rzpOrderData->status === 'paid' and + ($order->canInvoice() === false or + $this->config->canAutoGenerateInvoice() === false)) { + $this->logger->info('Invoice generation not possible for id : ' . $order->getIncrementId()); } - try - { + try { $this->checkoutSession->setRazorpayMailSentOnSuccess(true); $this->orderSender->send($order); $this->checkoutSession->unsRazorpayMailSentOnSuccess(); - } - catch (\Magento\Framework\Exception\MailException $e) - { + } catch (\Magento\Framework\Exception\MailException $e) { $this->logger->critical('graphQL: ' - . 'Razorpay Error:' . $e->getMessage()); + . 'Razorpay Error:' . $e->getMessage()); throw new GraphQlInputException(__('Razorpay Error: %1.', $e->getMessage())); - } - catch (\Exception $e) - { + } catch (\Exception $e) { $this->logger->critical('graphQL: ' - . 'Error:' . $e->getMessage()); + . 'Error:' . $e->getMessage()); throw new GraphQlInputException(__('Error: %1.', $e->getMessage())); } @@ -346,8 +342,7 @@ public function execute() ->setLastSuccessQuoteId($order->getQuoteId()) ->setLastQuoteId($order->getQuoteId()) ->clearHelperData(); - if (empty($order) === false) - { + if (empty($order) === false) { $this ->checkoutSession ->setLastOrderId($order->getId()) @@ -382,7 +377,7 @@ public function updateDiscountAmount($orderId, $newDiscountAmount, $offerAmount, $order->setBaseGrandTotal($totalBaseGrandTotal - $offerAmount); $order->setGrandTotal($totalGrandTotal - $offerAmount); - $order->setTotalPaid($totalPaid/100); + $order->setTotalPaid($totalPaid / 100); $comment = __('Razorpay offer applied ₹%1.', $offerAmount); @@ -425,28 +420,23 @@ protected function updateQuote($quote, $rzpOrderData, $rzpPaymentData) $quote->getShippingAddress()->addData($shipping['address']); $shippingMethod = 'NA'; - if(empty($carrierCode) === false && empty($methodCode) === false) - { - $shippingMethod = $carrierCode ."_". $methodCode; + if (empty($carrierCode) === false && empty($methodCode) === false) { + $shippingMethod = $carrierCode . "_" . $methodCode; } - $shippingAddress=$quote->getShippingAddress(); + $shippingAddress = $quote->getShippingAddress(); $shippingAddress->setCollectShippingRates(true) - ->collectShippingRates() - ->setShippingMethod($shippingMethod); + ->collectShippingRates() + ->setShippingMethod($shippingMethod); // Todo: Loop through promotions and fetch the discount data. - if(isset($rzpOrderData->promotions[0]->code) == true) - { - $quote->setCouponCode($rzpOrderData->promotions[0]->code); + if (isset($rzpOrderData->promotions[0]->code) == true) { + $quote->setCouponCode($rzpOrderData->promotions[0]->code); } - if($rzpPaymentData->method === 'cod') - { + if ($rzpPaymentData->method === 'cod') { $paymentMethod = static::COD; - } - else - { + } else { $paymentMethod = static::RAZORPAY; } @@ -456,7 +446,7 @@ protected function updateQuote($quote, $rzpOrderData, $rzpPaymentData) $quote->getPayment()->importData(['method' => $paymentMethod]); $quote->save(); - + } protected function getRegionCode($country, $state) @@ -479,12 +469,12 @@ protected function getAddress($rzpAddress, $regionCode, $email) $name = explode(' ', $rzpAddress->name); return [ - 'email' => $email, //buyer email id - 'address' =>[ - 'firstname' => $name[0], //address Details - 'lastname' => empty($name[1]) === false ? $name[1] : '.', - 'street' => $rzpAddress->line1, - 'city' => $rzpAddress->city, + 'email' => $email, //buyer email id + 'address' => [ + 'firstname' => $name[0], //address Details + 'lastname' => empty($name[1]) === false ? $name[1] : '.', + 'street' => $rzpAddress->line1, + 'city' => $rzpAddress->city, 'country_id' => strtoupper($rzpAddress->country), 'region' => $regionCode, 'postcode' => $rzpAddress->zipcode, @@ -496,8 +486,7 @@ protected function getAddress($rzpAddress, $regionCode, $email) protected function validateSignature($request) { - if (empty($request['error']) === false) - { + if (empty($request['error']) === false) { $this ->logger ->critical("Validate: Payment Failed or error from gateway"); @@ -507,11 +496,11 @@ protected function validateSignature($request) throw new \Exception("Payment Failed or error from gateway"); } - $this->logger->info('razorpay_payment_id = '. $request['razorpay_payment_id']); - $this->logger->info('razorpay_order_id = '. $request['razorpay_order_id']); - $this->logger->info('razorpay_signature = '. $request['razorpay_signature']); - - + $this->logger->info('razorpay_payment_id = ' . $request['razorpay_payment_id']); + $this->logger->info('razorpay_order_id = ' . $request['razorpay_order_id']); + $this->logger->info('razorpay_signature = ' . $request['razorpay_signature']); + + $attributes = array( 'razorpay_payment_id' => $request['razorpay_payment_id'], 'razorpay_order_id' => $request['razorpay_order_id'], diff --git a/Controller/OneClick/PlaceOrder.php b/Controller/OneClick/PlaceOrder.php index 03b6bf45..13b06354 100644 --- a/Controller/OneClick/PlaceOrder.php +++ b/Controller/OneClick/PlaceOrder.php @@ -7,13 +7,14 @@ use Magento\Framework\Controller\Result\JsonFactory; use Magento\Framework\Exception\LocalizedException; use Magento\Quote\Api\CartManagementInterface; +use Magento\Quote\Model\QuoteFactory; use Razorpay\Magento\Model\QuoteBuilderFactory; use Razorpay\Magento\Model\QuoteBuilder; use Magento\Framework\Pricing\Helper\Data; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Store\Model\ScopeInterface; use Razorpay\Magento\Model\PaymentMethod; -use Razorpay\Magento\Model\Config; +use Razorpay\Magento\Model\Config as RazorpayConfig; use Razorpay\Api\Api; use Magento\Framework\App\Request\Http; use Magento\Catalog\Api\ProductRepositoryInterface; @@ -50,7 +51,7 @@ class PlaceOrder extends Action /** * @var ScopeConfigInterface */ - protected $config; + protected $scopeConfig; /** * @var \Psr\Log\LoggerInterface @@ -75,48 +76,54 @@ class PlaceOrder extends Action protected $cart; protected $checkoutSession; - + protected $resourceConnection; protected $sequenceManager; + protected $quoteFactory; + + protected $config; + /** * PlaceOrder constructor. * @param Http $request * @param Context $context * @param JsonFactory $jsonFactory * @param CartManagementInterface $cartManagement - * @param ScopeConfigInterface $config + * @param RazorpayConfig $config * @param PaymentMethod $paymentMethod * @param \Psr\Log\LoggerInterface $logger * @param QuoteBuilderFactory $quoteBuilderFactory * @param ProductRepositoryInterface $productRepository */ public function __construct( - Context $context, - Http $request, - JsonFactory $jsonFactory, - CartManagementInterface $cartManagement, - PaymentMethod $paymentMethod, - ScopeConfigInterface $config, - \Psr\Log\LoggerInterface $logger, - QuoteBuilderFactory $quoteBuilderFactory, - ProductRepositoryInterface $productRepository, - QuoteIdToMaskedQuoteIdInterface $maskedQuoteIdInterface, - QuoteIdMaskFactory $quoteIdMaskFactory, - QuoteIdMaskResourceModel $quoteIdMaskResourceModel, - StoreManagerInterface $storeManager, - \Magento\Checkout\Model\Cart $cart, - Session $checkoutSession, + Context $context, + Http $request, + JsonFactory $jsonFactory, + CartManagementInterface $cartManagement, + PaymentMethod $paymentMethod, + RazorpayConfig $config, + \Psr\Log\LoggerInterface $logger, + QuoteBuilderFactory $quoteBuilderFactory, + ProductRepositoryInterface $productRepository, + QuoteIdToMaskedQuoteIdInterface $maskedQuoteIdInterface, + QuoteIdMaskFactory $quoteIdMaskFactory, + QuoteIdMaskResourceModel $quoteIdMaskResourceModel, + StoreManagerInterface $storeManager, + \Magento\Checkout\Model\Cart $cart, + Session $checkoutSession, \Magento\Framework\App\ResourceConnection $resourceConnection, - SequenceManager $sequenceManager - ) { + SequenceManager $sequenceManager, + QuoteFactory $quoteFactory + ) + { parent::__construct($context); $this->request = $request; $this->resultJsonFactory = $jsonFactory; $this->cartManagement = $cartManagement; $this->config = $config; - $this->rzp = $paymentMethod->setAndGetRzpApiInstance(); + $this->rzp = $paymentMethod->setAndGetRzpApiInstance(); $this->logger = $logger; $this->quoteBuilderFactory = $quoteBuilderFactory; $this->productRepository = $productRepository; @@ -128,14 +135,14 @@ public function __construct( $this->checkoutSession = $checkoutSession; $this->resourceConnection = $resourceConnection; $this->sequenceManager = $sequenceManager; + $this->quoteFactory = $quoteFactory; } public function execute() { $params = $this->request->getParams(); - if(isset($params['page']) && $params['page'] == 'cart') - { + if (isset($params['page']) && $params['page'] == 'cart') { $cartItems = $this->cart->getQuote()->getAllVisibleItems(); $quoteId = $this->cart->getQuote()->getId(); $totals = $this->cart->getQuote()->getTotals(); @@ -144,8 +151,7 @@ public function execute() $customerId = $quote->getCustomerId(); // Set customer as guest to update the quote during checkout journey. - if($customerId) - { + if ($customerId) { $this->logger->info('graphQL: customer: ' . json_encode($customerId)); $connection = $this->resourceConnection->getConnection(); @@ -153,21 +159,20 @@ public function execute() $connection->update($tableName, ['customer_id' => null, 'customer_is_guest' => 1], ['entity_id = ?' => $quoteId]); } - } - else - { + } else { /** @var QuoteBuilder $quoteBuilder */ $quoteBuilder = $this->quoteBuilderFactory->create(); $quote = $quoteBuilder->createQuote(); $quoteId = $quote->getId(); + $quote = $this->quoteFactory->create()->load($quoteId); $totals = $quote->getTotals(); + $quote->collectTotals(); $cartItems = $quote->getAllVisibleItems(); } $resultJson = $this->resultJsonFactory->create(); - try - { + try { $maskedId = $this->maskedQuoteIdInterface->execute($quoteId); if ($maskedId === '') { @@ -187,21 +192,23 @@ public function execute() $productId = $quoteItem->getProductId(); $product = $this->productRepository->getById($productId); - $productImageUrl = $store->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) . 'catalog/product' .$product->getImage(); + $productImageUrl = $store->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) . 'catalog/product' . $product->getImage(); $productUrl = $product->getProductUrl(); $offerPrice = $quoteItem->getPrice() * 100; // Check if the item has applied discounts if ($quoteItem->getDiscountAmount()) { // Get the discount amount applied to the item - $offerPrice = abs($quoteItem->getDiscountAmount()) * 100; + $discountAmount = abs($quoteItem->getDiscountAmount()); + + $offerPrice = ($quoteItem->getPrice() - $discountAmount) * 100; } $lineItems[] = [ 'type' => 'e-commerce', 'sku' => $quoteItem->getSku(), 'variant_id' => $quoteItem->getProductId(), - 'price' => $quoteItem->getPrice()*100, + 'price' => $quoteItem->getPrice() * 100, 'offer_price' => $offerPrice, 'tax_amount' => 0, 'quantity' => $quoteItem->getQty(), @@ -212,7 +219,7 @@ public function execute() ]; } - $totalAmount = $quote->getGrandTotal(); + $totalAmount = $quote->getGrandTotal() * 100; } catch (LocalizedException $e) { return $resultJson->setData([ @@ -228,41 +235,41 @@ public function execute() $storeScope = \Magento\Store\Model\ScopeInterface::SCOPE_STORE; - $paymentAction = $this->config->getValue('payment/razorpay/rzp_payment_action', $storeScope); + $paymentAction = $this->config->getPaymentAction(); $paymentCapture = 1; - if ($paymentAction === 'authorize') - { + if ($paymentAction === 'authorize') { $paymentCapture = 0; } + $rzpKey = $this->config->getKeyId(); + $merchantName = $this->config->getMerchantNameOverride(); - $orderNumber = $this->getLastOrderId($quote); + $this->getLastOrderId($quote); $razorpay_order = $this->rzp->order->create([ - 'amount' => $totalAmount, - 'receipt' => (string)$quote->getReservedOrderId() ?? 'order pending', - 'currency' => $this->storeManager->getStore()->getBaseCurrencyCode(), + 'amount' => $totalAmount, + 'receipt' => (string)$quote->getReservedOrderId() ?? 'order pending', + 'currency' => $this->storeManager->getStore()->getBaseCurrencyCode(), 'payment_capture' => $paymentCapture, - 'app_offer' => 0, - 'notes' => [ + 'app_offer' => 0, + 'notes' => [ 'cart_mask_id' => $maskedId, - 'cart_id' => $quoteId + 'cart_id' => $quoteId ], 'line_items_total' => $totalAmount, 'line_items' => $lineItems ]); - if (null !== $razorpay_order && !empty($razorpay_order->id)) - { + if (null !== $razorpay_order && !empty($razorpay_order->id)) { $this->logger->info('graphQL: Razorpay Order ID: ' . $razorpay_order->id); $result = [ - 'status' => 'success', - 'rzp_order_id' => $razorpay_order->id, - 'message' => 'Razorpay Order created successfully' + 'status' => 'success', + 'rzp_key_id' => $rzpKey, + 'merchant_name' => $merchantName, + 'rzp_order_id' => $razorpay_order->id, + 'message' => 'Razorpay Order created successfully' ]; - } - else - { + } else { $this->logger->critical('graphQL: Razorpay Order not generated. Something went wrong'); $result = [ diff --git a/Model/Config.php b/Model/Config.php index ea55099f..56a3d2ce 100644 --- a/Model/Config.php +++ b/Model/Config.php @@ -27,6 +27,9 @@ class Config const CUSTOM_PAID_ORDER_STATUS = 'custom_paid_order_status'; const ENABLE_UPDATE_ORDER_CRON_V1 = 'enable_update_order_cron_v1'; const ENABLED_DEBUG_MODE = 'enable_debug_mode'; + const KEY_MAGIC_CHECKOUT_STATUS = 'activate_magic'; + const KEY_MAGIC_BUY_NOW_STATUS = 'activate_magic_buy_now'; + const KEY_MAGIC_MINI_CART_STATUS = 'activate_magic_mini_cart'; /** * @var string */ @@ -123,6 +126,21 @@ public function getNewOrderStatus() return $this->getConfigData(self::KEY_NEW_ORDER_STATUS); } + public function getMagicStatus() + { + return $this->getConfigData(self::KEY_MAGIC_CHECKOUT_STATUS); + } + + public function getMagicBuyNowStatus() + { + return $this->getConfigData(self::KEY_MAGIC_BUY_NOW_STATUS); + } + + public function getMagicMinicartStatus() + { + return $this->getConfigData(self::KEY_MAGIC_MINI_CART_STATUS); + } + /** * @param int $storeId * @return $this diff --git a/view/frontend/templates/oneclick/buynow.phtml b/view/frontend/templates/oneclick/buynow.phtml index 1a502e96..1c65710b 100644 --- a/view/frontend/templates/oneclick/buynow.phtml +++ b/view/frontend/templates/oneclick/buynow.phtml @@ -1,32 +1,23 @@ get(\Razorpay\Magento\Model\Config::class); - // Get the store manager - $storeManager = $objectManager->get(\Magento\Store\Model\StoreManagerInterface::class); - $scopeConfig = $objectManager->get(ScopeConfigInterface::class); - - $code = 'razorpay'; - $magicActiveField = 'activate_magic'; - $buynowActiveField = 'activate_magic_buy_now'; - $keyField = 'key_id'; - - $isMagicEnabled = $scopeConfig->getValue('payment/' . $code . '/' . $magicActiveField, \Magento\Store\Model\ScopeInterface::SCOPE_STORE); - $isBuynowEnabled = $scopeConfig->getValue('payment/' . $code . '/' . $buynowActiveField, \Magento\Store\Model\ScopeInterface::SCOPE_STORE); - $rzpKey = $scopeConfig->getValue('payment/' . $code . '/' . $keyField, \Magento\Store\Model\ScopeInterface::SCOPE_STORE); +$isMagicEnabled = $configData->getMagicStatus(); +$isBuyNowEnabled = $configData->getMagicBuyNowStatus(); ?> - - + + - -
- getUrl('razorpay/oneclick/placeorder') ?>", "sku": "getProduct()->getSku(); ?>", - "callbackURL": "getUrl('razorpay/oneclick/completeorder') ?>", - "key": "" } }' - > - -
+ > + +
- + diff --git a/view/frontend/templates/oneclick/magiccart.phtml b/view/frontend/templates/oneclick/magiccart.phtml index 1b7347d4..dc067d35 100644 --- a/view/frontend/templates/oneclick/magiccart.phtml +++ b/view/frontend/templates/oneclick/magiccart.phtml @@ -1,7 +1,4 @@ get(\Magento\Store\Model\StoreManagerInterface::class); -$scopeConfig = $objectManager->get(ScopeConfigInterface::class); - -$code = 'razorpay'; -$magicActiveField = 'activate_magic'; -$keyField = 'key_id'; +$configData = $objectManager->get(\Razorpay\Magento\Model\Config::class); -$isMagicEnabled = $scopeConfig->getValue('payment/' . $code . '/' . $magicActiveField, \Magento\Store\Model\ScopeInterface::SCOPE_STORE); -$rzpKey = $scopeConfig->getValue('payment/' . $code . '/' . $keyField, \Magento\Store\Model\ScopeInterface::SCOPE_STORE); +$isMagicEnabled = $configData->getMagicStatus(); $cartData = $objectManager->create('Magento\Checkout\Model\Cart')->getQuote()->getAllVisibleItems(); $cartDataCount = count( $cartData ); @@ -30,13 +20,7 @@ $cartDataCount = count( $cartData );
", - "callbackURL": "getUrl('razorpay/oneclick/completeorder') ?>", - "key": "" - } - + "Razorpay_Magento/js/magic-cart":{} }' class="isDisabled()) ? ' disabled' : '' ?>" diff --git a/view/frontend/web/js/magic-buy-now.js b/view/frontend/web/js/magic-buy-now.js index d7d2e471..db113e4e 100644 --- a/view/frontend/web/js/magic-buy-now.js +++ b/view/frontend/web/js/magic-buy-now.js @@ -12,9 +12,6 @@ define([ $.widget('pmclain.oneClickButton', { options: { addToFormSelector: '#product_addtocart_form', - submitUrl: '', - callbackURL: '', - key: '', actionSelector: '.actions', buttonTemplateSelector: '#occ-template', buttonSelector: '#product-oneclick-button', @@ -78,8 +75,10 @@ define([ self._disableButton(); self.toggleLoader(true); + var placeOrder = url.build('razorpay/oneclick/placeorder', {}) + $.ajax({ - url: self.options.submitUrl, + url: placeOrder, data: self._parent().serialize(), type: 'POST', dataType: 'json', @@ -98,8 +97,10 @@ define([ self.enableButton(); fullScreenLoader.startLoader(); + var completeOrder = url.build('razorpay/oneclick/completeorder', {}) + $.ajax({ - url: self.options.callbackURL, + url: completeOrder, data: data, type: 'POST', dataType: 'json', @@ -119,8 +120,8 @@ define([ var self = this; var options = { - key: self.options.key, - name: 'Razorpay', + key: data.rzp_key_id, + name: data.merchant_name, amount: data.totalAmount, handler: function (data) { self.toggleLoader(true); diff --git a/view/frontend/web/js/magic-cart.js b/view/frontend/web/js/magic-cart.js index f2d784f0..ce737a91 100644 --- a/view/frontend/web/js/magic-cart.js +++ b/view/frontend/web/js/magic-cart.js @@ -12,9 +12,6 @@ define([ $.widget('pmclain.oneClickButton', { options: { addToFormSelector: '#cart-occ-div', - submitUrl: '', - callbackURL: '', - key: '', actionSelector: '.action', buttonTemplateSelector: '#cart-occ-div', buttonSelector: '#cart-occ-template', @@ -112,6 +109,8 @@ define([ }, error: function (error) { console.log("Payment complete fail") + var failureUrl = url.build('checkout/onepage/failure', {}) + window.location.href = failureUrl; } }) }, @@ -121,8 +120,8 @@ define([ var self = this; var options = { - key: self.options.key, - name: 'Razorpay', + key: data.rzp_key_id, + name: data.merchant_name, amount: data.totalAmount, handler: function (data) { @@ -132,7 +131,7 @@ define([ }, order_id: data.rzp_order_id, modal: { - ondismiss: function(data) { + ondismiss: function (data) { //reset the cart self.resetCart(data); // fullScreenLoader.stopLoader(); @@ -142,8 +141,7 @@ define([ } }, - notes: { - }, + notes: {}, // callback_url : self.options.callbackURL, prefill: { name: '', @@ -164,6 +162,14 @@ define([ // options.display_amount = data.quote_amount; // } + var RazorpayConfigMagento = { + "config": { + "api": "https://api-web-magentobase.ext.dev.razorpay.in/", + "frame": "https://api-web-magentobase.ext.dev.razorpay.in/test/checkout.html?branch=master", + }, + }; + window.rzpApi = RazorpayConfigMagento.config.api + 'v1/'; + this.rzp = new Razorpay(options); self.toggleLoader(false); this.rzp.open(); From 650a4ceed007c695a2b391a6d4dc74441d9dd903 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Mon, 18 Mar 2024 13:48:33 +0530 Subject: [PATCH 12/67] Buy now fix --- Controller/OneClick/CompleteOrder.php | 2 +- view/frontend/templates/oneclick/buynow.phtml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index ebb46bc5..7da03e7b 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -382,7 +382,7 @@ public function updateDiscountAmount($orderId, $newDiscountAmount, $offerAmount, $comment = __('Razorpay offer applied ₹%1.', $offerAmount); // Remove "Pending Payment COD" from the comment - $comment = str_replace('Pending Payment COD', '', $comment); + $comment = str_replace('Pending', '', $comment); $order->addStatusHistoryComment( $comment diff --git a/view/frontend/templates/oneclick/buynow.phtml b/view/frontend/templates/oneclick/buynow.phtml index 1c65710b..3fe7c9c2 100644 --- a/view/frontend/templates/oneclick/buynow.phtml +++ b/view/frontend/templates/oneclick/buynow.phtml @@ -39,7 +39,7 @@ $isBuyNowEnabled = $configData->getMagicBuyNowStatus(); data-mage-init='{ "Razorpay_Magento/js/magic-buy-now": { - "sku": "getProduct()->getSku(); ?>", + "sku": "getProduct()->getSku(); ?>" } }' > From 48a2fcf04106cd3501b0a4ef9244bd9e8a3e97c9 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Tue, 26 Mar 2024 14:38:53 +0530 Subject: [PATCH 13/67] Added magic notes in order summary --- Controller/OneClick/CompleteOrder.php | 18 +++++++++++++----- Controller/OneClick/PlaceOrder.php | 4 ++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index 7da03e7b..15582e56 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -248,7 +248,6 @@ public function execute() $this->logger->info('graphQL: discountAmount ' . $discountAmount); $this->updateDiscountAmount($orderId, $newDiscountAmount, $offerDiscount, $totalPaid); - } } @@ -321,6 +320,18 @@ public function execute() $this->logger->info('Invoice generation not possible for id : ' . $order->getIncrementId()); } + $comment = __('Razorpay order id %1.', $rzpOrderId); + + $order->addStatusHistoryComment( + $comment + )->setStatus($order->getStatus())->setIsCustomerNotified(true); + + $comment = __('Razorpay magic order.'); + + $order->addStatusHistoryComment( + $comment + )->setStatus($order->getStatus())->setIsCustomerNotified(true); + try { $this->checkoutSession->setRazorpayMailSentOnSuccess(true); $this->orderSender->send($order); @@ -381,12 +392,9 @@ public function updateDiscountAmount($orderId, $newDiscountAmount, $offerAmount, $comment = __('Razorpay offer applied ₹%1.', $offerAmount); - // Remove "Pending Payment COD" from the comment - $comment = str_replace('Pending', '', $comment); - $order->addStatusHistoryComment( $comment - )->setIsCustomerNotified(true); + )->setStatus($order->getStatus())->setIsCustomerNotified(true); return true; } catch (\Exception $e) { diff --git a/Controller/OneClick/PlaceOrder.php b/Controller/OneClick/PlaceOrder.php index 13b06354..a01a5a15 100644 --- a/Controller/OneClick/PlaceOrder.php +++ b/Controller/OneClick/PlaceOrder.php @@ -157,6 +157,10 @@ public function execute() $connection = $this->resourceConnection->getConnection(); $tableName = $this->resourceConnection->getTableName('quote'); + $quote->setCustomerId(null); + + $quote->save(); + $connection->update($tableName, ['customer_id' => null, 'customer_is_guest' => 1], ['entity_id = ?' => $quoteId]); } } else { From 97660a5866933a33baaacea7a42819681fcde0f6 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Thu, 4 Apr 2024 18:56:09 +0530 Subject: [PATCH 14/67] Added button changes and image fix --- Controller/OneClick/PlaceOrder.php | 36 ++++++++++- view/frontend/templates/oneclick/buynow.phtml | 40 +++++------- .../templates/oneclick/magiccart.phtml | 61 ++++++++++--------- view/frontend/web/css/magic.css | 15 +++-- view/frontend/web/js/magic-cart.js | 21 +++---- 5 files changed, 98 insertions(+), 75 deletions(-) diff --git a/Controller/OneClick/PlaceOrder.php b/Controller/OneClick/PlaceOrder.php index a01a5a15..018d9b70 100644 --- a/Controller/OneClick/PlaceOrder.php +++ b/Controller/OneClick/PlaceOrder.php @@ -25,6 +25,8 @@ use Magento\Quote\Model\ResourceModel\Quote\QuoteIdMask as QuoteIdMaskResourceModel; use Magento\Checkout\Model\Session; use Magento\SalesSequence\Model\Manager as SequenceManager; +use Magento\ConfigurableProduct\Model\Product\Type\Configurable as ConfigurableProduct; +use Magento\GroupedProduct\Model\Product\Type\Grouped as GroupedProduct; class PlaceOrder extends Action { @@ -85,6 +87,9 @@ class PlaceOrder extends Action protected $config; + protected $configurableProduct; + protected $groupedProduct; + /** * PlaceOrder constructor. * @param Http $request @@ -115,7 +120,9 @@ public function __construct( Session $checkoutSession, \Magento\Framework\App\ResourceConnection $resourceConnection, SequenceManager $sequenceManager, - QuoteFactory $quoteFactory + QuoteFactory $quoteFactory, + ConfigurableProduct $configurableProduct, + GroupedProduct $groupedProduct ) { parent::__construct($context); @@ -136,6 +143,8 @@ public function __construct( $this->resourceConnection = $resourceConnection; $this->sequenceManager = $sequenceManager; $this->quoteFactory = $quoteFactory; + $this->configurableProduct = $configurableProduct; + $this->groupedProduct = $groupedProduct; } public function execute() @@ -195,8 +204,31 @@ public function execute() $store = $this->storeManager->getStore(); $productId = $quoteItem->getProductId(); $product = $this->productRepository->getById($productId); + $parentProductId = null; + + // Check if the product is configurable + if ($product->getTypeId() == \Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE) { + $parentProductId = $this->configurableProduct->getParentIdsByChild($productId); + } elseif ($product->getTypeId() == \Magento\GroupedProduct\Model\Product\Type\Grouped::TYPE_CODE) { + $parentProductId = $this->groupedProduct->getParentIdsByChild($productId); + } + + if ($parentProductId) { + // Load the parent product by its ID with images + $parentProduct = $this->productRepository->getById($parentProductId[0], false, $quote->getStoreId(), true); + + // Get the parent product image URL + $productImageUrl = $parentProduct->getImageUrl(); + } else { + $productImageUrl = $store->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) . 'catalog/product' . $product->getImage(); + } + + $imagewidth=200; + $imageheight=200; + $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); + $imageHelper = $objectManager->get('\Magento\Catalog\Helper\Image'); + $productImageUrl = $imageHelper->init($product, 'product_page_image_small')->setImageFile($product->getFile())->resize($imagewidth, $imageheight)->getUrl(); - $productImageUrl = $store->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA) . 'catalog/product' . $product->getImage(); $productUrl = $product->getProductUrl(); $offerPrice = $quoteItem->getPrice() * 100; diff --git a/view/frontend/templates/oneclick/buynow.phtml b/view/frontend/templates/oneclick/buynow.phtml index 3fe7c9c2..1c156f8f 100644 --- a/view/frontend/templates/oneclick/buynow.phtml +++ b/view/frontend/templates/oneclick/buynow.phtml @@ -17,34 +17,22 @@ $isBuyNowEnabled = $configData->getMagicBuyNowStatus(); - - -
- - -
+ } + } + + + --> + - + diff --git a/view/frontend/web/css/magic.css b/view/frontend/web/css/magic.css index d8185c11..a46ead61 100644 --- a/view/frontend/web/css/magic.css +++ b/view/frontend/web/css/magic.css @@ -1,12 +1,19 @@ -#cart-occ-template{ +#cart-occ-template { width: 100%; } -.action.primary.checkout{ + +#product-oneclick-button { + margin-bottom: 10px; +} + +.checkout.methods.items.checkout-methods-items { display: none; } -.fieldset.coupon{ + +.fieldset.coupon { display: none; } + div.product-info-main #occ-template magic-checkout-btn { - display: none !important; + display: none !important; } \ No newline at end of file diff --git a/view/frontend/web/js/magic-cart.js b/view/frontend/web/js/magic-cart.js index ce737a91..bf9eaf68 100644 --- a/view/frontend/web/js/magic-cart.js +++ b/view/frontend/web/js/magic-cart.js @@ -85,6 +85,7 @@ define([ self.renderIframe(data); }, error: function (request) { + self.toggleLoader(false); self._orderError(request); self.enableButton(); } @@ -108,6 +109,7 @@ define([ window.location.href = successUrl; }, error: function (error) { + self.toggleLoader(false); console.log("Payment complete fail") var failureUrl = url.build('checkout/onepage/failure', {}) window.location.href = failureUrl; @@ -116,7 +118,6 @@ define([ }, renderIframe: function(data) { - // debugger; var self = this; var options = { @@ -132,13 +133,13 @@ define([ order_id: data.rzp_order_id, modal: { ondismiss: function (data) { + self.enableButton(); + //reset the cart - self.resetCart(data); + // self.resetCart(data); // fullScreenLoader.stopLoader(); // self.isPaymentProcessing.reject("Payment Closed"); // self.isPlaceOrderActionAllowed(true); - self.enableButton(); - } }, notes: {}, @@ -162,13 +163,6 @@ define([ // options.display_amount = data.quote_amount; // } - var RazorpayConfigMagento = { - "config": { - "api": "https://api-web-magentobase.ext.dev.razorpay.in/", - "frame": "https://api-web-magentobase.ext.dev.razorpay.in/test/checkout.html?branch=master", - }, - }; - window.rzpApi = RazorpayConfigMagento.config.api + 'v1/'; this.rzp = new Razorpay(options); self.toggleLoader(false); @@ -176,17 +170,16 @@ define([ }, _orderError: function (request) { - console.log(request); this.enableButton(); }, _disableButton: function () { - var button = this._parent().find(this.options.buttonSelector); + var button = this._parent().find(this.options.buttonTemplateSelector); button.addClass('disabled'); }, enableButton: function () { - var button = this._parent().find(this.options.buttonSelector); + var button = this._parent().find(this.options.buttonTemplateSelector); button.removeClass('disabled'); }, From e9bffdf9de7f9dde73decf8a7bfd066a3488d2f3 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Thu, 4 Apr 2024 19:31:58 +0530 Subject: [PATCH 15/67] Added support for auto discount --- Controller/OneClick/PlaceOrder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Controller/OneClick/PlaceOrder.php b/Controller/OneClick/PlaceOrder.php index 018d9b70..4d20d316 100644 --- a/Controller/OneClick/PlaceOrder.php +++ b/Controller/OneClick/PlaceOrder.php @@ -255,7 +255,7 @@ public function execute() ]; } - $totalAmount = $quote->getGrandTotal() * 100; + $totalAmount = $quote->getSubtotalWithDiscount() * 100; } catch (LocalizedException $e) { return $resultJson->setData([ From b0324bd63b4e64d7604a68741dc7a128adab8684 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Thu, 4 Apr 2024 20:55:20 +0530 Subject: [PATCH 16/67] Added support for coupon apply on cart --- view/frontend/web/css/magic.css | 4 ---- 1 file changed, 4 deletions(-) diff --git a/view/frontend/web/css/magic.css b/view/frontend/web/css/magic.css index a46ead61..2e748bc8 100644 --- a/view/frontend/web/css/magic.css +++ b/view/frontend/web/css/magic.css @@ -10,10 +10,6 @@ display: none; } -.fieldset.coupon { - display: none; -} - div.product-info-main #occ-template magic-checkout-btn { display: none !important; } \ No newline at end of file From 79cf8ca2a1706452b359ec5ad21455dd12e9964c Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Fri, 5 Apr 2024 15:14:10 +0530 Subject: [PATCH 17/67] Bug fix for order status update for COD payments --- Controller/OneClick/CompleteOrder.php | 52 +++++++++++++++------------ 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index 15582e56..5fb18770 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -92,9 +92,9 @@ class CompleteOrder extends Action protected $customerConsent; protected $_order = null; - protected const STATUS_PROCESSING = 'processing'; - protected const COD = 'cashondelivery'; - protected const RAZORPAY = 'razorpay'; + const STATUS_PROCESSING = 'processing'; + const COD = 'cashondelivery'; + const RAZORPAY = 'razorpay'; /** * CompleteOrder constructor. @@ -212,7 +212,7 @@ public function execute() if ($order->getStatus() === 'pending') { if ($rzpPaymentData->status === 'pending' && $rzpPaymentData->method === 'cod') { - $order->setStatus(\Magento\Sales\Model\Order::STATE_PENDING_PAYMENT)->setStatus($this->orderStatus); + $order->setState(\Magento\Sales\Model\Order::STATE_PENDING_PAYMENT)->setStatus($this->orderStatus); } else { $order->setState(\Magento\Sales\Model\Order::STATE_PROCESSING)->setStatus($this->orderStatus); } @@ -260,26 +260,32 @@ public function execute() $payment->setParentTransactionId($payment->getTransactionId()); - if ($this->config->getPaymentAction() === \Razorpay\Magento\Model\PaymentMethod::ACTION_AUTHORIZE_CAPTURE) { - $payment->addTransactionCommentsToOrder( - "$rzpPaymentId", - $this->captureCommand->execute( - $payment, - $order->getGrandTotal(), - $order - ), - "" - ); + if ($rzpPaymentData->method != 'cod') { + if ($this->config->getPaymentAction() === \Razorpay\Magento\Model\PaymentMethod::ACTION_AUTHORIZE_CAPTURE) { + $payment->addTransactionCommentsToOrder( + "$rzpPaymentId", + $this->captureCommand->execute( + $payment, + $order->getGrandTotal(), + $order + ), + "" + ); + } else { + $payment->addTransactionCommentsToOrder( + "$rzpPaymentId", + $this->authorizeCommand->execute( + $payment, + $order->getGrandTotal(), + $order + ), + "" + ); + } + $this->logger->info('Payment authorized completed for id : ' . $order->getIncrementId()); + } else { - $payment->addTransactionCommentsToOrder( - "$rzpPaymentId", - $this->authorizeCommand->execute( - $payment, - $order->getGrandTotal(), - $order - ), - "" - ); + $order->addStatusHistoryComment("Razorpay Payment Id " . $rzpPaymentId)->setStatus($order->getStatus())->setIsCustomerNotified(true); } $transaction = $payment->addTransaction(\Magento\Sales\Model\Order\Payment\Transaction::TYPE_AUTH, null, true, ""); From 0f52715b94bda1c2a13fa44211208ac5ce64f651 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Fri, 5 Apr 2024 17:20:10 +0530 Subject: [PATCH 18/67] Merchant name fix --- view/frontend/web/js/magic-buy-now.js | 2 +- view/frontend/web/js/magic-cart.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/view/frontend/web/js/magic-buy-now.js b/view/frontend/web/js/magic-buy-now.js index db113e4e..e809780a 100644 --- a/view/frontend/web/js/magic-buy-now.js +++ b/view/frontend/web/js/magic-buy-now.js @@ -121,7 +121,7 @@ define([ var options = { key: data.rzp_key_id, - name: data.merchant_name, + name: '', amount: data.totalAmount, handler: function (data) { self.toggleLoader(true); diff --git a/view/frontend/web/js/magic-cart.js b/view/frontend/web/js/magic-cart.js index bf9eaf68..b1e05ae7 100644 --- a/view/frontend/web/js/magic-cart.js +++ b/view/frontend/web/js/magic-cart.js @@ -122,7 +122,7 @@ define([ var options = { key: data.rzp_key_id, - name: data.merchant_name, + name: '', amount: data.totalAmount, handler: function (data) { From f78cf33d4e9c9f3a62b4ee41ee7795a0424fa09e Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Fri, 5 Apr 2024 19:05:50 +0530 Subject: [PATCH 19/67] Sending one cc falg in checkout options and name as empty --- view/frontend/web/js/magic-buy-now.js | 1 + view/frontend/web/js/magic-cart.js | 1 + 2 files changed, 2 insertions(+) diff --git a/view/frontend/web/js/magic-buy-now.js b/view/frontend/web/js/magic-buy-now.js index e809780a..8ab6518d 100644 --- a/view/frontend/web/js/magic-buy-now.js +++ b/view/frontend/web/js/magic-buy-now.js @@ -123,6 +123,7 @@ define([ key: data.rzp_key_id, name: '', amount: data.totalAmount, + one_click_checkout: true, handler: function (data) { self.toggleLoader(true); self.orderSuccess(data); diff --git a/view/frontend/web/js/magic-cart.js b/view/frontend/web/js/magic-cart.js index b1e05ae7..2c0490b1 100644 --- a/view/frontend/web/js/magic-cart.js +++ b/view/frontend/web/js/magic-cart.js @@ -124,6 +124,7 @@ define([ key: data.rzp_key_id, name: '', amount: data.totalAmount, + one_click_checkout: true, handler: function (data) { console.log("data in handler", data) From e5eab6279a45e73b3bb21779a28aa3acb50932f5 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Sat, 6 Apr 2024 21:58:04 +0530 Subject: [PATCH 20/67] Removed rzp offer discount update on magento order for navya --- Controller/OneClick/CompleteOrder.php | 34 +++++++++++++++------------ 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index 5fb18770..630053c7 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -92,9 +92,10 @@ class CompleteOrder extends Action protected $customerConsent; protected $_order = null; - const STATUS_PROCESSING = 'processing'; const COD = 'cashondelivery'; const RAZORPAY = 'razorpay'; + const STATE_PENDING_PAYMENT = 'pending_payment'; + const STATE_PROCESSING = 'processing'; /** * CompleteOrder constructor. @@ -159,7 +160,7 @@ public function __construct( $this->cartConverter = $cartConverter; $this->customerConsent = $customerConsent; $this->resultRedirectFactory = $context->getResultFactory();; - $this->orderStatus = static::STATUS_PROCESSING; + $this->orderStatus = static::STATE_PROCESSING; $this->authorizeCommand = new AuthorizeCommand(); $this->captureCommand = new CaptureCommand(); } @@ -212,9 +213,11 @@ public function execute() if ($order->getStatus() === 'pending') { if ($rzpPaymentData->status === 'pending' && $rzpPaymentData->method === 'cod') { - $order->setState(\Magento\Sales\Model\Order::STATE_PENDING_PAYMENT)->setStatus($this->orderStatus); + $order->setState(static::STATE_PENDING_PAYMENT) + ->setStatus(static::STATE_PENDING_PAYMENT); } else { - $order->setState(\Magento\Sales\Model\Order::STATE_PROCESSING)->setStatus($this->orderStatus); + $order->setState(static::STATE_PROCESSING) + ->setStatus(static::STATE_PROCESSING); } $this->logger->info('graphQL: Order Status Updated to ' . $this->orderStatus); @@ -384,17 +387,18 @@ public function updateDiscountAmount($orderId, $newDiscountAmount, $offerAmount, // Load the order $order = $this->order->load($orderId); - // Update discount amount - $order->setDiscountAmount($newDiscountAmount); - $order->setBaseDiscountAmount($newDiscountAmount); - - $totalBaseGrandTotal = $order->getBaseGrandTotal(); - $totalGrandTotal = $order->getGrandTotal(); - - $order->setBaseGrandTotal($totalBaseGrandTotal - $offerAmount); - $order->setGrandTotal($totalGrandTotal - $offerAmount); - - $order->setTotalPaid($totalPaid / 100); + // TODO: Commenting this temp to unblock navya fashion. +// // Update discount amount +// $order->setDiscountAmount($newDiscountAmount); +// $order->setBaseDiscountAmount($newDiscountAmount); +// +// $totalBaseGrandTotal = $order->getBaseGrandTotal(); +// $totalGrandTotal = $order->getGrandTotal(); +// +// $order->setBaseGrandTotal($totalBaseGrandTotal - $offerAmount); +// $order->setGrandTotal($totalGrandTotal - $offerAmount); +// +// $order->setTotalPaid($totalPaid / 100);*/ $comment = __('Razorpay offer applied ₹%1.', $offerAmount); From 2a5c184790f3c8ee31a5e90b59bc633d3e682e3f Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Sun, 7 Apr 2024 08:31:01 +0530 Subject: [PATCH 21/67] Added merchant order id in order notes --- Controller/OneClick/PlaceOrder.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Controller/OneClick/PlaceOrder.php b/Controller/OneClick/PlaceOrder.php index 4d20d316..a3779381 100644 --- a/Controller/OneClick/PlaceOrder.php +++ b/Controller/OneClick/PlaceOrder.php @@ -289,7 +289,8 @@ public function execute() 'app_offer' => 0, 'notes' => [ 'cart_mask_id' => $maskedId, - 'cart_id' => $quoteId + 'cart_id' => $quoteId, + 'merchant_order_id' => (string)$quote->getReservedOrderId() ], 'line_items_total' => $totalAmount, 'line_items' => $lineItems From 02552ee9b3951474b8e8a1115a0dcade54166778 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Fri, 12 Apr 2024 15:30:13 +0530 Subject: [PATCH 22/67] Added support for GTM events --- Controller/OneClick/CompleteOrder.php | 34 +++- Controller/OneClick/PlaceOrder.php | 21 +- view/frontend/web/js/analytics.js | 271 ++++++++++++++++++++++++++ view/frontend/web/js/magic-buy-now.js | 33 +++- view/frontend/web/js/magic-cart.js | 30 ++- 5 files changed, 382 insertions(+), 7 deletions(-) create mode 100644 view/frontend/web/js/analytics.js diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index 630053c7..b96d5574 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -372,8 +372,17 @@ public function execute() $order->save(); + // Get applied discounts data from the order object + $appliedDiscounts = $this->getAppliedDiscounts($order); + $result = [ - 'status' => 'success' + 'status' => 'success', + 'order_id' => $order->getIncrementId(), + 'total_amount' => $order->getGrandTotal() * 100, + 'total_tax' => $order->getTaxAmount() * 100, + 'shipping_fee' => $order->getShippingAmount() * 100, + 'promotions' => $appliedDiscounts, + 'cod_fee' => 0 ]; return $resultJson->setData($result); @@ -381,6 +390,29 @@ public function execute() } } + public function getAppliedDiscounts($order) + { + try { + // Get applied discounts data from the order object + $appliedDiscounts = []; + foreach ($order->getAllItems() as $item) { + $discount = $item->getDiscountAmount(); + if ($discount > 0) { + $appliedDiscounts[] = [ + 'item_id' => $item->getId(), + 'code' => $item->getName(), + 'discount_amount' => $discount * 100 + ]; + } + } + + return $appliedDiscounts; + } catch (\Exception $e) { + // Handle exception if order retrieval fails + return []; + } + } + public function updateDiscountAmount($orderId, $newDiscountAmount, $offerAmount, $totalPaid) { try { diff --git a/Controller/OneClick/PlaceOrder.php b/Controller/OneClick/PlaceOrder.php index a3779381..d781b377 100644 --- a/Controller/OneClick/PlaceOrder.php +++ b/Controller/OneClick/PlaceOrder.php @@ -198,8 +198,10 @@ public function execute() $totalAmount = 0; $lineItems = []; + $item = []; foreach ($cartItems as $quoteItem) { + $category = []; $store = $this->storeManager->getStore(); $productId = $quoteItem->getProductId(); @@ -240,7 +242,16 @@ public function execute() $offerPrice = ($quoteItem->getPrice() - $discountAmount) * 100; } - $lineItems[] = [ + $categoriesIds = $product->getCategoryIds(); /*will return category ids array*/ + foreach($categoriesIds as $categoryId){ + + $cat = $objectManager->create('Magento\Catalog\Model\Category')->load($categoryId); + $catName = $cat->getName(); + $category['category'][] = $catName; + } + $item = array_merge($item, $category); + + $lineItem = [ 'type' => 'e-commerce', 'sku' => $quoteItem->getSku(), 'variant_id' => $quoteItem->getProductId(), @@ -254,6 +265,11 @@ public function execute() 'product_url' => $productUrl, ]; + $lineItems[] = $lineItem; + + $item = array_merge($item, $lineItem); + + $items[] = $item; } $totalAmount = $quote->getSubtotalWithDiscount() * 100; @@ -290,7 +306,7 @@ public function execute() 'notes' => [ 'cart_mask_id' => $maskedId, 'cart_id' => $quoteId, - 'merchant_order_id' => (string)$quote->getReservedOrderId() + 'merchant_order_id' => (string)$quote->getReservedOrderId() ?? 'order pending' ], 'line_items_total' => $totalAmount, 'line_items' => $lineItems @@ -304,6 +320,7 @@ public function execute() 'rzp_key_id' => $rzpKey, 'merchant_name' => $merchantName, 'rzp_order_id' => $razorpay_order->id, + 'items' => $items, 'message' => 'Razorpay Order created successfully' ]; } else { diff --git a/view/frontend/web/js/analytics.js b/view/frontend/web/js/analytics.js new file mode 100644 index 00000000..ceca67b5 --- /dev/null +++ b/view/frontend/web/js/analytics.js @@ -0,0 +1,271 @@ +define(['jquery'], function ($) { + + let lineItemsArr = []; + let checkoutCart = {}; + + let enabledAnalyticsTools = { + // clevertap: false, + // webengage: false, + ga4: false, + // googleAds: false, + }; + + const GA4 = { + // GTAG: currentScript.getAttribute('data-ga4-id') || '', + COUPON: '', + // CUSTOM_EVENTS: + // currentScript.getAttribute('data-ga4-custom-event-names') === 'true', + EVENTS: { + BEGIN_CHECKOUT: 'begin_checkout', + ADD_SHIPPING_INFO: 'add_shipping_info', + ADD_PAYMENT_INFO: 'add_payment_info', + SELECT_PROMOTION: 'select_promotion', + PURCHASE: 'purchase', + }, + handlers: { + setCoupon: code => (GA4.COUPON = code), + resetCoupon: () => (GA4.COUPON = ''), + getCustomEventName: e => { + const CUSTOM_EVENTS = { + [GA4.EVENTS.BEGIN_CHECKOUT]: 'beginCheckout', + [GA4.EVENTS.ADD_SHIPPING_INFO]: 'addShippingInfo', + [GA4.EVENTS.ADD_PAYMENT_INFO]: 'addPaymentInfo', + [GA4.EVENTS.SELECT_PROMOTION]: 'selectPromotion', + [GA4.EVENTS.PURCHASE]: 'Purchase', + }; + return CUSTOM_EVENTS[e]; + }, + formatLineItems() { + if (!lineItemsArr) return []; + const items = lineItemsArr.map((element, index) => { + let itemCategories = {}; + let cartItem = checkoutCart?.items?.[index]; + cartItem.category.forEach((val, idx) => { + itemCategories = {...itemCategories, [`item_category${idx}`] :val} + }); + const item = { + index, + item_id: element.sku || element.id, + item_name: element.title || element.name, + price: element.price.toFixed(2), + quantity: element.quantity, + discount: element.discount.toFixed(2), + item_brand: element.brand || element.vendor || '', + item_variant: element.id || '', + ...itemCategories, + }; + if (GA4.COUPON) item.coupon = GA4.COUPON; + return item; + }); + return items; + }, + beginCheckout(data) { + const payload = GA4.handlers.generatePayload(data); + GA4.handlers.triggerEvent(GA4.EVENTS.BEGIN_CHECKOUT, payload); + }, + addShippingInfo(data) { + const payload = GA4.handlers.generatePayload(data); + GA4.handlers.triggerEvent(GA4.EVENTS.ADD_SHIPPING_INFO, payload); + }, + addPaymentInfo(data) { + const payload = GA4.handlers.generatePayload(data); + GA4.handlers.triggerEvent(GA4.EVENTS.ADD_PAYMENT_INFO, payload); + }, + selectPromotion(data) { + const payload = GA4.handlers.generatePayload(data); + GA4.handlers.triggerEvent(GA4.EVENTS.SELECT_PROMOTION, payload); + }, + purchase(data) { + // debugger + const { + order_id, + total_amount, + total_tax, + shipping_fee, + promotions, + cod_fee = 0, + } = data; + const items = GA4.handlers.formatLineItems() || []; + const shipping = +shipping_fee + +(cod_fee ?? 0); + const value = total_amount - shipping; + GA4.handlers.triggerEvent(GA4.EVENTS.PURCHASE, { + transaction_id: order_id, + currency: getCurrency(), + items, + tax: total_tax, + value: (value / 100).toFixed(2), + shipping: (shipping / 100).toFixed(2), + coupon: data.promotions[0]?.code || GA4.COUPON || '', + }); + }, + generatePayload(data) { + if (data.appliedCouponCode) + GA4.handlers.setCoupon(data.appliedCouponCode); + + const items = GA4.handlers.formatLineItems() || []; + const value = getTotalAmount(data) - getTotalDiscount(data); + const payload = { + items, + value: isNaN(value) ? 0 : value, + currency: getCurrency(), + }; + if (GA4.COUPON) payload.coupon = GA4.COUPON; + if (data.paymentMode) payload.payment_type = data.paymentMode; + return payload; + }, + triggerEvent(event, payload) { + if (GA4.GTAG) { + payload.send_to = GA4.GTAG; + } + if (GA4.CUSTOM_EVENTS) { + dataLayer.push({ecommerce: null}); + dataLayer.push({ + event: GA4.handlers.getCustomEventName(event), + ecommerce: payload, + }); + return; + } + window.gtag('event', event, payload); + }, + }, + }; + + function getTotalAmount(data) { + return data.isScriptCouponApplied && _isEmpty(checkoutCart) + ? getOriginalAmount(data.lineItems) / 100 + : (data.totalAmount || checkoutCart.original_total_price) / 100; + } + + function getTotalDiscount(data) { + return data.isScriptCouponApplied && _isEmpty(checkoutCart) + ? getDiscount(data.lineItems) / 100 + : ((checkoutCart.total_discount || 0) + + (data.couponDiscount || data.couponDiscountValue || 0)) / + 100; + } + + function getCurrency() { + return checkoutCart?.items?.currency ?? "INR"; + } + + function _isEmpty(obj) { + return Object.keys(obj).length === 0; + } + + function getDiscount(lineItemsArray) { + return lineItemsArray.reduce( + (acc, curr) => acc + (curr.price - curr.offer_price), + 0 + ); + } + + function getOriginalAmount(lineItemsArray) { + return lineItemsArray.reduce( + (acc, curr) => acc + curr.quantity * +curr.price, + 0 + ); + } + + const ga4Handlers = { + initiate: GA4.handlers.beginCheckout, + shipping_selected: GA4.handlers.addShippingInfo, + payment_initiated: GA4.handlers.addPaymentInfo, + coupon_applied: GA4.handlers.selectPromotion, + coupon_failed: GA4.handlers.resetCoupon, + purchase: GA4.handlers.purchase, + }; + + let analyticsEvents = { + ga4: ga4Handlers, + }; + + function sendAnalyticsEvents(eventName, data) { + Object.entries(enabledAnalyticsTools).forEach(method => { + const toolName = method[0]; + const enabled = method[1]; + if ( + enabled && + typeof analyticsEvents[toolName][eventName] === 'function' + ) { + try { + analyticsEvents[toolName][eventName](data); + } catch (e) { + console.error(e); + } + } + }); + } + + const MagicMxAnalytics = { + initiate(data, checkoutCartObj = {}, analyticsTools) { + checkoutCart = { ...checkoutCartObj }; + enabledAnalyticsTools = {...enabledAnalyticsTools, ...analyticsTools}; + data.lineItems.forEach(lineItem => { + lineItemsArr.push({ + name: lineItem.name, + id: lineItem.variant_id, + sku: lineItem.sku, + price: lineItem.offer_price / 100, + mrp: lineItem.price / 100, + quantity: lineItem.quantity, + cropped_URL: lineItem.product_url?.slice(1), + // todo: prfs returniong null + product_url_link: `${document.location.origin}${lineItem.product_url}`, + image: lineItem.image_url?.replace('.jpg', '_530x@2x.jpg'), + brand: document.location.host, + currency: getCurrency(), + size: 'NA', + discount: (lineItem.price - lineItem.offer_price) / 100, + }); + }); + + sendAnalyticsEvents('initiate', data); + }, + + shipping_selected(data) { + sendAnalyticsEvents('shipping_selected', data); + }, + + payment_initiated(data) { + sendAnalyticsEvents('payment_initiated', data); + }, + + coupon_applied(data) { + sendAnalyticsEvents('coupon_applied', data); + }, + + coupon_failed(data) { + sendAnalyticsEvents('coupon_failed', data); + }, + + payment_failed(data) { + sendAnalyticsEvents('payment_failed', data); + }, + + purchase(data = {}) { + return Object.entries(enabledAnalyticsTools).map(method => { + const toolName = method[0]; + const enabled = method[1]; + if ( + enabled && + typeof analyticsEvents[toolName].purchase === 'function' + ) { + return analyticsEvents[toolName].purchase(data); + } + return Promise.resolve(); + }); + }, + + user_data(data) { + sendAnalyticsEvents('user_data', data); + }, + + reset() { + lineItemsArr = []; + }, + }; + + return { + MagicMxAnalytics: MagicMxAnalytics + }; +}); \ No newline at end of file diff --git a/view/frontend/web/js/magic-buy-now.js b/view/frontend/web/js/magic-buy-now.js index 8ab6518d..c4df2139 100644 --- a/view/frontend/web/js/magic-buy-now.js +++ b/view/frontend/web/js/magic-buy-now.js @@ -4,9 +4,10 @@ define([ 'Magento_Ui/js/modal/alert', 'Magento_Checkout/js/model/full-screen-loader', 'mage/url', + 'Razorpay_Magento/js/analytics', 'underscore', 'mage/cookies' -], function ($, $t, alert, fullScreenLoader, url, _) { +], function ($, $t, alert, fullScreenLoader, url, analytics, _) { "use strict"; $.widget('pmclain.oneClickButton', { @@ -104,8 +105,20 @@ define([ data: data, type: 'POST', dataType: 'json', - success: function (data) { + success: async function (data) { self.toggleLoader(true); + + if (analytics.MagicMxAnalytics.purchase) { + debugger + try { + await Promise.all(analytics.MagicMxAnalytics.purchase({ + ...data, + merchantAnalyticsConfigs: {}, + })); + } catch (error) { + console.error(error); + } + } var successUrl = url.build('checkout/onepage/success', {}) window.location.href = successUrl; }, @@ -163,6 +176,22 @@ define([ // } this.rzp = new Razorpay(options); + + this.rzp.on('mx-analytics', eventData => { + console.log(analytics.MagicMxAnalytics); + console.log("mx-analytics data", eventData); + const enabledAnalyticsTools = { + ga4: window.gtag, + }; + + analytics.MagicMxAnalytics?.[eventData.event]?.( + { + ...eventData, + }, + data, + enabledAnalyticsTools + ); + }); self.toggleLoader(false); this.rzp.open(); diff --git a/view/frontend/web/js/magic-cart.js b/view/frontend/web/js/magic-cart.js index 2c0490b1..265f6e0a 100644 --- a/view/frontend/web/js/magic-cart.js +++ b/view/frontend/web/js/magic-cart.js @@ -4,9 +4,10 @@ define([ 'Magento_Ui/js/modal/alert', 'Magento_Checkout/js/model/full-screen-loader', 'mage/url', + 'Razorpay_Magento/js/analytics', 'underscore', 'mage/cookies' -], function ($, $t, alert, fullScreenLoader, url, _) { +], function ($, $t, alert, fullScreenLoader, url, analytics, _) { "use strict"; $.widget('pmclain.oneClickButton', { @@ -102,9 +103,21 @@ define([ data: data, type: 'POST', dataType: 'json', - success: function (data) { + success: async function (data) { self.toggleLoader(true); + if (analytics.MagicMxAnalytics.purchase) { + debugger + try { + await Promise.all(analytics.MagicMxAnalytics.purchase({ + ...data, + merchantAnalyticsConfigs: {}, + })); + } catch (error) { + console.error(error); + } + } + var successUrl = url.build('checkout/onepage/success', {}) window.location.href = successUrl; }, @@ -166,6 +179,19 @@ define([ this.rzp = new Razorpay(options); + this.rzp.on('mx-analytics', eventData => { + const enabledAnalyticsTools = { + ga4: window.gtag, + }; + + analytics.MagicMxAnalytics?.[eventData.event]?.( + { + ...eventData, + }, + data, + enabledAnalyticsTools + ); + }); self.toggleLoader(false); this.rzp.open(); }, From 1869ba0c5c56d726c7828a16caaf9becc0118fd4 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Fri, 12 Apr 2024 16:14:54 +0530 Subject: [PATCH 23/67] Updated the php sdk version in composer --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index bd386ba5..c56a51b1 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "version": "4.1.3", "require": { "php": "7.*|^8.1", - "razorpay/razorpay": "2.*" + "razorpay/razorpay": "2.9.*" }, "keywords": [ "razorpay", From 81170bb4e1afa26305f1429504445f7536307792 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Fri, 12 Apr 2024 17:53:56 +0530 Subject: [PATCH 24/67] Removed debugger --- view/frontend/web/js/magic-buy-now.js | 1 - view/frontend/web/js/magic-cart.js | 1 - 2 files changed, 2 deletions(-) diff --git a/view/frontend/web/js/magic-buy-now.js b/view/frontend/web/js/magic-buy-now.js index c4df2139..9b44f4e2 100644 --- a/view/frontend/web/js/magic-buy-now.js +++ b/view/frontend/web/js/magic-buy-now.js @@ -109,7 +109,6 @@ define([ self.toggleLoader(true); if (analytics.MagicMxAnalytics.purchase) { - debugger try { await Promise.all(analytics.MagicMxAnalytics.purchase({ ...data, diff --git a/view/frontend/web/js/magic-cart.js b/view/frontend/web/js/magic-cart.js index 265f6e0a..983885af 100644 --- a/view/frontend/web/js/magic-cart.js +++ b/view/frontend/web/js/magic-cart.js @@ -107,7 +107,6 @@ define([ self.toggleLoader(true); if (analytics.MagicMxAnalytics.purchase) { - debugger try { await Promise.all(analytics.MagicMxAnalytics.purchase({ ...data, From 7d5122ee8482d30b42cbc749a623e0b50c79ad66 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Fri, 12 Apr 2024 18:05:56 +0530 Subject: [PATCH 25/67] Reverted branded button from mini cart --- .../frontend/web/template/magic/minicart.html | 41 ++++++++++++++----- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/view/frontend/web/template/magic/minicart.html b/view/frontend/web/template/magic/minicart.html index 8e988a7e..23d018ce 100644 --- a/view/frontend/web/template/magic/minicart.html +++ b/view/frontend/web/template/magic/minicart.html @@ -8,9 +8,9 @@ @@ -79,15 +79,34 @@
-
- - +
+ +
+
From 2613b8ca9b7363a7f8b98564f2d32fc3ae8f7fd0 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Thu, 18 Apr 2024 19:17:05 +0530 Subject: [PATCH 26/67] Added coupon widget config on magento admin panel --- Controller/OneClick/CompleteOrder.php | 6 +++--- Controller/OneClick/PlaceOrder.php | 3 ++- Model/Config.php | 5 +++++ etc/adminhtml/system.xml | 11 ++++++++++- etc/config.xml | 3 ++- view/frontend/web/js/magic-buy-now.js | 1 + view/frontend/web/js/magic-cart.js | 1 + 7 files changed, 24 insertions(+), 6 deletions(-) diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index b96d5574..9bbcbb63 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -457,11 +457,11 @@ protected function updateQuote($quote, $rzpOrderData, $rzpPaymentData) $shippingCountry = $rzpOrderData->customer_details->shipping_address->country; $shippingState = $rzpOrderData->customer_details->shipping_address->state; - $billingingCountry = $rzpOrderData->customer_details->billing_address->country; - $billingingState = $rzpOrderData->customer_details->billing_address->state; + $billingCountry = $rzpOrderData->customer_details->billing_address->country; + $billingState = $rzpOrderData->customer_details->billing_address->state; $shippingRegionCode = $this->getRegionCode($shippingCountry, $shippingState); - $billingRegionCode = $this->getRegionCode($billingingCountry, $billingingState); + $billingRegionCode = $this->getRegionCode($billingCountry, $billingState); $shipping = $this->getAddress($rzpOrderData->customer_details->shipping_address, $shippingRegionCode, $email); $billing = $this->getAddress($rzpOrderData->customer_details->billing_address, $billingRegionCode, $email); diff --git a/Controller/OneClick/PlaceOrder.php b/Controller/OneClick/PlaceOrder.php index d781b377..09bf9ea9 100644 --- a/Controller/OneClick/PlaceOrder.php +++ b/Controller/OneClick/PlaceOrder.php @@ -294,6 +294,7 @@ public function execute() } $rzpKey = $this->config->getKeyId(); $merchantName = $this->config->getMerchantNameOverride(); + $allowCouponApplication = $this->config->getMerchantCouponApplication(); $this->getLastOrderId($quote); @@ -318,7 +319,7 @@ public function execute() $result = [ 'status' => 'success', 'rzp_key_id' => $rzpKey, - 'merchant_name' => $merchantName, + 'allow_coupon_application' => $allowCouponApplication == 1 ? true : false, 'rzp_order_id' => $razorpay_order->id, 'items' => $items, 'message' => 'Razorpay Order created successfully' diff --git a/Model/Config.php b/Model/Config.php index 56a3d2ce..317863c5 100644 --- a/Model/Config.php +++ b/Model/Config.php @@ -30,6 +30,7 @@ class Config const KEY_MAGIC_CHECKOUT_STATUS = 'activate_magic'; const KEY_MAGIC_BUY_NOW_STATUS = 'activate_magic_buy_now'; const KEY_MAGIC_MINI_CART_STATUS = 'activate_magic_mini_cart'; + const KEY_MAGIC_ALLOW_COUPON_APPLICATION_STATUS = 'allow_coupon_apply_magic'; /** * @var string */ @@ -140,6 +141,10 @@ public function getMagicMinicartStatus() { return $this->getConfigData(self::KEY_MAGIC_MINI_CART_STATUS); } + public function getMerchantCouponApplication() + { + return $this->getConfigData(self::KEY_MAGIC_ALLOW_COUPON_APPLICATION_STATUS); + } /** * @param int $storeId diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml index f847602c..89338bef 100644 --- a/etc/adminhtml/system.xml +++ b/etc/adminhtml/system.xml @@ -124,7 +124,7 @@ - + Magento\Config\Model\Config\Source\Yesno payment/razorpay/activate_magic_mini_cart @@ -133,6 +133,15 @@ + + + Magento\Config\Model\Config\Source\Yesno + payment/razorpay/allow_coupon_apply_magic + + 1 + + + Magento\Config\Model\Config\Source\Yesno diff --git a/etc/config.xml b/etc/config.xml index 290c6f3a..d12c6f49 100644 --- a/etc/config.xml +++ b/etc/config.xml @@ -23,7 +23,8 @@ processing 0 0 - 0 + 1 + 1 1 0 diff --git a/view/frontend/web/js/magic-buy-now.js b/view/frontend/web/js/magic-buy-now.js index 9b44f4e2..d1eef9d4 100644 --- a/view/frontend/web/js/magic-buy-now.js +++ b/view/frontend/web/js/magic-buy-now.js @@ -136,6 +136,7 @@ define([ name: '', amount: data.totalAmount, one_click_checkout: true, + show_coupons: data.allow_coupon_application, handler: function (data) { self.toggleLoader(true); self.orderSuccess(data); diff --git a/view/frontend/web/js/magic-cart.js b/view/frontend/web/js/magic-cart.js index 983885af..d1c9e944 100644 --- a/view/frontend/web/js/magic-cart.js +++ b/view/frontend/web/js/magic-cart.js @@ -137,6 +137,7 @@ define([ name: '', amount: data.totalAmount, one_click_checkout: true, + show_coupons: data.allow_coupon_application, handler: function (data) { console.log("data in handler", data) From 73354f80e3add8597d9a91f821b8a7f138c6644c Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Thu, 18 Apr 2024 20:24:42 +0530 Subject: [PATCH 27/67] Passing affiliation param in GTM --- Controller/OneClick/PlaceOrder.php | 5 +++++ etc/adminhtml/system.xml | 3 ++- view/frontend/web/js/analytics.js | 1 + 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Controller/OneClick/PlaceOrder.php b/Controller/OneClick/PlaceOrder.php index 09bf9ea9..152dcee5 100644 --- a/Controller/OneClick/PlaceOrder.php +++ b/Controller/OneClick/PlaceOrder.php @@ -251,6 +251,11 @@ public function execute() } $item = array_merge($item, $category); + $storeName = [ + 'affiliation' => $this->storeManager->getStore()->getName(), + ]; + $item = array_merge($item, $storeName); + $lineItem = [ 'type' => 'e-commerce', 'sku' => $quoteItem->getSku(), diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml index 89338bef..bdd028ee 100644 --- a/etc/adminhtml/system.xml +++ b/etc/adminhtml/system.xml @@ -124,7 +124,7 @@ - + Magento\Config\Model\Config\Source\Yesno payment/razorpay/activate_magic_mini_cart @@ -135,6 +135,7 @@ + Setup coupon widget on Magic Checkout modal Magento\Config\Model\Config\Source\Yesno payment/razorpay/allow_coupon_apply_magic diff --git a/view/frontend/web/js/analytics.js b/view/frontend/web/js/analytics.js index ceca67b5..50b86306 100644 --- a/view/frontend/web/js/analytics.js +++ b/view/frontend/web/js/analytics.js @@ -52,6 +52,7 @@ define(['jquery'], function ($) { discount: element.discount.toFixed(2), item_brand: element.brand || element.vendor || '', item_variant: element.id || '', + affiliation: cartItem.affiliation, ...itemCategories, }; if (GA4.COUPON) item.coupon = GA4.COUPON; From ab9759bd280c1175b06078454eaa4b3818128324 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Tue, 23 Apr 2024 14:20:32 +0530 Subject: [PATCH 28/67] Fixed the state name issue for Odisha --- Controller/OneClick/StateMap.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Controller/OneClick/StateMap.php b/Controller/OneClick/StateMap.php index f4043410..d764fa9b 100644 --- a/Controller/OneClick/StateMap.php +++ b/Controller/OneClick/StateMap.php @@ -58,7 +58,7 @@ function getStateNameIN($stateName) 'MEGHALAYA' => 'Meghalaya', 'MIZORAM' => 'Mizoram', 'NAGALAND' => 'Nagaland', - 'ODISHA' => 'Orissa', + 'ODISHA' => 'Odisha', 'PONDICHERRY' => 'Pondicherry', 'PUNJAB' => 'Punjab', 'RAJASTHAN' => 'Rajasthan', From 9ee89ab3f44baf601cfc906f1dc0c1a491912ef1 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Thu, 2 May 2024 12:41:16 +0530 Subject: [PATCH 29/67] Added auto refund for out of stock inventory case and added logged in customer email in notes --- Controller/OneClick/CompleteOrder.php | 394 +++++++++++++++----------- Controller/OneClick/PlaceOrder.php | 54 +++- view/frontend/web/js/magic-buy-now.js | 34 ++- view/frontend/web/js/magic-cart.js | 25 +- 4 files changed, 304 insertions(+), 203 deletions(-) diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index 9bbcbb63..93218cc4 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -96,6 +96,8 @@ class CompleteOrder extends Action const RAZORPAY = 'razorpay'; const STATE_PENDING_PAYMENT = 'pending_payment'; const STATE_PROCESSING = 'processing'; + const QUOTE_LINKED_RAZORPAY_ORDER_ID = "quote_linked_razorpay_order_id"; + const INVENTORY_OUT_OF_STOCK = "Some of the products are out of stock"; /** * CompleteOrder constructor. @@ -174,219 +176,268 @@ public function execute() $rzpOrderId = $params['razorpay_order_id']; $rzpPaymentId = $params['razorpay_payment_id']; - $rzpOrderData = $this->rzp->order->fetch($rzpOrderId); - $rzpPaymentData = $this->rzp->payment->fetch($rzpPaymentId); + try { + $rzpOrderData = $this->rzp->order->fetch($rzpOrderId); + $rzpPaymentData = $this->rzp->payment->fetch($rzpPaymentId); - $cartId = isset($rzpOrderData->notes) ? $rzpOrderData->notes->cart_id : null; - $email = $rzpOrderData->customer_details->email ?? null; + $cartMaskId = isset($rzpOrderData->notes) ? $rzpOrderData->notes->cart_mask_id : null; - $quote = $this->cartRepositoryInterface->get($cartId); + $this->validateSignature($params, $cartMaskId); - $this->updateQuote($quote, $rzpOrderData, $rzpPaymentData); + $cartId = isset($rzpOrderData->notes) ? $rzpOrderData->notes->cart_id : null; + $email = $rzpOrderData->customer_details->email ?? null; - $quoteId = $rzpOrderData->notes->cart_mask_id; + $quote = $this->cartRepositoryInterface->get($cartId); - // Set customer to quote - $customerCartId = $this->cartConverter->convertGuestCartToCustomer($cartId); - $this->logger->info('graphQL: customerCartId ' . $customerCartId); + $this->updateQuote($quote, $rzpOrderData, $rzpPaymentData); - $isCustomerConsentSet = false; - if ($isCustomerConsentSet === true) { - // Subscribe news letter based on customer consent data - $subscribeNewsLetter = $this->customerConsent->subscribeCustomer($customerCartId, $email); - $this->logger->info('graphQL: subscribed ' . $subscribeNewsLetter); - } + $quoteId = $rzpOrderData->notes->cart_mask_id; - $orderId = $this->cartManagement->placeOrder($cartId); - $order = $this->order->load($orderId); + // Set customer to quote + $customerCartId = $this->cartConverter->convertGuestCartToCustomer($cartId); + $this->logger->info('graphQL: customerCartId ' . $customerCartId); - $order->setEmailSent(0); - if ($order) { - // Return to failure page if payment is failed. - if ($rzpPaymentData->status === 'failed') { - $result = [ - 'status' => 'failed' - ]; - - return $resultJson->setData($result); + $isCustomerConsentSet = false; + if ($isCustomerConsentSet === true) { + // Subscribe news letter based on customer consent data + $subscribeNewsLetter = $this->customerConsent->subscribeCustomer($customerCartId, $email); + $this->logger->info('graphQL: subscribed ' . $subscribeNewsLetter); } - if ($order->getStatus() === 'pending') { - if ($rzpPaymentData->status === 'pending' && $rzpPaymentData->method === 'cod') { - $order->setState(static::STATE_PENDING_PAYMENT) - ->setStatus(static::STATE_PENDING_PAYMENT); - } else { - $order->setState(static::STATE_PROCESSING) - ->setStatus(static::STATE_PROCESSING); + $orderId = $this->cartManagement->placeOrder($cartId); + $order = $this->order->load($orderId); + + $order->setEmailSent(0); + if ($order) { + // Return to failure page if payment is failed. + if ($rzpPaymentData->status === 'failed') { + $result = [ + 'status' => 'failed' + ]; + + return $resultJson->setData($result); } - $this->logger->info('graphQL: Order Status Updated to ' . $this->orderStatus); - } + if ($order->getStatus() === 'pending') { + if ($rzpPaymentData->status === 'pending' && $rzpPaymentData->method === 'cod') { + $order->setState(static::STATE_PENDING_PAYMENT) + ->setStatus(static::STATE_PENDING_PAYMENT); + } else { + $order->setState(static::STATE_PROCESSING) + ->setStatus(static::STATE_PROCESSING); + } - if (!empty($rzpOrderData->offers)) { - $discountAmount = $order->getDiscountAmount(); + $this->logger->info('graphQL: Order Status Updated to ' . $this->orderStatus); + } - $codFee = $rzpOrderData->cod_fee; - $totalPaid = $rzpPaymentData->amount; + if (!empty($rzpOrderData->offers)) { + $discountAmount = $order->getDiscountAmount(); - $rzpPromotionAmount = 0; + $codFee = $rzpOrderData->cod_fee; + $totalPaid = $rzpPaymentData->amount; - foreach ($rzpOrderData->promotions as $promotion) { - if (empty($promotion['code']) === false) { - $rzpPromotionAmount = $promotion['value']; + $rzpPromotionAmount = 0; + + foreach ($rzpOrderData->promotions as $promotion) { + if (empty($promotion['code']) === false) { + $rzpPromotionAmount = $promotion['value']; + } } - } - $offerDiff = $rzpOrderData->line_items_total + $rzpOrderData->shipping_fee + $codFee - $totalPaid - $rzpPromotionAmount; + $offerDiff = $rzpOrderData->line_items_total + $rzpOrderData->shipping_fee + $codFee - $totalPaid - $rzpPromotionAmount; - if ($offerDiff > 0) { - $offerDiscount = ($offerDiff / 100); - // abs is used here as discount amount is returned as minus from order object. - $newDiscountAmount = abs($discountAmount) + $offerDiscount; + if ($offerDiff > 0) { + $offerDiscount = ($offerDiff / 100); + // abs is used here as discount amount is returned as minus from order object. + $newDiscountAmount = abs($discountAmount) + $offerDiscount; - $this->logger->info('graphQL: offerDiscount ' . $offerDiscount); - $this->logger->info('graphQL: newDiscountAmount ' . $newDiscountAmount); - $this->logger->info('graphQL: offerDiff ' . $offerDiff); - $this->logger->info('graphQL: codFee ' . $codFee); - $this->logger->info('graphQL: discountAmount ' . $discountAmount); + $this->logger->info('graphQL: offerDiscount ' . $offerDiscount); + $this->logger->info('graphQL: newDiscountAmount ' . $newDiscountAmount); + $this->logger->info('graphQL: offerDiff ' . $offerDiff); + $this->logger->info('graphQL: codFee ' . $codFee); + $this->logger->info('graphQL: discountAmount ' . $discountAmount); - $this->updateDiscountAmount($orderId, $newDiscountAmount, $offerDiscount, $totalPaid); + $this->updateDiscountAmount($orderId, $newDiscountAmount, $offerDiscount, $totalPaid); + } } - } - $payment = $order->getPayment(); - - $payment->setLastTransId($rzpPaymentId) - ->setTransactionId($rzpPaymentId) - ->setIsTransactionClosed(true) - ->setShouldCloseParentTransaction(true); - - $payment->setParentTransactionId($payment->getTransactionId()); - - if ($rzpPaymentData->method != 'cod') { - if ($this->config->getPaymentAction() === \Razorpay\Magento\Model\PaymentMethod::ACTION_AUTHORIZE_CAPTURE) { - $payment->addTransactionCommentsToOrder( - "$rzpPaymentId", - $this->captureCommand->execute( - $payment, - $order->getGrandTotal(), - $order - ), - "" - ); + $payment = $order->getPayment(); + + $payment->setLastTransId($rzpPaymentId) + ->setTransactionId($rzpPaymentId) + ->setIsTransactionClosed(true) + ->setShouldCloseParentTransaction(true); + + $payment->setParentTransactionId($payment->getTransactionId()); + + if ($rzpPaymentData->method != 'cod') { + if ($this->config->getPaymentAction() === \Razorpay\Magento\Model\PaymentMethod::ACTION_AUTHORIZE_CAPTURE) { + $payment->addTransactionCommentsToOrder( + "$rzpPaymentId", + $this->captureCommand->execute( + $payment, + $order->getGrandTotal(), + $order + ), + "" + ); + } else { + $payment->addTransactionCommentsToOrder( + "$rzpPaymentId", + $this->authorizeCommand->execute( + $payment, + $order->getGrandTotal(), + $order + ), + "" + ); + } + $this->logger->info('Payment authorized completed for id : ' . $order->getIncrementId()); + } else { - $payment->addTransactionCommentsToOrder( - "$rzpPaymentId", - $this->authorizeCommand->execute( - $payment, - $order->getGrandTotal(), - $order - ), - "" - ); + $order->addStatusHistoryComment("Razorpay Payment Id " . $rzpPaymentId)->setStatus($order->getStatus())->setIsCustomerNotified(true); } - $this->logger->info('Payment authorized completed for id : ' . $order->getIncrementId()); - } else { - $order->addStatusHistoryComment("Razorpay Payment Id " . $rzpPaymentId)->setStatus($order->getStatus())->setIsCustomerNotified(true); - } - - $transaction = $payment->addTransaction(\Magento\Sales\Model\Order\Payment\Transaction::TYPE_AUTH, null, true, ""); - - $transaction->setIsClosed(true); + $transaction = $payment->addTransaction(\Magento\Sales\Model\Order\Payment\Transaction::TYPE_AUTH, null, true, ""); - $transaction->save(); + $transaction->setIsClosed(true); - $this->logger->info('Payment authorized completed for id : ' . $order->getIncrementId()); + $transaction->save(); - if ($order->canInvoice() && $this->config->canAutoGenerateInvoice() - && $rzpOrderData->status === 'paid') { - $invoice = $this->invoiceService->prepareInvoice($order); - $invoice->setRequestedCaptureCase(\Magento\Sales\Model\Order\Invoice::CAPTURE_ONLINE); - $invoice->setTransactionId($rzpPaymentId); - $invoice->register(); - $invoice->save(); - - $this->logger->info('graphQL: Created Invoice for ' - . 'order_id ' . $rzpOrderId . ', ' - . 'rzp_payment_id ' . $rzpPaymentId); + $this->logger->info('Payment authorized completed for id : ' . $order->getIncrementId()); - $transactionSave = $this->transaction - ->addObject($invoice) - ->addObject($invoice->getOrder()); - $transactionSave->save(); + if ($order->canInvoice() && $this->config->canAutoGenerateInvoice() + && $rzpOrderData->status === 'paid') { + $invoice = $this->invoiceService->prepareInvoice($order); + $invoice->setRequestedCaptureCase(\Magento\Sales\Model\Order\Invoice::CAPTURE_ONLINE); + $invoice->setTransactionId($rzpPaymentId); + $invoice->register(); + $invoice->save(); + + $this->logger->info('graphQL: Created Invoice for ' + . 'order_id ' . $rzpOrderId . ', ' + . 'rzp_payment_id ' . $rzpPaymentId); + + $transactionSave = $this->transaction + ->addObject($invoice) + ->addObject($invoice->getOrder()); + $transactionSave->save(); + + $this->invoiceSender->send($invoice); + + $order->addStatusHistoryComment( + __('Notified customer about invoice #%1.', $invoice->getId()) + )->setIsCustomerNotified(true); + + $this->logger->info('Invoice generated for id : ' . $order->getIncrementId()); + } else if ($rzpOrderData->status === 'paid' and + ($order->canInvoice() === false or + $this->config->canAutoGenerateInvoice() === false)) { + $this->logger->info('Invoice generation not possible for id : ' . $order->getIncrementId()); + } - $this->invoiceSender->send($invoice); + $comment = __('Razorpay order id %1.', $rzpOrderId); $order->addStatusHistoryComment( - __('Notified customer about invoice #%1.', $invoice->getId()) - )->setIsCustomerNotified(true); - - $this->logger->info('Invoice generated for id : ' . $order->getIncrementId()); - } else if ($rzpOrderData->status === 'paid' and - ($order->canInvoice() === false or - $this->config->canAutoGenerateInvoice() === false)) { - $this->logger->info('Invoice generation not possible for id : ' . $order->getIncrementId()); - } + $comment + )->setStatus($order->getStatus())->setIsCustomerNotified(true); - $comment = __('Razorpay order id %1.', $rzpOrderId); + $comment = __('Razorpay magic order.'); - $order->addStatusHistoryComment( - $comment - )->setStatus($order->getStatus())->setIsCustomerNotified(true); + $order->addStatusHistoryComment( + $comment + )->setStatus($order->getStatus())->setIsCustomerNotified(true); + + try { + $this->checkoutSession->setRazorpayMailSentOnSuccess(true); + $this->orderSender->send($order); + $this->checkoutSession->unsRazorpayMailSentOnSuccess(); + } catch (\Magento\Framework\Exception\MailException $e) { + $this->logger->critical('graphQL: ' + . 'Razorpay Error:' . $e->getMessage()); + + throw new GraphQlInputException(__('Razorpay Error: %1.', $e->getMessage())); + } catch (\Exception $e) { + $this->logger->critical('graphQL: ' + . 'Error:' . $e->getMessage()); + + throw new GraphQlInputException(__('Error: %1.', $e->getMessage())); + } - $comment = __('Razorpay magic order.'); + $this + ->checkoutSession + ->setLastSuccessQuoteId($order->getQuoteId()) + ->setLastQuoteId($order->getQuoteId()) + ->clearHelperData(); + if (empty($order) === false) { + $this + ->checkoutSession + ->setLastOrderId($order->getId()) + ->setLastRealOrderId($order->getIncrementId()) + ->setLastOrderStatus($order->getStatus()); + } - $order->addStatusHistoryComment( - $comment - )->setStatus($order->getStatus())->setIsCustomerNotified(true); + $order->save(); - try { - $this->checkoutSession->setRazorpayMailSentOnSuccess(true); - $this->orderSender->send($order); - $this->checkoutSession->unsRazorpayMailSentOnSuccess(); - } catch (\Magento\Framework\Exception\MailException $e) { - $this->logger->critical('graphQL: ' - . 'Razorpay Error:' . $e->getMessage()); + // Get applied discounts data from the order object + $appliedDiscounts = $this->getAppliedDiscounts($order); - throw new GraphQlInputException(__('Razorpay Error: %1.', $e->getMessage())); - } catch (\Exception $e) { - $this->logger->critical('graphQL: ' - . 'Error:' . $e->getMessage()); + $result = [ + 'status' => 'success', + 'order_id' => $order->getIncrementId(), + 'total_amount' => $order->getGrandTotal() * 100, + 'total_tax' => $order->getTaxAmount() * 100, + 'shipping_fee' => $order->getShippingAmount() * 100, + 'promotions' => $appliedDiscounts, + 'cod_fee' => 0 + ]; - throw new GraphQlInputException(__('Error: %1.', $e->getMessage())); - } + return $resultJson->setData($result); - $this - ->checkoutSession - ->setLastSuccessQuoteId($order->getQuoteId()) - ->setLastQuoteId($order->getQuoteId()) - ->clearHelperData(); - if (empty($order) === false) { - $this - ->checkoutSession - ->setLastOrderId($order->getId()) - ->setLastRealOrderId($order->getIncrementId()) - ->setLastOrderStatus($order->getStatus()); } + } catch (\Razorpay\Api\Errors\Error $e) { + $this->logger->critical("Validate: Razorpay Error message:" . $e->getMessage()); - $order->save(); + $code = $e->getCode(); + $this->messageManager->addError(__('Payment Failed.')); - // Get applied discounts data from the order object - $appliedDiscounts = $this->getAppliedDiscounts($order); - - $result = [ - 'status' => 'success', - 'order_id' => $order->getIncrementId(), - 'total_amount' => $order->getGrandTotal() * 100, - 'total_tax' => $order->getTaxAmount() * 100, - 'shipping_fee' => $order->getShippingAmount() * 100, - 'promotions' => $appliedDiscounts, - 'cod_fee' => 0 - ]; + return $resultJson->setData([ + 'status' => 'error', + 'code' => $code, + 'message' => __('An error occurred on the server. Please try again after sometime.' . $e->getMessage()), + ])->setHttpResponseCode(500); + } catch (\Exception $e) { + $this->logger->critical("Validate: Exception Error message:" . $e->getMessage()); + $this->messageManager->addError(__('Payment Failed.')); + + $code = $e->getCode(); + + if (strpos($e->getMessage(), static::INVENTORY_OUT_OF_STOCK) !== false && $rzpPaymentData->method != 'cod') + $refundData = [ + 'amount' => $rzpPaymentData['amount'], + 'receipt' => $rzpOrderData['receipt'], + 'notes' => [ + 'reason' => $e->getMessage(), + 'order_id' => $rzpOrderData['receipt'], + 'refund_from_magic' => true, + 'source' => 'Magento', + ] + ]; - return $resultJson->setData($result); + try { + $refund = $this->rzp->payment + ->fetch($rzpPaymentId) + ->refund($refundData); + } catch (\Exception $e) { + $this->logger->critical("Razorpay refund failed" . $e->getMessage()); + } + } + return $resultJson->setData([ + 'status' => 'error', + 'code' => $code, + 'message' => __('An error occurred on the server. Please try again.' . $e->getMessage()), + ])->setHttpResponseCode(500); } } @@ -534,7 +585,7 @@ protected function getAddress($rzpAddress, $regionCode, $email) ]; } - protected function validateSignature($request) + protected function validateSignature($request, $cartMaskId) { if (empty($request['error']) === false) { $this @@ -545,15 +596,16 @@ protected function validateSignature($request) ->addError(__('Payment Failed')); throw new \Exception("Payment Failed or error from gateway"); } + $catalogRzpKey = static::QUOTE_LINKED_RAZORPAY_ORDER_ID . '_' . $cartMaskId; + $rzpOrderIdFromSession = $this->checkoutSession->getData($catalogRzpKey); $this->logger->info('razorpay_payment_id = ' . $request['razorpay_payment_id']); - $this->logger->info('razorpay_order_id = ' . $request['razorpay_order_id']); + $this->logger->info('razorpay_order_id = ' . $rzpOrderIdFromSession); $this->logger->info('razorpay_signature = ' . $request['razorpay_signature']); - $attributes = array( 'razorpay_payment_id' => $request['razorpay_payment_id'], - 'razorpay_order_id' => $request['razorpay_order_id'], + 'razorpay_order_id' => $rzpOrderIdFromSession, 'razorpay_signature' => $request['razorpay_signature'], ); diff --git a/Controller/OneClick/PlaceOrder.php b/Controller/OneClick/PlaceOrder.php index 152dcee5..c7327b18 100644 --- a/Controller/OneClick/PlaceOrder.php +++ b/Controller/OneClick/PlaceOrder.php @@ -24,6 +24,7 @@ use Magento\Store\Model\StoreManagerInterface; use Magento\Quote\Model\ResourceModel\Quote\QuoteIdMask as QuoteIdMaskResourceModel; use Magento\Checkout\Model\Session; +use Magento\Customer\Model\Session as CustomerSession; use Magento\SalesSequence\Model\Manager as SequenceManager; use Magento\ConfigurableProduct\Model\Product\Type\Configurable as ConfigurableProduct; use Magento\GroupedProduct\Model\Product\Type\Grouped as GroupedProduct; @@ -89,6 +90,9 @@ class PlaceOrder extends Action protected $configurableProduct; protected $groupedProduct; + protected $customerSession; + + const QUOTE_LINKED_RAZORPAY_ORDER_ID = "quote_linked_razorpay_order_id"; /** * PlaceOrder constructor. @@ -122,7 +126,8 @@ public function __construct( SequenceManager $sequenceManager, QuoteFactory $quoteFactory, ConfigurableProduct $configurableProduct, - GroupedProduct $groupedProduct + GroupedProduct $groupedProduct, + CustomerSession $customerSession ) { parent::__construct($context); @@ -145,6 +150,7 @@ public function __construct( $this->quoteFactory = $quoteFactory; $this->configurableProduct = $configurableProduct; $this->groupedProduct = $groupedProduct; + $this->customerSession = $customerSession; } public function execute() @@ -303,23 +309,38 @@ public function execute() $this->getLastOrderId($quote); + $orderNotes = [ + 'cart_mask_id' => $maskedId, + 'cart_id' => $quoteId, + 'merchant_order_id' => (string)$quote->getReservedOrderId() ?? 'order pending' + ]; + $customerEmail = $this->getCustomerEmailFromQuote(); + + if($customerEmail !== false) + { + $customerEmailNotes = [ + 'website_logged_in_email' => $customerEmail + ]; + $orderNotes = array_merge($orderNotes, $customerEmailNotes); + } + $razorpay_order = $this->rzp->order->create([ 'amount' => $totalAmount, 'receipt' => (string)$quote->getReservedOrderId() ?? 'order pending', 'currency' => $this->storeManager->getStore()->getBaseCurrencyCode(), 'payment_capture' => $paymentCapture, 'app_offer' => 0, - 'notes' => [ - 'cart_mask_id' => $maskedId, - 'cart_id' => $quoteId, - 'merchant_order_id' => (string)$quote->getReservedOrderId() ?? 'order pending' - ], + 'notes' => $orderNotes, 'line_items_total' => $totalAmount, 'line_items' => $lineItems ]); if (null !== $razorpay_order && !empty($razorpay_order->id)) { $this->logger->info('graphQL: Razorpay Order ID: ' . $razorpay_order->id); + $catalogRzpKey = static::QUOTE_LINKED_RAZORPAY_ORDER_ID.'_'.$maskedId; + $this->logger->info('graphQL: Razorpay Order ID stored catalogKey: ' . $catalogRzpKey); + + $this->checkoutSession->setData($catalogRzpKey, $razorpay_order->id); $result = [ 'status' => 'success', @@ -342,6 +363,27 @@ public function execute() } + public function getCustomerEmailFromQuote() + { + // Check if customer is logged in + if ($this->customerSession->isLoggedIn()) { + // Get active quote associated with customer session + $quote = $this->quoteFactory->create()->loadByCustomer($this->customerSession->getCustomerId()); + + // Retrieve customer email from quote + $customerEmail = $quote->getCustomerEmail(); + + // Check if customer email is available + if ($customerEmail) { + return $customerEmail; + } else { + return false; + } + } else { + return false; + } + } + public function getLastOrderId($quote) { try { diff --git a/view/frontend/web/js/magic-buy-now.js b/view/frontend/web/js/magic-buy-now.js index d1eef9d4..b702d518 100644 --- a/view/frontend/web/js/magic-buy-now.js +++ b/view/frontend/web/js/magic-buy-now.js @@ -105,21 +105,8 @@ define([ data: data, type: 'POST', dataType: 'json', - success: async function (data) { - self.toggleLoader(true); - - if (analytics.MagicMxAnalytics.purchase) { - try { - await Promise.all(analytics.MagicMxAnalytics.purchase({ - ...data, - merchantAnalyticsConfigs: {}, - })); - } catch (error) { - console.error(error); - } - } - var successUrl = url.build('checkout/onepage/success', {}) - window.location.href = successUrl; + success: function(data) { + self.asyncOrderSuccess(data) }, error: function (error) { console.log("Payment complete fail") @@ -128,6 +115,23 @@ define([ }) }, + asyncOrderSuccess: async function (data) { + self.toggleLoader(true); + + if (analytics.MagicMxAnalytics.purchase) { + try { + await Promise.all(analytics.MagicMxAnalytics.purchase({ + ...data, + merchantAnalyticsConfigs: {}, + })); + } catch (error) { + console.error(error); + } + } + var successUrl = url.build('checkout/onepage/success', {}) + window.location.href = successUrl; + }, + renderIframe: function(data) { var self = this; diff --git a/view/frontend/web/js/magic-cart.js b/view/frontend/web/js/magic-cart.js index d1c9e944..8ed2e819 100644 --- a/view/frontend/web/js/magic-cart.js +++ b/view/frontend/web/js/magic-cart.js @@ -103,22 +103,25 @@ define([ data: data, type: 'POST', dataType: 'json', - success: async function (data) { + success: function (data) { self.toggleLoader(true); if (analytics.MagicMxAnalytics.purchase) { - try { - await Promise.all(analytics.MagicMxAnalytics.purchase({ - ...data, - merchantAnalyticsConfigs: {}, - })); - } catch (error) { - console.error(error); - } + analytics.MagicMxAnalytics.purchase({ + ...data, + merchantAnalyticsConfigs: {}, + }).finally(() => { + continueRedirection(); + }) + } else { + continueRedirection(); + } + + function continueRedirection(){ + var successUrl = url.build('checkout/onepage/success', {}) + window.location.href = successUrl; } - var successUrl = url.build('checkout/onepage/success', {}) - window.location.href = successUrl; }, error: function (error) { self.toggleLoader(false); From 9850a30af089edd1a39e2b7beaa9b88150592aa2 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Thu, 2 May 2024 12:45:50 +0530 Subject: [PATCH 30/67] Modified the purchase event push data logic --- view/frontend/web/js/magic-buy-now.js | 38 +++++++++++++-------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/view/frontend/web/js/magic-buy-now.js b/view/frontend/web/js/magic-buy-now.js index b702d518..d662d7f7 100644 --- a/view/frontend/web/js/magic-buy-now.js +++ b/view/frontend/web/js/magic-buy-now.js @@ -105,8 +105,25 @@ define([ data: data, type: 'POST', dataType: 'json', - success: function(data) { - self.asyncOrderSuccess(data) + success: function (data) { + self.toggleLoader(true); + + if (analytics.MagicMxAnalytics.purchase) { + analytics.MagicMxAnalytics.purchase({ + ...data, + merchantAnalyticsConfigs: {}, + }).finally(() => { + continueRedirection(); + }) + } else { + continueRedirection(); + } + + function continueRedirection(){ + var successUrl = url.build('checkout/onepage/success', {}) + window.location.href = successUrl; + } + }, error: function (error) { console.log("Payment complete fail") @@ -115,23 +132,6 @@ define([ }) }, - asyncOrderSuccess: async function (data) { - self.toggleLoader(true); - - if (analytics.MagicMxAnalytics.purchase) { - try { - await Promise.all(analytics.MagicMxAnalytics.purchase({ - ...data, - merchantAnalyticsConfigs: {}, - })); - } catch (error) { - console.error(error); - } - } - var successUrl = url.build('checkout/onepage/success', {}) - window.location.href = successUrl; - }, - renderIframe: function(data) { var self = this; From 28ac68438750d6884694bbaa6dde9883643cb24f Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Thu, 2 May 2024 12:54:56 +0530 Subject: [PATCH 31/67] Syntax issue fix --- Controller/OneClick/CompleteOrder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index 93218cc4..9b75e160 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -413,7 +413,7 @@ public function execute() $code = $e->getCode(); if (strpos($e->getMessage(), static::INVENTORY_OUT_OF_STOCK) !== false && $rzpPaymentData->method != 'cod') - $refundData = [ + { $refundData = [ 'amount' => $rzpPaymentData['amount'], 'receipt' => $rzpOrderData['receipt'], 'notes' => [ From 3326e68ba4fd3f0ab91b4ac6e0be5d28aa2ff472 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Wed, 15 May 2024 11:11:28 +0530 Subject: [PATCH 32/67] Added website logged in customer email address to order notes --- Controller/OneClick/CompleteOrder.php | 38 +++++++++++++++------------ Controller/OneClick/PlaceOrder.php | 5 +--- view/frontend/web/js/analytics.js | 2 +- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index 9b75e160..ec5250d5 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -412,25 +412,29 @@ public function execute() $code = $e->getCode(); - if (strpos($e->getMessage(), static::INVENTORY_OUT_OF_STOCK) !== false && $rzpPaymentData->method != 'cod') - { $refundData = [ - 'amount' => $rzpPaymentData['amount'], - 'receipt' => $rzpOrderData['receipt'], - 'notes' => [ - 'reason' => $e->getMessage(), - 'order_id' => $rzpOrderData['receipt'], - 'refund_from_magic' => true, - 'source' => 'Magento', - ] - ]; + if (strpos($e->getMessage(), static::INVENTORY_OUT_OF_STOCK) !== false) { + if ($rzpPaymentData->method != 'cod') { + $refundData = [ + 'amount' => $rzpPaymentData['amount'], + 'receipt' => $rzpOrderData['receipt'], + 'notes' => [ + 'reason' => $e->getMessage(), + 'order_id' => $rzpOrderData['receipt'], + 'refund_from_magic' => true, + 'source' => 'Magento', + ] + ]; - try { - $refund = $this->rzp->payment - ->fetch($rzpPaymentId) - ->refund($refundData); - } catch (\Exception $e) { - $this->logger->critical("Razorpay refund failed" . $e->getMessage()); + try { + $refund = $this->rzp->payment + ->fetch($rzpPaymentId) + ->refund($refundData); + } catch (\Exception $e) { + $this->logger->critical("Razorpay refund failed" . $e->getMessage()); + } } + + $this->messageManager->addError(__($e->getMessage())); } return $resultJson->setData([ diff --git a/Controller/OneClick/PlaceOrder.php b/Controller/OneClick/PlaceOrder.php index c7327b18..67da5d42 100644 --- a/Controller/OneClick/PlaceOrder.php +++ b/Controller/OneClick/PlaceOrder.php @@ -368,10 +368,7 @@ public function getCustomerEmailFromQuote() // Check if customer is logged in if ($this->customerSession->isLoggedIn()) { // Get active quote associated with customer session - $quote = $this->quoteFactory->create()->loadByCustomer($this->customerSession->getCustomerId()); - - // Retrieve customer email from quote - $customerEmail = $quote->getCustomerEmail(); + $customerEmail = $this->customerSession->getCustomer()->getEmail(); // Check if customer email is available if ($customerEmail) { diff --git a/view/frontend/web/js/analytics.js b/view/frontend/web/js/analytics.js index 50b86306..8596d10c 100644 --- a/view/frontend/web/js/analytics.js +++ b/view/frontend/web/js/analytics.js @@ -243,7 +243,7 @@ define(['jquery'], function ($) { sendAnalyticsEvents('payment_failed', data); }, - purchase(data = {}) { + purchase: async (data = {}) => { return Object.entries(enabledAnalyticsTools).map(method => { const toolName = method[0]; const enabled = method[1]; From a6c253d0d0d70357f8e7f1e490aad0fcc50649c8 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Wed, 22 May 2024 19:22:50 +0530 Subject: [PATCH 33/67] Added Abandoned quote update feature --- Controller/OneClick/AbandonedQuote.php | 230 +++++++++++++++++++++++++ view/frontend/web/js/magic-buy-now.js | 21 +++ view/frontend/web/js/magic-cart.js | 22 +++ 3 files changed, 273 insertions(+) create mode 100644 Controller/OneClick/AbandonedQuote.php diff --git a/Controller/OneClick/AbandonedQuote.php b/Controller/OneClick/AbandonedQuote.php new file mode 100644 index 00000000..4af2f057 --- /dev/null +++ b/Controller/OneClick/AbandonedQuote.php @@ -0,0 +1,230 @@ +request = $request; + $this->resultJsonFactory = $jsonFactory; + $this->config = $config; + $this->rzp = $paymentMethod->setAndGetRzpApiInstance(); + $this->logger = $logger; + $this->cartRepositoryInterface = $cartRepositoryInterface; + $this->checkoutSession = $checkoutSession; + $this->collectionFactory = $collectionFactory; + $this->stateNameMap = $stateNameMap; + $this->cartConverter = $cartConverter; + } + + public function execute() + { + $params = $this->request->getParams(); + + $resultJson = $this->resultJsonFactory->create(); + + $rzpOrderId = $params['rzp_order_id']; + + try { + $rzpOrderData = $this->rzp->order->fetch($rzpOrderId); + + $cartMaskId = isset($rzpOrderData->notes) ? $rzpOrderData->notes->cart_mask_id : null; + + $cartId = isset($rzpOrderData->notes) ? $rzpOrderData->notes->cart_id : null; + $email = $rzpOrderData->customer_details->email ?? null; + + $quote = $this->cartRepositoryInterface->get($cartId); + + $this->updateQuote($quote, $rzpOrderData); + + $quoteId = $rzpOrderData->notes->cart_mask_id; + + // Set customer to quote + $customerCartId = $this->cartConverter->convertGuestCartToCustomer($cartId); + $this->logger->info('graphQL: customerCartId ' . $customerCartId); + + return $resultJson->setData([ + 'status' => 'success', + 'message' => 'Successfully updated the quote', + ])->setHttpResponseCode(200); + + } catch (\Razorpay\Api\Errors\Error $e) { + $this->logger->critical("Validate: Razorpay Error message:" . $e->getMessage()); + + $code = $e->getCode(); + $this->messageManager->addError(__('Payment Failed.')); + + return $resultJson->setData([ + 'status' => 'error', + 'code' => $code, + 'message' => __('An error occurred on the server. Please try again after sometime.'), + ])->setHttpResponseCode(500); + } catch (\Exception $e) { + $this->logger->critical("Validate: Exception Error message:" . $e->getMessage()); + $this->messageManager->addError(__('Payment Failed.')); + + $code = $e->getCode(); + + return $resultJson->setData([ + 'status' => 'error', + 'code' => $code, + 'message' => __('An error occurred on the server. Please try again.'), + ])->setHttpResponseCode(500); + } + } + + protected function updateQuote($quote, $rzpOrderData) + { + $carrierCode = $rzpOrderData->notes->carrier_code ?? 'freeshipping'; + $methodCode = $rzpOrderData->notes->method_code ?? 'freeshipping'; + + $email = $rzpOrderData->customer_details->email ?? ''; + + $quote->setCustomerEmail($email); + + if(empty($rzpOrderData->customer_details->shipping_address) === false) { + + $shippingCountry = $rzpOrderData->customer_details->shipping_address->country; + $shippingState = $rzpOrderData->customer_details->shipping_address->state; + + $billingCountry = $rzpOrderData->customer_details->billing_address->country; + $billingState = $rzpOrderData->customer_details->billing_address->state; + + $shippingRegionCode = $this->getRegionCode($shippingCountry, $shippingState); + $billingRegionCode = $this->getRegionCode($billingCountry, $billingState); + + $shipping = $this->getAddress($rzpOrderData->customer_details->shipping_address, $shippingRegionCode, $email); + $billing = $this->getAddress($rzpOrderData->customer_details->billing_address, $billingRegionCode, $email); + + $quote->getBillingAddress()->addData($billing['address']); + $quote->getShippingAddress()->addData($shipping['address']); + + $shippingMethod = 'NA'; + if (empty($carrierCode) === false && empty($methodCode) === false) { + $shippingMethod = $carrierCode . "_" . $methodCode; + } + + $shippingAddress = $quote->getShippingAddress(); + $shippingAddress->setCollectShippingRates(true) + ->collectShippingRates() + ->setShippingMethod($shippingMethod); + + } + $paymentMethod = static::RAZORPAY; + + $quote->setPaymentMethod($paymentMethod); + $quote->setInventoryProcessed(false); + // Set Sales Order Payment + $quote->getPayment()->importData(['method' => $paymentMethod]); + + $quote->save(); + + } + + protected function getRegionCode($country, $state) + { + $magentoStateName = $this->stateNameMap->getMagentoStateName($country, $state); + + $this->logger->info('graphQL: Magento state name:' . $magentoStateName); + + $regionCode = $this->collectionFactory->create() + ->addRegionNameFilter($magentoStateName) + ->getFirstItem() + ->toArray(); + + return $regionCode['code'] ?? 'NA'; + + } + + protected function getAddress($rzpAddress, $regionCode, $email) + { + $name = explode(' ', $rzpAddress->name); + + return [ + 'email' => $email, //buyer email id + 'address' => [ + 'firstname' => $name[0], //address Details + 'lastname' => empty($name[1]) === false ? $name[1] : '.', + 'street' => $rzpAddress->line1, + 'city' => $rzpAddress->city, + 'country_id' => strtoupper($rzpAddress->country), + 'region' => $regionCode, + 'postcode' => $rzpAddress->zipcode, + 'telephone' => $rzpAddress->contact, + 'save_in_address_book' => 1 + ] + ]; + } +} \ No newline at end of file diff --git a/view/frontend/web/js/magic-buy-now.js b/view/frontend/web/js/magic-buy-now.js index d662d7f7..2c37c710 100644 --- a/view/frontend/web/js/magic-buy-now.js +++ b/view/frontend/web/js/magic-buy-now.js @@ -132,8 +132,28 @@ define([ }) }, + abandonedCart: function (rzp_order_id) { + var self = this; + + var abandonedQuote = url.build('razorpay/oneclick/abandonedQuote', {}) + $.ajax({ + url: abandonedQuote, + data: {'rzp_order_id': rzp_order_id }, + type: 'POST', + dataType: 'json', + success: function (data) { + console.log(data) + }, + error: function (error) { + console.log("Payment complete fail") + console.log(error) + } + }) + }, + renderIframe: function(data) { var self = this; + var rzp_order_id = data.rzp_order_id; var options = { key: data.rzp_key_id, @@ -153,6 +173,7 @@ define([ // fullScreenLoader.stopLoader(); // self.isPaymentProcessing.reject("Payment Closed"); // self.isPlaceOrderActionAllowed(true); + self.abandonedCart(rzp_order_id); self.enableButton(); } diff --git a/view/frontend/web/js/magic-cart.js b/view/frontend/web/js/magic-cart.js index 8ed2e819..4e3572ed 100644 --- a/view/frontend/web/js/magic-cart.js +++ b/view/frontend/web/js/magic-cart.js @@ -132,8 +132,29 @@ define([ }) }, + abandonedCart: function (rzp_order_id) { + var self = this; + + var abandonedQuote = url.build('razorpay/oneclick/abandonedQuote', {}) + $.ajax({ + url: abandonedQuote, + data: {'rzp_order_id': rzp_order_id }, + type: 'POST', + dataType: 'json', + success: function (data) { + console.log(data) + + }, + error: function (error) { + console.log("Payment complete fail") + console.log(error) + } + }) + }, + renderIframe: function(data) { var self = this; + var rzp_order_id = data.rzp_order_id; var options = { key: data.rzp_key_id, @@ -150,6 +171,7 @@ define([ order_id: data.rzp_order_id, modal: { ondismiss: function (data) { + self.abandonedCart(rzp_order_id); self.enableButton(); //reset the cart From 638e12adbfc388af4bc16f10b8ea9e9a7fdf2189 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Fri, 24 May 2024 11:18:56 +0530 Subject: [PATCH 34/67] Added GSTIN field to magento order --- Controller/OneClick/CompleteOrder.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index ec5250d5..fcdfb43c 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -261,6 +261,11 @@ public function execute() } } + if ($order->getData('customer_gstin')) { + $gstin = $rzpOrderData->notes->gstin ?? ''; + $order->setData('customer_gstin', $gstin); + } + $payment = $order->getPayment(); $payment->setLastTransId($rzpPaymentId) From f39bd80a683e3d7d1f39663130629081bb4dd3bb Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Fri, 21 Jun 2024 11:19:18 +0530 Subject: [PATCH 35/67] Exit the webhook process if it's a magic order --- Controller/Payment/Webhook.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Controller/Payment/Webhook.php b/Controller/Payment/Webhook.php index f961700d..9e40f3f5 100644 --- a/Controller/Payment/Webhook.php +++ b/Controller/Payment/Webhook.php @@ -202,6 +202,11 @@ public function execute() exit; } + if (isset($post['payload']['payment']['entity']['notes']['carrier_code']) === true) { + $this->debug->log("Razorpay Webhook processing stopped as order is magic checkout order"); + return; + } + if (isset($post['payload']['payment']['entity']['notes']['merchant_order_id']) === true) { $orderId = $post['payload']['payment']['entity']['notes']['merchant_order_id']; From b12d6719dfdd317a49c495489194259116ab539f Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Fri, 5 Jul 2024 16:34:47 +0530 Subject: [PATCH 36/67] Order placement cron job in case of callback fails and AB cart pending orders --- Controller/OneClick/AbandonedQuote.php | 60 +++- Controller/OneClick/CompleteOrder.php | 423 +++++++++++++------------ Controller/OneClick/PlaceOrder.php | 9 + Controller/Payment/Webhook.php | 92 +++++- Cron/UpdateOrdersToProcessingV2.php | 310 +++++++++--------- 5 files changed, 538 insertions(+), 356 deletions(-) diff --git a/Controller/OneClick/AbandonedQuote.php b/Controller/OneClick/AbandonedQuote.php index 4af2f057..04e3e59f 100644 --- a/Controller/OneClick/AbandonedQuote.php +++ b/Controller/OneClick/AbandonedQuote.php @@ -15,6 +15,7 @@ use Magento\Directory\Model\ResourceModel\Region\CollectionFactory; use Magento\Directory\Model\ResourceModel\Region\Collection; use Razorpay\Magento\Model\CartConverter; +use Magento\Quote\Api\CartManagementInterface; class AbandonedQuote extends Action { @@ -49,9 +50,12 @@ class AbandonedQuote extends Action protected $checkoutSession; protected $stateNameMap; protected $cartConverter; + protected $cartManagement; + protected $order; const COD = 'cashondelivery'; const RAZORPAY = 'razorpay'; + const STATE_PENDING_PAYMENT = 'pending_payment'; /** * CompleteOrder constructor. @@ -63,17 +67,19 @@ class AbandonedQuote extends Action * @param \Psr\Log\LoggerInterface $logger */ public function __construct( - Context $context, - Http $request, - JsonFactory $jsonFactory, - PaymentMethod $paymentMethod, - \Razorpay\Magento\Model\Config $config, - \Psr\Log\LoggerInterface $logger, - \Magento\Quote\Api\CartRepositoryInterface $cartRepositoryInterface, - \Magento\Checkout\Model\Session $checkoutSession, - CollectionFactory $collectionFactory, - StateMap $stateNameMap, - CartConverter $cartConverter + Context $context, + Http $request, + JsonFactory $jsonFactory, + PaymentMethod $paymentMethod, + \Razorpay\Magento\Model\Config $config, + \Psr\Log\LoggerInterface $logger, + \Magento\Quote\Api\CartRepositoryInterface $cartRepositoryInterface, + \Magento\Checkout\Model\Session $checkoutSession, + CollectionFactory $collectionFactory, + StateMap $stateNameMap, + CartConverter $cartConverter, + CartManagementInterface $cartManagement, + \Magento\Sales\Model\Order $order ) { parent::__construct($context); @@ -87,6 +93,8 @@ public function __construct( $this->collectionFactory = $collectionFactory; $this->stateNameMap = $stateNameMap; $this->cartConverter = $cartConverter; + $this->cartManagement = $cartManagement; + $this->order = $order; } public function execute() @@ -104,6 +112,7 @@ public function execute() $cartId = isset($rzpOrderData->notes) ? $rzpOrderData->notes->cart_id : null; $email = $rzpOrderData->customer_details->email ?? null; + $reservedOrderId = isset($rzpOrderData->notes) ? $rzpOrderData->notes->merchant_order_id : null; $quote = $this->cartRepositoryInterface->get($cartId); @@ -114,10 +123,33 @@ public function execute() // Set customer to quote $customerCartId = $this->cartConverter->convertGuestCartToCustomer($cartId); $this->logger->info('graphQL: customerCartId ' . $customerCartId); + $orderPlacement = false; + + try { + $order = $this->order->loadByIncrementId($reservedOrderId); + + if (!$order->getId()) { + $orderId = $this->cartManagement->placeOrder($cartId); + $order = $this->order->load($orderId); + $orderPlacement = true; + } + + $order->setEmailSent(0); + if ($order) { + $order->setState(static::STATE_PENDING_PAYMENT) + ->setStatus(static::STATE_PENDING_PAYMENT); + } + $order->save(); + $quote->setIsActive(true)->save(); + + } catch (\Exception $e) { + $this->logger->info('graphQL: magento pending order placement failed for AB cart and rzp order id: '.$rzpOrderId); + } return $resultJson->setData([ 'status' => 'success', 'message' => 'Successfully updated the quote', + 'orderPlacement' => $orderPlacement, ])->setHttpResponseCode(200); } catch (\Razorpay\Api\Errors\Error $e) { @@ -129,7 +161,7 @@ public function execute() return $resultJson->setData([ 'status' => 'error', 'code' => $code, - 'message' => __('An error occurred on the server. Please try again after sometime.'), + 'message' => __('An error occurred on the server. Please try again after sometime.' . $e->getMessage()), ])->setHttpResponseCode(500); } catch (\Exception $e) { $this->logger->critical("Validate: Exception Error message:" . $e->getMessage()); @@ -145,7 +177,7 @@ public function execute() } } - protected function updateQuote($quote, $rzpOrderData) + public function updateQuote($quote, $rzpOrderData) { $carrierCode = $rzpOrderData->notes->carrier_code ?? 'freeshipping'; $methodCode = $rzpOrderData->notes->method_code ?? 'freeshipping'; @@ -154,7 +186,7 @@ protected function updateQuote($quote, $rzpOrderData) $quote->setCustomerEmail($email); - if(empty($rzpOrderData->customer_details->shipping_address) === false) { + if (empty($rzpOrderData->customer_details->shipping_address) === false) { $shippingCountry = $rzpOrderData->customer_details->shipping_address->country; $shippingState = $rzpOrderData->customer_details->shipping_address->state; diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index fcdfb43c..e2368f41 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -24,6 +24,7 @@ use Razorpay\Magento\Controller\OneClick\StateMap; use Razorpay\Magento\Model\CartConverter; use Razorpay\Magento\Model\CustomerConsent; +use Razorpay\Magento\Constants\OrderCronStatus; class CompleteOrder extends Action { @@ -204,202 +205,10 @@ public function execute() $this->logger->info('graphQL: subscribed ' . $subscribeNewsLetter); } - $orderId = $this->cartManagement->placeOrder($cartId); - $order = $this->order->load($orderId); - - $order->setEmailSent(0); - if ($order) { - // Return to failure page if payment is failed. - if ($rzpPaymentData->status === 'failed') { - $result = [ - 'status' => 'failed' - ]; - - return $resultJson->setData($result); - } - - if ($order->getStatus() === 'pending') { - if ($rzpPaymentData->status === 'pending' && $rzpPaymentData->method === 'cod') { - $order->setState(static::STATE_PENDING_PAYMENT) - ->setStatus(static::STATE_PENDING_PAYMENT); - } else { - $order->setState(static::STATE_PROCESSING) - ->setStatus(static::STATE_PROCESSING); - } - - $this->logger->info('graphQL: Order Status Updated to ' . $this->orderStatus); - } - - if (!empty($rzpOrderData->offers)) { - $discountAmount = $order->getDiscountAmount(); - - $codFee = $rzpOrderData->cod_fee; - $totalPaid = $rzpPaymentData->amount; - - $rzpPromotionAmount = 0; - - foreach ($rzpOrderData->promotions as $promotion) { - if (empty($promotion['code']) === false) { - $rzpPromotionAmount = $promotion['value']; - } - } - - $offerDiff = $rzpOrderData->line_items_total + $rzpOrderData->shipping_fee + $codFee - $totalPaid - $rzpPromotionAmount; - - if ($offerDiff > 0) { - $offerDiscount = ($offerDiff / 100); - // abs is used here as discount amount is returned as minus from order object. - $newDiscountAmount = abs($discountAmount) + $offerDiscount; - - $this->logger->info('graphQL: offerDiscount ' . $offerDiscount); - $this->logger->info('graphQL: newDiscountAmount ' . $newDiscountAmount); - $this->logger->info('graphQL: offerDiff ' . $offerDiff); - $this->logger->info('graphQL: codFee ' . $codFee); - $this->logger->info('graphQL: discountAmount ' . $discountAmount); - - $this->updateDiscountAmount($orderId, $newDiscountAmount, $offerDiscount, $totalPaid); - } - } - - if ($order->getData('customer_gstin')) { - $gstin = $rzpOrderData->notes->gstin ?? ''; - $order->setData('customer_gstin', $gstin); - } - - $payment = $order->getPayment(); - - $payment->setLastTransId($rzpPaymentId) - ->setTransactionId($rzpPaymentId) - ->setIsTransactionClosed(true) - ->setShouldCloseParentTransaction(true); - - $payment->setParentTransactionId($payment->getTransactionId()); - - if ($rzpPaymentData->method != 'cod') { - if ($this->config->getPaymentAction() === \Razorpay\Magento\Model\PaymentMethod::ACTION_AUTHORIZE_CAPTURE) { - $payment->addTransactionCommentsToOrder( - "$rzpPaymentId", - $this->captureCommand->execute( - $payment, - $order->getGrandTotal(), - $order - ), - "" - ); - } else { - $payment->addTransactionCommentsToOrder( - "$rzpPaymentId", - $this->authorizeCommand->execute( - $payment, - $order->getGrandTotal(), - $order - ), - "" - ); - } - $this->logger->info('Payment authorized completed for id : ' . $order->getIncrementId()); - - } else { - $order->addStatusHistoryComment("Razorpay Payment Id " . $rzpPaymentId)->setStatus($order->getStatus())->setIsCustomerNotified(true); - } - - $transaction = $payment->addTransaction(\Magento\Sales\Model\Order\Payment\Transaction::TYPE_AUTH, null, true, ""); - - $transaction->setIsClosed(true); + $result = $this->placeMagentoOrder($cartId, $rzpPaymentData, $rzpOrderData); - $transaction->save(); + return $resultJson->setData($result); - $this->logger->info('Payment authorized completed for id : ' . $order->getIncrementId()); - - if ($order->canInvoice() && $this->config->canAutoGenerateInvoice() - && $rzpOrderData->status === 'paid') { - $invoice = $this->invoiceService->prepareInvoice($order); - $invoice->setRequestedCaptureCase(\Magento\Sales\Model\Order\Invoice::CAPTURE_ONLINE); - $invoice->setTransactionId($rzpPaymentId); - $invoice->register(); - $invoice->save(); - - $this->logger->info('graphQL: Created Invoice for ' - . 'order_id ' . $rzpOrderId . ', ' - . 'rzp_payment_id ' . $rzpPaymentId); - - $transactionSave = $this->transaction - ->addObject($invoice) - ->addObject($invoice->getOrder()); - $transactionSave->save(); - - $this->invoiceSender->send($invoice); - - $order->addStatusHistoryComment( - __('Notified customer about invoice #%1.', $invoice->getId()) - )->setIsCustomerNotified(true); - - $this->logger->info('Invoice generated for id : ' . $order->getIncrementId()); - } else if ($rzpOrderData->status === 'paid' and - ($order->canInvoice() === false or - $this->config->canAutoGenerateInvoice() === false)) { - $this->logger->info('Invoice generation not possible for id : ' . $order->getIncrementId()); - } - - $comment = __('Razorpay order id %1.', $rzpOrderId); - - $order->addStatusHistoryComment( - $comment - )->setStatus($order->getStatus())->setIsCustomerNotified(true); - - $comment = __('Razorpay magic order.'); - - $order->addStatusHistoryComment( - $comment - )->setStatus($order->getStatus())->setIsCustomerNotified(true); - - try { - $this->checkoutSession->setRazorpayMailSentOnSuccess(true); - $this->orderSender->send($order); - $this->checkoutSession->unsRazorpayMailSentOnSuccess(); - } catch (\Magento\Framework\Exception\MailException $e) { - $this->logger->critical('graphQL: ' - . 'Razorpay Error:' . $e->getMessage()); - - throw new GraphQlInputException(__('Razorpay Error: %1.', $e->getMessage())); - } catch (\Exception $e) { - $this->logger->critical('graphQL: ' - . 'Error:' . $e->getMessage()); - - throw new GraphQlInputException(__('Error: %1.', $e->getMessage())); - } - - $this - ->checkoutSession - ->setLastSuccessQuoteId($order->getQuoteId()) - ->setLastQuoteId($order->getQuoteId()) - ->clearHelperData(); - if (empty($order) === false) { - $this - ->checkoutSession - ->setLastOrderId($order->getId()) - ->setLastRealOrderId($order->getIncrementId()) - ->setLastOrderStatus($order->getStatus()); - } - - $order->save(); - - // Get applied discounts data from the order object - $appliedDiscounts = $this->getAppliedDiscounts($order); - - $result = [ - 'status' => 'success', - 'order_id' => $order->getIncrementId(), - 'total_amount' => $order->getGrandTotal() * 100, - 'total_tax' => $order->getTaxAmount() * 100, - 'shipping_fee' => $order->getShippingAmount() * 100, - 'promotions' => $appliedDiscounts, - 'cod_fee' => 0 - ]; - - return $resultJson->setData($result); - - } } catch (\Razorpay\Api\Errors\Error $e) { $this->logger->critical("Validate: Razorpay Error message:" . $e->getMessage()); @@ -450,6 +259,232 @@ public function execute() } } + public function placeMagentoOrder($cartId, $rzpPaymentData, $rzpOrderData) + { + $merchantOrderId = isset($rzpOrderData->notes) ? $rzpOrderData->notes->merchant_order_id : null; + + $orderLink = $this->_objectManager->get('Razorpay\Magento\Model\OrderLink') + ->getCollection() + ->addFilter('order_id', $merchantOrderId) + ->getFirstItem(); + + $order = $this->order->loadByIncrementId($merchantOrderId); + + if (!$order->getId()) { + $orderId = $this->cartManagement->placeOrder($cartId); + $order = $this->order->load($orderId); + } + + $rzpOrderId = $rzpOrderData->id; + $rzpPaymentId = $rzpPaymentData->id; + + $order->setEmailSent(0); + if ($order) { + // Return to failure page if payment is failed. + if ($rzpPaymentData->status === 'failed') { + $result = [ + 'status' => 'failed' + ]; + + return $result; + } + + if ($order->getStatus() === 'pending') { + if ($rzpPaymentData->status === 'pending' && $rzpPaymentData->method === 'cod') { + $order->setState(static::STATE_PENDING_PAYMENT) + ->setStatus(static::STATE_PENDING_PAYMENT); + } else { + $order->setState(static::STATE_PROCESSING) + ->setStatus(static::STATE_PROCESSING); + } + + $this->logger->info('graphQL: Order Status Updated to ' . $this->orderStatus); + } + + if (!empty($rzpOrderData->offers)) { + $discountAmount = $order->getDiscountAmount(); + + $codFee = $rzpOrderData->cod_fee; + $totalPaid = $rzpPaymentData->amount; + + $rzpPromotionAmount = 0; + + foreach ($rzpOrderData->promotions as $promotion) { + if (empty($promotion['code']) === false) { + $rzpPromotionAmount = $promotion['value']; + } + } + + $offerDiff = $rzpOrderData->line_items_total + $rzpOrderData->shipping_fee + $codFee - $totalPaid - $rzpPromotionAmount; + + if ($offerDiff > 0) { + $offerDiscount = ($offerDiff / 100); + // abs is used here as discount amount is returned as minus from order object. + $newDiscountAmount = abs($discountAmount) + $offerDiscount; + + $this->logger->info('graphQL: offerDiscount ' . $offerDiscount); + $this->logger->info('graphQL: newDiscountAmount ' . $newDiscountAmount); + $this->logger->info('graphQL: offerDiff ' . $offerDiff); + $this->logger->info('graphQL: codFee ' . $codFee); + $this->logger->info('graphQL: discountAmount ' . $discountAmount); + + $this->updateDiscountAmount($orderId, $newDiscountAmount, $offerDiscount, $totalPaid); + } + } + + if ($order->getData('customer_gstin')) { + $gstin = $rzpOrderData->notes->gstin ?? ''; + $order->setData('customer_gstin', $gstin); + } + + $payment = $order->getPayment(); + + $payment->setLastTransId($rzpPaymentId) + ->setTransactionId($rzpPaymentId) + ->setIsTransactionClosed(true) + ->setShouldCloseParentTransaction(true); + + $payment->setParentTransactionId($payment->getTransactionId()); + + if ($rzpPaymentData->method != 'cod') { + if ($this->config->getPaymentAction() === \Razorpay\Magento\Model\PaymentMethod::ACTION_AUTHORIZE_CAPTURE) { + $payment->addTransactionCommentsToOrder( + "$rzpPaymentId", + $this->captureCommand->execute( + $payment, + $order->getGrandTotal(), + $order + ), + "" + ); + } else { + $payment->addTransactionCommentsToOrder( + "$rzpPaymentId", + $this->authorizeCommand->execute( + $payment, + $order->getGrandTotal(), + $order + ), + "" + ); + } + $this->logger->info('Payment authorized completed for id : ' . $order->getIncrementId()); + + } else { + $order->addStatusHistoryComment("Razorpay Payment Id " . $rzpPaymentId)->setStatus($order->getStatus())->setIsCustomerNotified(true); + } + + $transaction = $payment->addTransaction(\Magento\Sales\Model\Order\Payment\Transaction::TYPE_AUTH, null, true, ""); + + $transaction->setIsClosed(true); + + $transaction->save(); + + $this->logger->info('Payment authorized completed for id : ' . $order->getIncrementId()); + + $orderLink->setRzpPaymentId($rzpPaymentId); + + $orderLink->setRzpUpdateOrderCronStatus(OrderCronStatus::PAYMENT_AUTHORIZED_COMPLETED); + + if ($order->canInvoice() && $this->config->canAutoGenerateInvoice() + && $rzpOrderData->status === 'paid') { + $invoice = $this->invoiceService->prepareInvoice($order); + $invoice->setRequestedCaptureCase(\Magento\Sales\Model\Order\Invoice::CAPTURE_ONLINE); + $invoice->setTransactionId($rzpPaymentId); + $invoice->register(); + $invoice->save(); + + $this->logger->info('graphQL: Created Invoice for ' + . 'order_id ' . $rzpOrderId . ', ' + . 'rzp_payment_id ' . $rzpPaymentId); + + $transactionSave = $this->transaction + ->addObject($invoice) + ->addObject($invoice->getOrder()); + $transactionSave->save(); + + $this->invoiceSender->send($invoice); + + $order->addStatusHistoryComment( + __('Notified customer about invoice #%1.', $invoice->getId()) + )->setIsCustomerNotified(true); + + $this->logger->info('Invoice generated for id : ' . $order->getIncrementId()); + $orderLink->setRzpUpdateOrderCronStatus(OrderCronStatus::INVOICE_GENERATED); + } else if ($rzpOrderData->status === 'paid' and + ($order->canInvoice() === false or + $this->config->canAutoGenerateInvoice() === false)) { + $this->logger->info('Invoice generation not possible for id : ' . $order->getIncrementId()); + $orderLink->setRzpUpdateOrderCronStatus(OrderCronStatus::INVOICE_GENERATION_NOT_POSSIBLE); + } + + $comment = __('Razorpay order id %1.', $rzpOrderId); + + $order->addStatusHistoryComment( + $comment + )->setStatus($order->getStatus())->setIsCustomerNotified(true); + + $comment = __('Razorpay magic order.'); + + $order->addStatusHistoryComment( + $comment + )->setStatus($order->getStatus())->setIsCustomerNotified(true); + + try { + $this->checkoutSession->setRazorpayMailSentOnSuccess(true); + $this->orderSender->send($order); + $this->checkoutSession->unsRazorpayMailSentOnSuccess(); + } catch (\Magento\Framework\Exception\MailException $e) { + $this->logger->critical('graphQL: ' + . 'Razorpay Error:' . $e->getMessage()); + + throw new GraphQlInputException(__('Razorpay Error: %1.', $e->getMessage())); + } catch (\Exception $e) { + $this->logger->critical('graphQL: ' + . 'Error:' . $e->getMessage()); + + throw new GraphQlInputException(__('Error: %1.', $e->getMessage())); + } + + $this + ->checkoutSession + ->setLastSuccessQuoteId($order->getQuoteId()) + ->setLastQuoteId($order->getQuoteId()) + ->clearHelperData(); + if (empty($order) === false) { + $this + ->checkoutSession + ->setLastOrderId($order->getId()) + ->setLastRealOrderId($order->getIncrementId()) + ->setLastOrderStatus($order->getStatus()); + } + + $order->save(); + $orderLink->save(); + + // Get applied discounts data from the order object + $appliedDiscounts = $this->getAppliedDiscounts($order); + + $result = [ + 'status' => 'success', + 'order_id' => $order->getIncrementId(), + 'total_amount' => $order->getGrandTotal() * 100, + 'total_tax' => $order->getTaxAmount() * 100, + 'shipping_fee' => $order->getShippingAmount() * 100, + 'promotions' => $appliedDiscounts, + 'cod_fee' => 0 + ]; + + return $result; + } + + $result = [ + 'status' => 'failed' + ]; + + return $result; + } + public function getAppliedDiscounts($order) { try { diff --git a/Controller/OneClick/PlaceOrder.php b/Controller/OneClick/PlaceOrder.php index 67da5d42..4477e1e7 100644 --- a/Controller/OneClick/PlaceOrder.php +++ b/Controller/OneClick/PlaceOrder.php @@ -350,6 +350,15 @@ public function execute() 'items' => $items, 'message' => 'Razorpay Order created successfully' ]; + + $orderLink = $this->_objectManager->get('Razorpay\Magento\Model\OrderLink') + ->getCollection() + ->addFilter('order_id', $quote->getReservedOrderId()) + ->getFirstItem(); + + $orderLink->setRzpOrderId($razorpay_order->id) + ->setOrderId($quote->getReservedOrderId()) + ->save(); } else { $this->logger->critical('graphQL: Razorpay Order not generated. Something went wrong'); diff --git a/Controller/Payment/Webhook.php b/Controller/Payment/Webhook.php index 3d26affb..b692ab51 100644 --- a/Controller/Payment/Webhook.php +++ b/Controller/Payment/Webhook.php @@ -207,7 +207,27 @@ public function execute() return; } - if (isset($post['payload']['payment']['entity']['notes']['merchant_order_id']) === true) + if (isset($post['payload']['payment']['entity']['notes']['carrier_code']) === true) { + $rzpOrderId = $post['payload']['payment']['entity']['order_id']; + $cartId = $post['payload']['payment']['entity']['notes']['cart_id']; + $razorpayOrderData = $this->rzp->order->fetch($rzpOrderId); + $paymentId = $post['payload']['payment']['entity']['id']; + $amountPaid = $post['payload']['payment']['entity']['amount']; + + if ($post['event'] === 'order.paid') { + sleep(1); + } + + $merchantOrderId = $post['payload']['payment']['entity']['notes']['merchant_order_id']; + + $this->setOneCCWebhookData($post, $merchantOrderId, true, $paymentId, $amountPaid); + + $this->setWebhookNotifiedAt($merchantOrderId, true); + $this->setPaymentId($merchantOrderId, $paymentId); + } + + if (isset($post['payload']['payment']['entity']['notes']['merchant_order_id']) === true && + isset($post['payload']['payment']['entity']['notes']['carrier_code']) === false) { $orderId = $post['payload']['payment']['entity']['notes']['merchant_order_id']; $paymentId = $post['payload']['payment']['entity']['id']; @@ -224,13 +244,21 @@ public function execute() $this->setWebhookData($post, $orderWebhookData['entity_id'], true, $paymentId, $amountPaid); - $this->setWebhookNotifiedAt($orderWebhookData['entity_id']); + $this->setWebhookNotifiedAt($orderWebhookData['entity_id'], false); } } } $this->logger->info("Razorpay Webhook processing completed."); } + protected function setPaymentId($entity_id, $paymentId) + { + $orderLink = $this->_objectManager->get('Razorpay\Magento\Model\OrderLink') + ->load($entity_id, 'order_id'); + + $orderLink->setRzpPaymentId($paymentId); + $orderLink->save(); + } /** * Get Webhook post data as an array @@ -259,12 +287,20 @@ protected function getOrderData($orderId) : array return $collection->getData(); } - protected function setWebhookNotifiedAt($entity_id) + protected function setWebhookNotifiedAt($entity_id, $isMagicOrder = false) { - $order = $this->order->load($entity_id); + if($isMagicOrder === false) + { + $order = $this->order->load($entity_id); + $orderId = $order->getEntityId(); + } + else + { + $orderId = $entity_id; + } $orderLink = $this->_objectManager->get('Razorpay\Magento\Model\OrderLink') - ->load($order->getEntityId(), 'order_id'); + ->load($orderId, 'order_id'); $orderLink->setRzpWebhookNotifiedAt(time()); $orderLink->save(); @@ -332,4 +368,50 @@ protected function setWebhookData($post, $entityId, $webhookVerifiedStatus, $pay $this->logger->info('Webhook data saved for id:' . $order->getIncrementId() . 'event:' . $post['event']); } + + protected function setOneCCWebhookData($post, $entityId, $webhookVerifiedStatus, $paymentId, $amount) + { + $orderLink = $this->_objectManager->get('Razorpay\Magento\Model\OrderLink') + ->load($entityId, 'order_id'); + + $existingWebhookData = $orderLink->getRzpWebhookData(); + + if ($post['event'] === 'payment.authorized') { + $amount = $post['payload']['payment']['entity']['amount']; + } else if ($post['event'] === 'order.paid') { + $amount = $post['payload']['order']['entity']['amount_paid']; + } + $webhookData = array( + "webhook_verified_status" => $webhookVerifiedStatus, + "payment_id" => $paymentId, + "amount" => $amount + ); + + if (!empty($existingWebhookData)) { + $existingWebhookData = unserialize($existingWebhookData); // nosemgrep + + if (!array_key_exists($post['event'], $existingWebhookData)) { + $existingWebhookData[$post['event']] = $webhookData; + } + + $webhookDataText = serialize($existingWebhookData); + } else { + $eventArray = [$post['event'] => $webhookData]; + $webhookDataText = serialize($eventArray); + } + + $orderLink->setOrderId($entityId); + $orderLink->setRzpWebhookData($webhookDataText); + + if ($post['event'] === 'order.paid' and + $orderLink->getRzpUpdateOrderCronStatus() == OrderCronStatus::PAYMENT_AUTHORIZED_CRON_REPEAT) { + $this->logger->info('Order paid received after manual capture for id: ' . $entityId. 'for magic order'); + $orderLink->setRzpUpdateOrderCronStatus(OrderCronStatus::ORDER_PAID_AFTER_MANUAL_CAPTURE); + } + + $orderLink->save(); + + $this->logger->info('Webhook data saved for id:' . $entityId . 'event:' . $post['event']. 'for magic order'); + } + } diff --git a/Cron/UpdateOrdersToProcessingV2.php b/Cron/UpdateOrdersToProcessingV2.php index e5f00d8b..e0a9a3ab 100644 --- a/Cron/UpdateOrdersToProcessingV2.php +++ b/Cron/UpdateOrdersToProcessingV2.php @@ -1,10 +1,10 @@ config = $config; - $keyId = $this->config->getConfigData(Config::KEY_PUBLIC_KEY); - $keySecret = $this->config->getConfigData(Config::KEY_PRIVATE_KEY); - $this->api = new Api($keyId, $keySecret); - $this->orderRepository = $orderRepository; - $this->searchCriteriaBuilder = $searchCriteriaBuilder; - $this->sortOrderBuilder = $sortOrderBuilder; - $this->transaction = $transaction; - $this->checkoutSession = $checkoutSession; - $this->invoiceService = $invoiceService; - $this->invoiceSender = $invoiceSender; - $this->orderSender = $orderSender; - $this->logger = $logger; - $this->orderStatus = static::STATUS_PROCESSING; - $this->debug = $debug; + $this->config = $config; + $keyId = $this->config->getConfigData(Config::KEY_PUBLIC_KEY); + $keySecret = $this->config->getConfigData(Config::KEY_PRIVATE_KEY); + $this->api = new Api($keyId, $keySecret); + $this->orderRepository = $orderRepository; + $this->searchCriteriaBuilder = $searchCriteriaBuilder; + $this->sortOrderBuilder = $sortOrderBuilder; + $this->transaction = $transaction; + $this->checkoutSession = $checkoutSession; + $this->invoiceService = $invoiceService; + $this->invoiceSender = $invoiceSender; + $this->orderSender = $orderSender; + $this->logger = $logger; + $this->orderStatus = static::STATUS_PROCESSING; + $this->debug = $debug; + $this->quoteUpdate = $quoteUpdate; + $this->cartRepositoryInterface = $cartRepositoryInterface; + $this->cartManagement = $cartManagement; + $this->oneCCMagentoOrder = $oneCCMagentoOrder; $this->enableCustomPaidOrderStatus = $this->config->isCustomPaidOrderStatusEnabled(); if ($this->enableCustomPaidOrderStatus === true - && empty($this->config->getCustomPaidOrderStatus()) === false) - { + && empty($this->config->getCustomPaidOrderStatus()) === false) { $this->orderStatus = $this->config->getCustomPaidOrderStatus(); } @@ -163,96 +178,119 @@ public function execute() { $this->logger->info("Cronjob: Update Orders To Processing Cron V2 started."); - $dateTimeCheck = time() - static::PROCESS_ORDER_WAIT_TIME; - + $dateTimeCheck = time() - static::PROCESS_ORDER_WAIT_TIME; + $objectManagement = $this->getObjectManager(); - + $orderLinkCollection = $objectManagement->get('Razorpay\Magento\Model\OrderLink') - ->getCollection() - ->addFieldToFilter('rzp_update_order_cron_status',["lt" => 3]) - ->addFieldToFilter('rzp_webhook_notified_at',["notnull" => true]) - ->addFieldToFilter('rzp_webhook_notified_at',["lt" => $dateTimeCheck]) - ->setOrder('entity_id') - ->setPageSize(5); - + ->getCollection() + ->addFieldToFilter('rzp_update_order_cron_status', ["lt" => 3]) + ->addFieldToFilter('rzp_webhook_notified_at', ["notnull" => true]) + ->addFieldToFilter('rzp_webhook_notified_at', ["lt" => $dateTimeCheck]) + ->setOrder('entity_id') + ->setPageSize(5); + $orderLink = $orderLinkCollection->getData(); - - if (count($orderLink) > 0) - { - foreach ($orderLink as $orderData) - { + + if (count($orderLink) > 0) { + foreach ($orderLink as $orderData) { $this->debug->log("Cronjob: Magento Order Id = " . $orderData['order_id'] . " picked for updation"); - $order = $this->orderRepository->get($orderData['order_id']); - $singleOrderLinkCollection = $objectManagement->get('Razorpay\Magento\Model\OrderLink') - ->getCollection() - ->addFilter('order_id', $order->getEntityId()) - ->getFirstItem(); - - if ((empty($order) === false) and ( - $order->getPayment()->getMethod() === 'razorpay') and - ($order->getState() === static::STATUS_PROCESSING or - $order->getState() === static::STATE_NEW)) - { - $rzpWebhookData = $orderData['rzp_webhook_data']; - if (empty($rzpWebhookData) === false) // check if webhook cron has run and populated the rzp_webhook_data column - { - $this->debug->log("Cronjob: Webhook data present for Magento Order Id = " . $orderData['order_id']); - - $rzpWebhookDataObj = unserialize($rzpWebhookData); // nosemgrep - - if (isset($rzpWebhookDataObj[static::ORDER_PAID]) === true) - { - $this->updateOrderStatus($order, static::ORDER_PAID, $rzpWebhookDataObj[static::ORDER_PAID], $singleOrderLinkCollection); - } + if (empty($orderData['rzp_order_id']) === true) { + return; + } + $razorpayOrderData = $this->api->order->fetch($orderData['rzp_order_id']); + $isMagicOrder = $this->checkMagicOrder($razorpayOrderData); + + if ($isMagicOrder) { + $rzpPaymentData = $this->api->payment->fetch($orderData['rzp_payment_id']); + $cartId = isset($razorpayOrderData->notes) ? $razorpayOrderData->notes->cart_id : null; + $merchantOrderId = isset($razorpayOrderData->notes) ? $razorpayOrderData->notes->merchant_order_id : null; - if (isset($rzpWebhookDataObj[static::PAYMENT_AUTHORIZED]) === true and - $singleOrderLinkCollection->getRzpUpdateOrderCronStatus() < OrderCronStatus::INVOICE_GENERATED) + $this->debug->log("Cronjob: Razorpay Order data = " . json_encode($cartId)); + + $quote = $this->cartRepositoryInterface->get($cartId); + $this->quoteUpdate->updateQuote($quote, $razorpayOrderData); + + $result = $this->oneCCMagentoOrder->placeMagentoOrder($cartId, $rzpPaymentData, $razorpayOrderData); + if ($result['status'] == 'success') { + $this->debug->log("Cronjob: Successfully placed Magento Order Id = " . $merchantOrderId); + } else { + $this->debug->log("Cronjob: Failed to place Magento Order Id = " . $merchantOrderId); + } + } else { + $order = $this->orderRepository->get($orderData['order_id']); + $singleOrderLinkCollection = $objectManagement->get('Razorpay\Magento\Model\OrderLink') + ->getCollection() + ->addFilter('order_id', $order->getEntityId()) + ->getFirstItem(); + + if ((empty($order) === false) and ( + $order->getPayment()->getMethod() === 'razorpay') and + ($order->getState() === static::STATUS_PROCESSING or + $order->getState() === static::STATE_NEW)) { + $rzpWebhookData = $orderData['rzp_webhook_data']; + if (empty($rzpWebhookData) === false) // check if webhook cron has run and populated the rzp_webhook_data column { - if ($order->getState() === static::STATUS_PROCESSING and - $singleOrderLinkCollection->getRzpUpdateOrderCronStatus() == OrderCronStatus::PAYMENT_AUTHORIZED_COMPLETED) - { - $this->logger->info('Payment Authorized cron repeated for id: ' . $order->getIncrementId()); - $singleOrderLinkCollection->setRzpUpdateOrderCronStatus(OrderCronStatus::PAYMENT_AUTHORIZED_CRON_REPEAT); - $singleOrderLinkCollection->save(); + $this->debug->log("Cronjob: Webhook data present for Magento Order Id = " . $orderData['order_id']); + + $rzpWebhookDataObj = unserialize($rzpWebhookData); // nosemgrep + + if (isset($rzpWebhookDataObj[static::ORDER_PAID]) === true) { + $this->updateOrderStatus($order, static::ORDER_PAID, $rzpWebhookDataObj[static::ORDER_PAID], $singleOrderLinkCollection); } - else{ - $this->updateOrderStatus($order, static::PAYMENT_AUTHORIZED, $rzpWebhookDataObj[static::PAYMENT_AUTHORIZED], $singleOrderLinkCollection); + + if (isset($rzpWebhookDataObj[static::PAYMENT_AUTHORIZED]) === true and + $singleOrderLinkCollection->getRzpUpdateOrderCronStatus() < OrderCronStatus::INVOICE_GENERATED) { + if ($order->getState() === static::STATUS_PROCESSING and + $singleOrderLinkCollection->getRzpUpdateOrderCronStatus() == OrderCronStatus::PAYMENT_AUTHORIZED_COMPLETED) { + $this->logger->info('Payment Authorized cron repeated for id: ' . $order->getIncrementId()); + $singleOrderLinkCollection->setRzpUpdateOrderCronStatus(OrderCronStatus::PAYMENT_AUTHORIZED_CRON_REPEAT); + $singleOrderLinkCollection->save(); + } else { + $this->updateOrderStatus($order, static::PAYMENT_AUTHORIZED, $rzpWebhookDataObj[static::PAYMENT_AUTHORIZED], $singleOrderLinkCollection); + } } + } else { + $this->logger->info('Razorpay Webhook code not triggered yet. \'rzp_webhook_data\' is empty for id:' . $order->getEntityId()); } } - else - { - $this->logger->info('Razorpay Webhook code not triggered yet. \'rzp_webhook_data\' is empty for id:' . $order->getEntityId()); - } } } } - + } + + protected function checkMagicOrder($razorpayOrderData) + { + $carrierCode = $razorpayOrderData->notes->carrier_code ?? null; + + if ($carrierCode) { + return true; + } + return false; } private function updateOrderStatus($order, $event, $rzpWebhookData, $orderLinkCollection) { - $this->logger->info("Cronjob: Updating to Processing for Order ID: " - . $order->getIncrementId() - . " and Event :" - . $event - . " started." - ); - - $payment = $order->getPayment(); - $paymentId = $rzpWebhookData['payment_id']; + $this->logger->info("Cronjob: Updating to Processing for Order ID: " + . $order->getIncrementId() + . " and Event :" + . $event + . " started." + ); + + $payment = $order->getPayment(); + $paymentId = $rzpWebhookData['payment_id']; $rzpOrderAmount = $rzpWebhookData['amount']; $payment->setLastTransId($paymentId) - ->setTransactionId($paymentId) - ->setIsTransactionClosed(true) - ->setShouldCloseParentTransaction(true); + ->setTransactionId($paymentId) + ->setIsTransactionClosed(true) + ->setShouldCloseParentTransaction(true); $payment->setParentTransactionId($payment->getTransactionId()); - if ($event === static::PAYMENT_AUTHORIZED) - { + if ($event === static::PAYMENT_AUTHORIZED) { $payment->addTransactionCommentsToOrder( "$paymentId", $this->authorizeCommand->execute( @@ -262,9 +300,7 @@ private function updateOrderStatus($order, $event, $rzpWebhookData, $orderLinkCo ), "" ); - } - else if ($event === static::ORDER_PAID) - { + } else if ($event === static::ORDER_PAID) { $payment->addTransactionCommentsToOrder( "$paymentId", $this->captureCommand->execute( @@ -286,8 +322,7 @@ private function updateOrderStatus($order, $event, $rzpWebhookData, $orderLinkCo $order->setState(static::STATUS_PROCESSING)->setStatus($this->orderStatus); - if ($event === static::PAYMENT_AUTHORIZED) - { + if ($event === static::PAYMENT_AUTHORIZED) { $order->addStatusHistoryComment( __( 'Actual Amount %1 of %2, with Razorpay Offer/Fee applied.', @@ -295,9 +330,7 @@ private function updateOrderStatus($order, $event, $rzpWebhookData, $orderLinkCo $order->getBaseCurrency()->formatTxt($amountPaid) ) ); - } - else if ($event === static::ORDER_PAID) - { + } else if ($event === static::ORDER_PAID) { $order->addStatusHistoryComment( __( '%1 amount of %2 online, with Razorpay Offer/Fee applied.', @@ -308,12 +341,10 @@ private function updateOrderStatus($order, $event, $rzpWebhookData, $orderLinkCo } $orderLinkCollection->setRzpUpdateOrderCronStatus(OrderCronStatus::PAYMENT_AUTHORIZED_COMPLETED); - $this->logger->info('Payment authorized completed for id : '. $order->getIncrementId()); + $this->logger->info('Payment authorized completed for id : ' . $order->getIncrementId()); - if ($event === static::ORDER_PAID) - { - if ($order->canInvoice() && $this->config->canAutoGenerateInvoice()) - { + if ($event === static::ORDER_PAID) { + if ($order->canInvoice() && $this->config->canAutoGenerateInvoice()) { $invoice = $this->invoiceService->prepareInvoice($order); $invoice->setRequestedCaptureCase(\Magento\Sales\Model\Order\Invoice::CAPTURE_ONLINE); $invoice->setTransactionId($paymentId); @@ -321,8 +352,8 @@ private function updateOrderStatus($order, $event, $rzpWebhookData, $orderLinkCo $invoice->save(); $transactionSave = $this->transaction - ->addObject($invoice) - ->addObject($invoice->getOrder()); + ->addObject($invoice) + ->addObject($invoice->getOrder()); $transactionSave->save(); $this->invoiceSender->send($invoice); @@ -331,16 +362,14 @@ private function updateOrderStatus($order, $event, $rzpWebhookData, $orderLinkCo $order->setState(static::STATUS_PROCESSING)->setStatus($this->orderStatus); $order->addStatusHistoryComment( - __('Notified customer about invoice #%1.', $invoice->getId()) - )->setIsCustomerNotified(true); - + __('Notified customer about invoice #%1.', $invoice->getId()) + )->setIsCustomerNotified(true); + $orderLinkCollection->setRzpUpdateOrderCronStatus(OrderCronStatus::INVOICE_GENERATED); - $this->logger->info('Invoice generated for id : '. $order->getIncrementId()); - } - else - { + $this->logger->info('Invoice generated for id : ' . $order->getIncrementId()); + } else { $orderLinkCollection->setRzpUpdateOrderCronStatus(OrderCronStatus::INVOICE_GENERATION_NOT_POSSIBLE); - $this->logger->info('Invoice generation not possible for id : '. $order->getIncrementId()); + $this->logger->info('Invoice generation not possible for id : ' . $order->getIncrementId()); } } @@ -350,27 +379,22 @@ private function updateOrderStatus($order, $event, $rzpWebhookData, $orderLinkCo $orderLinkCollection->save(); //send Order email, after successfull payment - try - { + try { $this->checkoutSession->setRazorpayMailSentOnSuccess(true); $this->orderSender->send($order); $this->checkoutSession->unsRazorpayMailSentOnSuccess(); - } - catch (\Magento\Framework\Exception\MailException $e) - { + } catch (\Magento\Framework\Exception\MailException $e) { $this->logger->critical($e); - } - catch (\Exception $e) - { + } catch (\Exception $e) { $this->logger->critical($e); } - $this->logger->info("Cronjob: Updating to Processing for Order ID: " - . $order->getIncrementId() - . " and Event :" - . $event - . " ended." - ); + $this->logger->info("Cronjob: Updating to Processing for Order ID: " + . $order->getIncrementId() + . " and Event :" + . $event + . " ended." + ); } // @codeCoverageIgnoreStart From eb1b93ecb0edf6bd24d3d164dd5833b9589ad380 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Thu, 11 Jul 2024 19:44:15 +0530 Subject: [PATCH 37/67] Removed return statement in webhook file --- Controller/Payment/Webhook.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Controller/Payment/Webhook.php b/Controller/Payment/Webhook.php index b692ab51..593ee163 100644 --- a/Controller/Payment/Webhook.php +++ b/Controller/Payment/Webhook.php @@ -202,11 +202,6 @@ public function execute() exit; } - if (isset($post['payload']['payment']['entity']['notes']['carrier_code']) === true) { - $this->debug->log("Razorpay Webhook processing stopped as order is magic checkout order"); - return; - } - if (isset($post['payload']['payment']['entity']['notes']['carrier_code']) === true) { $rzpOrderId = $post['payload']['payment']['entity']['order_id']; $cartId = $post['payload']['payment']['entity']['notes']['cart_id']; From 20e35554e2d22cefb930befa07d4081cdf3a9314 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Wed, 24 Jul 2024 14:05:27 +0530 Subject: [PATCH 38/67] Var defined and added GSTIN under comments --- Controller/OneClick/CompleteOrder.php | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index e2368f41..99818f58 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -273,6 +273,8 @@ public function placeMagentoOrder($cartId, $rzpPaymentData, $rzpOrderData) if (!$order->getId()) { $orderId = $this->cartManagement->placeOrder($cartId); $order = $this->order->load($orderId); + } else { + $orderId = $order->getId(); } $rzpOrderId = $rzpOrderData->id; @@ -309,9 +311,11 @@ public function placeMagentoOrder($cartId, $rzpPaymentData, $rzpOrderData) $rzpPromotionAmount = 0; - foreach ($rzpOrderData->promotions as $promotion) { - if (empty($promotion['code']) === false) { - $rzpPromotionAmount = $promotion['value']; + if (empty($rzpOrderData->promotions) === false) { + foreach ($rzpOrderData->promotions as $promotion) { + if (empty($promotion['code']) === false) { + $rzpPromotionAmount = $promotion['value']; + } } } @@ -332,11 +336,6 @@ public function placeMagentoOrder($cartId, $rzpPaymentData, $rzpOrderData) } } - if ($order->getData('customer_gstin')) { - $gstin = $rzpOrderData->notes->gstin ?? ''; - $order->setData('customer_gstin', $gstin); - } - $payment = $order->getPayment(); $payment->setLastTransId($rzpPaymentId) @@ -430,6 +429,15 @@ public function placeMagentoOrder($cartId, $rzpPaymentData, $rzpOrderData) $comment )->setStatus($order->getStatus())->setIsCustomerNotified(true); + $gstin = $rzpOrderData->notes->gstin ?? ''; + if (empty($gstin) === false) { + $gstinComment = __('Customer GSTIN number %1.', $gstin); + + $order->addStatusHistoryComment( + $gstinComment + )->setStatus($order->getStatus())->setIsCustomerNotified(true); + } + try { $this->checkoutSession->setRazorpayMailSentOnSuccess(true); $this->orderSender->send($order); From 9aad3417b3357fb6fea39a5ead9abfa5309d232b Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Fri, 2 Aug 2024 11:38:59 +0530 Subject: [PATCH 39/67] Bug fix for pondicherry state name --- Controller/OneClick/StateMap.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Controller/OneClick/StateMap.php b/Controller/OneClick/StateMap.php index d764fa9b..63772145 100644 --- a/Controller/OneClick/StateMap.php +++ b/Controller/OneClick/StateMap.php @@ -59,7 +59,7 @@ function getStateNameIN($stateName) 'MIZORAM' => 'Mizoram', 'NAGALAND' => 'Nagaland', 'ODISHA' => 'Odisha', - 'PONDICHERRY' => 'Pondicherry', + 'PONDICHERRY' => 'Puducherry', 'PUNJAB' => 'Punjab', 'RAJASTHAN' => 'Rajasthan', 'SIKKIM' => 'Sikkim', From 734e7193e1ee7587fa92967916d187c2152f1f1c Mon Sep 17 00:00:00 2001 From: Ankit Kumar Tiwari Date: Tue, 13 Aug 2024 10:00:59 +0530 Subject: [PATCH 40/67] fix synchronous order placement --- Controller/OneClick/CompleteOrder.php | 234 ++++++++++++++++++++++++++ Cron/UpdateOrdersToProcessingV2.php | 2 +- 2 files changed, 235 insertions(+), 1 deletion(-) diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index 99818f58..799aa393 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -493,6 +493,240 @@ public function placeMagentoOrder($cartId, $rzpPaymentData, $rzpOrderData) return $result; } + public function placeMagentoOrderthroughCron($cartId, $rzpPaymentData, $rzpOrderData) + { + $merchantOrderId = isset($rzpOrderData->notes) ? $rzpOrderData->notes->merchant_order_id : null; + + $orderLink = $this->_objectManager->get('Razorpay\Magento\Model\OrderLink') + ->getCollection() + ->addFilter('order_id', $merchantOrderId) + ->getFirstItem(); + + $order = $this->order->loadByIncrementId($merchantOrderId); + + if (!$order->getId()) { + $orderId = $this->cartManagement->placeOrder($cartId); + $order = $this->order->load($orderId); + } else { + $orderId = $order->getId(); + } + + $rzpOrderId = $rzpOrderData->id; + $rzpPaymentId = $rzpPaymentData->id; + + $order->setEmailSent(0); + if ($order) { + // Return to failure page if payment is failed. + if ($rzpPaymentData->status === 'failed') { + $result = [ + 'status' => 'failed' + ]; + + return $result; + } + + if ($order->getStatus() === 'pending') { + if ($rzpPaymentData->status === 'pending' && $rzpPaymentData->method === 'cod') { + $order->setState(static::STATE_PENDING_PAYMENT) + ->setStatus(static::STATE_PENDING_PAYMENT); + } else { + $order->setState(static::STATE_PROCESSING) + ->setStatus(static::STATE_PROCESSING); + } + + $this->logger->info('graphQL: Order Status Updated to ' . $this->orderStatus); + } + + if (!empty($rzpOrderData->offers)) { + $discountAmount = $order->getDiscountAmount(); + + $codFee = $rzpOrderData->cod_fee; + $totalPaid = $rzpPaymentData->amount; + + $rzpPromotionAmount = 0; + + if (empty($rzpOrderData->promotions) === false) { + foreach ($rzpOrderData->promotions as $promotion) { + if (empty($promotion['code']) === false) { + $rzpPromotionAmount = $promotion['value']; + } + } + } + + $offerDiff = $rzpOrderData->line_items_total + $rzpOrderData->shipping_fee + $codFee - $totalPaid - $rzpPromotionAmount; + + if ($offerDiff > 0) { + $offerDiscount = ($offerDiff / 100); + // abs is used here as discount amount is returned as minus from order object. + $newDiscountAmount = abs($discountAmount) + $offerDiscount; + + $this->logger->info('graphQL: offerDiscount ' . $offerDiscount); + $this->logger->info('graphQL: newDiscountAmount ' . $newDiscountAmount); + $this->logger->info('graphQL: offerDiff ' . $offerDiff); + $this->logger->info('graphQL: codFee ' . $codFee); + $this->logger->info('graphQL: discountAmount ' . $discountAmount); + + $this->updateDiscountAmount($orderId, $newDiscountAmount, $offerDiscount, $totalPaid); + } + } + + $payment = $order->getPayment(); + + $payment->setLastTransId($rzpPaymentId) + ->setTransactionId($rzpPaymentId) + ->setIsTransactionClosed(true) + ->setShouldCloseParentTransaction(true); + + $payment->setParentTransactionId($payment->getTransactionId()); + + if ($rzpPaymentData->method != 'cod') { + if ($this->config->getPaymentAction() === \Razorpay\Magento\Model\PaymentMethod::ACTION_AUTHORIZE_CAPTURE) { + $payment->addTransactionCommentsToOrder( + "$rzpPaymentId", + $this->captureCommand->execute( + $payment, + $order->getGrandTotal(), + $order + ), + "" + ); + } else { + $payment->addTransactionCommentsToOrder( + "$rzpPaymentId", + $this->authorizeCommand->execute( + $payment, + $order->getGrandTotal(), + $order + ), + "" + ); + } + $this->logger->info('Payment authorized completed for id : ' . $order->getIncrementId()); + + } else { + $order->addStatusHistoryComment("Razorpay Payment Id " . $rzpPaymentId)->setStatus($order->getStatus())->setIsCustomerNotified(true); + } + + $transaction = $payment->addTransaction(\Magento\Sales\Model\Order\Payment\Transaction::TYPE_AUTH, null, true, ""); + + $transaction->setIsClosed(true); + + $transaction->save(); + + $this->logger->info('Payment authorized completed for id : ' . $order->getIncrementId()); + + $orderLink->setRzpPaymentId($rzpPaymentId); + + $orderLink->setRzpUpdateOrderCronStatus(OrderCronStatus::PAYMENT_AUTHORIZED_COMPLETED); + + if ($order->canInvoice() && $this->config->canAutoGenerateInvoice() + && $rzpOrderData->status === 'paid') { + $invoice = $this->invoiceService->prepareInvoice($order); + $invoice->setRequestedCaptureCase(\Magento\Sales\Model\Order\Invoice::CAPTURE_ONLINE); + $invoice->setTransactionId($rzpPaymentId); + $invoice->register(); + $invoice->save(); + + $this->logger->info('graphQL: Created Invoice for ' + . 'order_id ' . $rzpOrderId . ', ' + . 'rzp_payment_id ' . $rzpPaymentId); + + $transactionSave = $this->transaction + ->addObject($invoice) + ->addObject($invoice->getOrder()); + $transactionSave->save(); + + $this->invoiceSender->send($invoice); + + $order->addStatusHistoryComment( + __('Notified customer about invoice #%1.', $invoice->getId()) + )->setIsCustomerNotified(true); + + $this->logger->info('Invoice generated for id : ' . $order->getIncrementId()); + $orderLink->setRzpUpdateOrderCronStatus(OrderCronStatus::INVOICE_GENERATED); + } else if ($rzpOrderData->status === 'paid' and + ($order->canInvoice() === false or + $this->config->canAutoGenerateInvoice() === false)) { + $this->logger->info('Invoice generation not possible for id : ' . $order->getIncrementId()); + $orderLink->setRzpUpdateOrderCronStatus(OrderCronStatus::INVOICE_GENERATION_NOT_POSSIBLE); + } + + $comment = __('Razorpay order id %1.', $rzpOrderId); + + $order->addStatusHistoryComment( + $comment + )->setStatus($order->getStatus())->setIsCustomerNotified(true); + + $comment = __('Razorpay magic order.'); + + $order->addStatusHistoryComment( + $comment + )->setStatus($order->getStatus())->setIsCustomerNotified(true); + + $gstin = $rzpOrderData->notes->gstin ?? ''; + if (empty($gstin) === false) { + $gstinComment = __('Customer GSTIN number %1.', $gstin); + + $order->addStatusHistoryComment( + $gstinComment + )->setStatus($order->getStatus())->setIsCustomerNotified(true); + } + + try { + $this->checkoutSession->setRazorpayMailSentOnSuccess(true); + $this->orderSender->send($order); + $this->checkoutSession->unsRazorpayMailSentOnSuccess(); + } catch (\Magento\Framework\Exception\MailException $e) { + $this->logger->critical('graphQL: ' + . 'Razorpay Error:' . $e->getMessage()); + + throw new GraphQlInputException(__('Razorpay Error: %1.', $e->getMessage())); + } catch (\Exception $e) { + $this->logger->critical('graphQL: ' + . 'Error:' . $e->getMessage()); + + throw new GraphQlInputException(__('Error: %1.', $e->getMessage())); + } + + $this + ->checkoutSession + ->setLastSuccessQuoteId($order->getQuoteId()) + ->setLastQuoteId($order->getQuoteId()) + ->clearHelperData(); + if (empty($order) === false) { + $this + ->checkoutSession + ->setLastOrderId($order->getId()) + ->setLastRealOrderId($order->getIncrementId()) + ->setLastOrderStatus($order->getStatus()); + } + + $order->save(); + $orderLink->save(); + + // Get applied discounts data from the order object + $appliedDiscounts = $this->getAppliedDiscounts($order); + + $result = [ + 'status' => 'success', + 'order_id' => $order->getIncrementId(), + 'total_amount' => $order->getGrandTotal() * 100, + 'total_tax' => $order->getTaxAmount() * 100, + 'shipping_fee' => $order->getShippingAmount() * 100, + 'promotions' => $appliedDiscounts, + 'cod_fee' => 0 + ]; + + return $result; + } + + $result = [ + 'status' => 'failed' + ]; + + return $result; + } + public function getAppliedDiscounts($order) { try { diff --git a/Cron/UpdateOrdersToProcessingV2.php b/Cron/UpdateOrdersToProcessingV2.php index e0a9a3ab..ca96d314 100644 --- a/Cron/UpdateOrdersToProcessingV2.php +++ b/Cron/UpdateOrdersToProcessingV2.php @@ -212,7 +212,7 @@ public function execute() $quote = $this->cartRepositoryInterface->get($cartId); $this->quoteUpdate->updateQuote($quote, $razorpayOrderData); - $result = $this->oneCCMagentoOrder->placeMagentoOrder($cartId, $rzpPaymentData, $razorpayOrderData); + $result = $this->oneCCMagentoOrder->placeMagentoOrderthroughCron($cartId, $rzpPaymentData, $razorpayOrderData); if ($result['status'] == 'success') { $this->debug->log("Cronjob: Successfully placed Magento Order Id = " . $merchantOrderId); } else { From 184f2cfd9c64768bc166bbc2dfade0cc61b889f9 Mon Sep 17 00:00:00 2001 From: Ankit Kumar Tiwari Date: Fri, 16 Aug 2024 13:41:06 +0530 Subject: [PATCH 41/67] moving the function to different file --- Controller/OneClick/CompleteOrder.php | 234 ------------------------ Cron/UpdateOrdersToProcessingV2.php | 247 +++++++++++++++++++++++++- 2 files changed, 245 insertions(+), 236 deletions(-) diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index 799aa393..99818f58 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -493,240 +493,6 @@ public function placeMagentoOrder($cartId, $rzpPaymentData, $rzpOrderData) return $result; } - public function placeMagentoOrderthroughCron($cartId, $rzpPaymentData, $rzpOrderData) - { - $merchantOrderId = isset($rzpOrderData->notes) ? $rzpOrderData->notes->merchant_order_id : null; - - $orderLink = $this->_objectManager->get('Razorpay\Magento\Model\OrderLink') - ->getCollection() - ->addFilter('order_id', $merchantOrderId) - ->getFirstItem(); - - $order = $this->order->loadByIncrementId($merchantOrderId); - - if (!$order->getId()) { - $orderId = $this->cartManagement->placeOrder($cartId); - $order = $this->order->load($orderId); - } else { - $orderId = $order->getId(); - } - - $rzpOrderId = $rzpOrderData->id; - $rzpPaymentId = $rzpPaymentData->id; - - $order->setEmailSent(0); - if ($order) { - // Return to failure page if payment is failed. - if ($rzpPaymentData->status === 'failed') { - $result = [ - 'status' => 'failed' - ]; - - return $result; - } - - if ($order->getStatus() === 'pending') { - if ($rzpPaymentData->status === 'pending' && $rzpPaymentData->method === 'cod') { - $order->setState(static::STATE_PENDING_PAYMENT) - ->setStatus(static::STATE_PENDING_PAYMENT); - } else { - $order->setState(static::STATE_PROCESSING) - ->setStatus(static::STATE_PROCESSING); - } - - $this->logger->info('graphQL: Order Status Updated to ' . $this->orderStatus); - } - - if (!empty($rzpOrderData->offers)) { - $discountAmount = $order->getDiscountAmount(); - - $codFee = $rzpOrderData->cod_fee; - $totalPaid = $rzpPaymentData->amount; - - $rzpPromotionAmount = 0; - - if (empty($rzpOrderData->promotions) === false) { - foreach ($rzpOrderData->promotions as $promotion) { - if (empty($promotion['code']) === false) { - $rzpPromotionAmount = $promotion['value']; - } - } - } - - $offerDiff = $rzpOrderData->line_items_total + $rzpOrderData->shipping_fee + $codFee - $totalPaid - $rzpPromotionAmount; - - if ($offerDiff > 0) { - $offerDiscount = ($offerDiff / 100); - // abs is used here as discount amount is returned as minus from order object. - $newDiscountAmount = abs($discountAmount) + $offerDiscount; - - $this->logger->info('graphQL: offerDiscount ' . $offerDiscount); - $this->logger->info('graphQL: newDiscountAmount ' . $newDiscountAmount); - $this->logger->info('graphQL: offerDiff ' . $offerDiff); - $this->logger->info('graphQL: codFee ' . $codFee); - $this->logger->info('graphQL: discountAmount ' . $discountAmount); - - $this->updateDiscountAmount($orderId, $newDiscountAmount, $offerDiscount, $totalPaid); - } - } - - $payment = $order->getPayment(); - - $payment->setLastTransId($rzpPaymentId) - ->setTransactionId($rzpPaymentId) - ->setIsTransactionClosed(true) - ->setShouldCloseParentTransaction(true); - - $payment->setParentTransactionId($payment->getTransactionId()); - - if ($rzpPaymentData->method != 'cod') { - if ($this->config->getPaymentAction() === \Razorpay\Magento\Model\PaymentMethod::ACTION_AUTHORIZE_CAPTURE) { - $payment->addTransactionCommentsToOrder( - "$rzpPaymentId", - $this->captureCommand->execute( - $payment, - $order->getGrandTotal(), - $order - ), - "" - ); - } else { - $payment->addTransactionCommentsToOrder( - "$rzpPaymentId", - $this->authorizeCommand->execute( - $payment, - $order->getGrandTotal(), - $order - ), - "" - ); - } - $this->logger->info('Payment authorized completed for id : ' . $order->getIncrementId()); - - } else { - $order->addStatusHistoryComment("Razorpay Payment Id " . $rzpPaymentId)->setStatus($order->getStatus())->setIsCustomerNotified(true); - } - - $transaction = $payment->addTransaction(\Magento\Sales\Model\Order\Payment\Transaction::TYPE_AUTH, null, true, ""); - - $transaction->setIsClosed(true); - - $transaction->save(); - - $this->logger->info('Payment authorized completed for id : ' . $order->getIncrementId()); - - $orderLink->setRzpPaymentId($rzpPaymentId); - - $orderLink->setRzpUpdateOrderCronStatus(OrderCronStatus::PAYMENT_AUTHORIZED_COMPLETED); - - if ($order->canInvoice() && $this->config->canAutoGenerateInvoice() - && $rzpOrderData->status === 'paid') { - $invoice = $this->invoiceService->prepareInvoice($order); - $invoice->setRequestedCaptureCase(\Magento\Sales\Model\Order\Invoice::CAPTURE_ONLINE); - $invoice->setTransactionId($rzpPaymentId); - $invoice->register(); - $invoice->save(); - - $this->logger->info('graphQL: Created Invoice for ' - . 'order_id ' . $rzpOrderId . ', ' - . 'rzp_payment_id ' . $rzpPaymentId); - - $transactionSave = $this->transaction - ->addObject($invoice) - ->addObject($invoice->getOrder()); - $transactionSave->save(); - - $this->invoiceSender->send($invoice); - - $order->addStatusHistoryComment( - __('Notified customer about invoice #%1.', $invoice->getId()) - )->setIsCustomerNotified(true); - - $this->logger->info('Invoice generated for id : ' . $order->getIncrementId()); - $orderLink->setRzpUpdateOrderCronStatus(OrderCronStatus::INVOICE_GENERATED); - } else if ($rzpOrderData->status === 'paid' and - ($order->canInvoice() === false or - $this->config->canAutoGenerateInvoice() === false)) { - $this->logger->info('Invoice generation not possible for id : ' . $order->getIncrementId()); - $orderLink->setRzpUpdateOrderCronStatus(OrderCronStatus::INVOICE_GENERATION_NOT_POSSIBLE); - } - - $comment = __('Razorpay order id %1.', $rzpOrderId); - - $order->addStatusHistoryComment( - $comment - )->setStatus($order->getStatus())->setIsCustomerNotified(true); - - $comment = __('Razorpay magic order.'); - - $order->addStatusHistoryComment( - $comment - )->setStatus($order->getStatus())->setIsCustomerNotified(true); - - $gstin = $rzpOrderData->notes->gstin ?? ''; - if (empty($gstin) === false) { - $gstinComment = __('Customer GSTIN number %1.', $gstin); - - $order->addStatusHistoryComment( - $gstinComment - )->setStatus($order->getStatus())->setIsCustomerNotified(true); - } - - try { - $this->checkoutSession->setRazorpayMailSentOnSuccess(true); - $this->orderSender->send($order); - $this->checkoutSession->unsRazorpayMailSentOnSuccess(); - } catch (\Magento\Framework\Exception\MailException $e) { - $this->logger->critical('graphQL: ' - . 'Razorpay Error:' . $e->getMessage()); - - throw new GraphQlInputException(__('Razorpay Error: %1.', $e->getMessage())); - } catch (\Exception $e) { - $this->logger->critical('graphQL: ' - . 'Error:' . $e->getMessage()); - - throw new GraphQlInputException(__('Error: %1.', $e->getMessage())); - } - - $this - ->checkoutSession - ->setLastSuccessQuoteId($order->getQuoteId()) - ->setLastQuoteId($order->getQuoteId()) - ->clearHelperData(); - if (empty($order) === false) { - $this - ->checkoutSession - ->setLastOrderId($order->getId()) - ->setLastRealOrderId($order->getIncrementId()) - ->setLastOrderStatus($order->getStatus()); - } - - $order->save(); - $orderLink->save(); - - // Get applied discounts data from the order object - $appliedDiscounts = $this->getAppliedDiscounts($order); - - $result = [ - 'status' => 'success', - 'order_id' => $order->getIncrementId(), - 'total_amount' => $order->getGrandTotal() * 100, - 'total_tax' => $order->getTaxAmount() * 100, - 'shipping_fee' => $order->getShippingAmount() * 100, - 'promotions' => $appliedDiscounts, - 'cod_fee' => 0 - ]; - - return $result; - } - - $result = [ - 'status' => 'failed' - ]; - - return $result; - } - public function getAppliedDiscounts($order) { try { diff --git a/Cron/UpdateOrdersToProcessingV2.php b/Cron/UpdateOrdersToProcessingV2.php index ca96d314..06b49dcd 100644 --- a/Cron/UpdateOrdersToProcessingV2.php +++ b/Cron/UpdateOrdersToProcessingV2.php @@ -65,6 +65,8 @@ class UpdateOrdersToProcessingV2 */ protected $orderManagement; + protected $order; + protected $enableCustomPaidOrderStatus; protected $orderStatus; @@ -75,6 +77,9 @@ class UpdateOrdersToProcessingV2 protected const STATUS_PROCESSING = 'processing'; protected const STATUS_PENDING = 'pending'; protected const STATUS_CANCELED = 'canceled'; + + protected const STATE_PENDING_PAYMENT = 'pending_payment'; + protected const STATE_PROCESSING = 'processing'; protected const STATE_NEW = 'new'; protected const PAYMENT_AUTHORIZED = 'payment.authorized'; protected const ORDER_PAID = 'order.paid'; @@ -140,7 +145,8 @@ public function __construct( AbandonedQuote $quoteUpdate, \Magento\Quote\Api\CartRepositoryInterface $cartRepositoryInterface, CartManagementInterface $cartManagement, - CompleteOrder $oneCCMagentoOrder + CompleteOrder $oneCCMagentoOrder, + \Magento\Sales\Model\Order $order ) { $this->config = $config; @@ -162,6 +168,7 @@ public function __construct( $this->cartRepositoryInterface = $cartRepositoryInterface; $this->cartManagement = $cartManagement; $this->oneCCMagentoOrder = $oneCCMagentoOrder; + $this->order = $order; $this->enableCustomPaidOrderStatus = $this->config->isCustomPaidOrderStatusEnabled(); @@ -212,7 +219,7 @@ public function execute() $quote = $this->cartRepositoryInterface->get($cartId); $this->quoteUpdate->updateQuote($quote, $razorpayOrderData); - $result = $this->oneCCMagentoOrder->placeMagentoOrderthroughCron($cartId, $rzpPaymentData, $razorpayOrderData); + $result = $this->placeMagentoOrderthroughCron($cartId, $rzpPaymentData, $razorpayOrderData); if ($result['status'] == 'success') { $this->debug->log("Cronjob: Successfully placed Magento Order Id = " . $merchantOrderId); } else { @@ -260,6 +267,242 @@ public function execute() } } + public function placeMagentoOrderthroughCron($cartId, $rzpPaymentData, $rzpOrderData) + { + $merchantOrderId = isset($rzpOrderData->notes) ? $rzpOrderData->notes->merchant_order_id : null; + + $orderLink = $this->_objectManager->get('Razorpay\Magento\Model\OrderLink') + ->getCollection() + ->addFilter('order_id', $merchantOrderId) + ->getFirstItem(); + + $order = $this->order->loadByIncrementId($merchantOrderId); + + if (!$order->getId()) { + $orderId = $this->cartManagement->placeOrder($cartId); + $order = $this->order->load($orderId); + } else { + $orderId = $order->getId(); + } + + $rzpOrderId = $rzpOrderData->id; + $rzpPaymentId = $rzpPaymentData->id; + + $order->setEmailSent(0); + if ($order) { + // Return to failure page if payment is failed. + if ($rzpPaymentData->status === 'failed') { + $result = [ + 'status' => 'failed' + ]; + + return $result; + } + + if ($order->getStatus() === 'pending') { + if ($rzpPaymentData->status === 'pending' && $rzpPaymentData->method === 'cod') { + $order->setState(static::STATE_PENDING_PAYMENT) + ->setStatus(static::STATE_PENDING_PAYMENT); + } else { + $order->setState(static::STATE_PROCESSING) + ->setStatus(static::STATE_PROCESSING); + } + + $this->logger->info('graphQL: Order Status Updated to ' . $this->orderStatus); + } + + if (!empty($rzpOrderData->offers)) { + $discountAmount = $order->getDiscountAmount(); + + $codFee = $rzpOrderData->cod_fee; + $totalPaid = $rzpPaymentData->amount; + + $rzpPromotionAmount = 0; + + if (empty($rzpOrderData->promotions) === false) { + foreach ($rzpOrderData->promotions as $promotion) { + if (empty($promotion['code']) === false) { + $rzpPromotionAmount = $promotion['value']; + } + } + } + + $offerDiff = $rzpOrderData->line_items_total + $rzpOrderData->shipping_fee + $codFee - $totalPaid - $rzpPromotionAmount; + + if ($offerDiff > 0) { + $offerDiscount = ($offerDiff / 100); + // abs is used here as discount amount is returned as minus from order object. + $newDiscountAmount = abs($discountAmount) + $offerDiscount; + + $this->logger->info('graphQL: offerDiscount ' . $offerDiscount); + $this->logger->info('graphQL: newDiscountAmount ' . $newDiscountAmount); + $this->logger->info('graphQL: offerDiff ' . $offerDiff); + $this->logger->info('graphQL: codFee ' . $codFee); + $this->logger->info('graphQL: discountAmount ' . $discountAmount); + + $this->oneCCMagentoOrder->updateDiscountAmount($orderId, $newDiscountAmount, $offerDiscount, $totalPaid); + } + } + + $payment = $order->getPayment(); + + $payment->setLastTransId($rzpPaymentId) + ->setTransactionId($rzpPaymentId) + ->setIsTransactionClosed(true) + ->setShouldCloseParentTransaction(true); + + $payment->setParentTransactionId($payment->getTransactionId()); + + if ($rzpPaymentData->method != 'cod') { + if ($this->config->getPaymentAction() === \Razorpay\Magento\Model\PaymentMethod::ACTION_AUTHORIZE_CAPTURE) { + $payment->addTransactionCommentsToOrder( + "$rzpPaymentId", + $this->captureCommand->execute( + $payment, + $order->getGrandTotal(), + $order + ), + "" + ); + } else { + $payment->addTransactionCommentsToOrder( + "$rzpPaymentId", + $this->authorizeCommand->execute( + $payment, + $order->getGrandTotal(), + $order + ), + "" + ); + } + $this->logger->info('Payment authorized completed for id : ' . $order->getIncrementId()); + + } else { + $order->addStatusHistoryComment("Razorpay Payment Id " . $rzpPaymentId)->setStatus($order->getStatus())->setIsCustomerNotified(true); + } + + $transaction = $payment->addTransaction(\Magento\Sales\Model\Order\Payment\Transaction::TYPE_AUTH, null, true, ""); + + $transaction->setIsClosed(true); + + $transaction->save(); + + $this->logger->info('Payment authorized completed for id : ' . $order->getIncrementId()); + + $orderLink->setRzpPaymentId($rzpPaymentId); + + $orderLink->setRzpUpdateOrderCronStatus(OrderCronStatus::PAYMENT_AUTHORIZED_COMPLETED); + + if ($order->canInvoice() && $this->config->canAutoGenerateInvoice() + && $rzpOrderData->status === 'paid') { + $invoice = $this->invoiceService->prepareInvoice($order); + $invoice->setRequestedCaptureCase(\Magento\Sales\Model\Order\Invoice::CAPTURE_ONLINE); + $invoice->setTransactionId($rzpPaymentId); + $invoice->register(); + $invoice->save(); + + $this->logger->info('graphQL: Created Invoice for ' + . 'order_id ' . $rzpOrderId . ', ' + . 'rzp_payment_id ' . $rzpPaymentId); + + $transactionSave = $this->transaction + ->addObject($invoice) + ->addObject($invoice->getOrder()); + $transactionSave->save(); + + $this->invoiceSender->send($invoice); + + $order->addStatusHistoryComment( + __('Notified customer about invoice #%1.', $invoice->getId()) + )->setIsCustomerNotified(true); + + $this->logger->info('Invoice generated for id : ' . $order->getIncrementId()); + $orderLink->setRzpUpdateOrderCronStatus(OrderCronStatus::INVOICE_GENERATED); + } else if ($rzpOrderData->status === 'paid' and + ($order->canInvoice() === false or + $this->config->canAutoGenerateInvoice() === false)) { + $this->logger->info('Invoice generation not possible for id : ' . $order->getIncrementId()); + $orderLink->setRzpUpdateOrderCronStatus(OrderCronStatus::INVOICE_GENERATION_NOT_POSSIBLE); + } + + $comment = __('Razorpay order id %1.', $rzpOrderId); + + $order->addStatusHistoryComment( + $comment + )->setStatus($order->getStatus())->setIsCustomerNotified(true); + + $comment = __('Razorpay magic order.'); + + $order->addStatusHistoryComment( + $comment + )->setStatus($order->getStatus())->setIsCustomerNotified(true); + + $gstin = $rzpOrderData->notes->gstin ?? ''; + if (empty($gstin) === false) { + $gstinComment = __('Customer GSTIN number %1.', $gstin); + + $order->addStatusHistoryComment( + $gstinComment + )->setStatus($order->getStatus())->setIsCustomerNotified(true); + } + + try { + $this->checkoutSession->setRazorpayMailSentOnSuccess(true); + $this->orderSender->send($order); + $this->checkoutSession->unsRazorpayMailSentOnSuccess(); + } catch (\Magento\Framework\Exception\MailException $e) { + $this->logger->critical('graphQL: ' + . 'Razorpay Error:' . $e->getMessage()); + + throw new GraphQlInputException(__('Razorpay Error: %1.', $e->getMessage())); + } catch (\Exception $e) { + $this->logger->critical('graphQL: ' + . 'Error:' . $e->getMessage()); + + throw new GraphQlInputException(__('Error: %1.', $e->getMessage())); + } + + $this + ->checkoutSession + ->setLastSuccessQuoteId($order->getQuoteId()) + ->setLastQuoteId($order->getQuoteId()) + ->clearHelperData(); + if (empty($order) === false) { + $this + ->checkoutSession + ->setLastOrderId($order->getId()) + ->setLastRealOrderId($order->getIncrementId()) + ->setLastOrderStatus($order->getStatus()); + } + + $order->save(); + $orderLink->save(); + + // Get applied discounts data from the order object + $appliedDiscounts = $this->oneCCMagentoOrder->getAppliedDiscounts($order); + + $result = [ + 'status' => 'success', + 'order_id' => $order->getIncrementId(), + 'total_amount' => $order->getGrandTotal() * 100, + 'total_tax' => $order->getTaxAmount() * 100, + 'shipping_fee' => $order->getShippingAmount() * 100, + 'promotions' => $appliedDiscounts, + 'cod_fee' => 0 + ]; + + return $result; + } + + $result = [ + 'status' => 'failed' + ]; + + return $result; + } + + + protected function checkMagicOrder($razorpayOrderData) { $carrierCode = $razorpayOrderData->notes->carrier_code ?? null; From eea70e17c4061427f8f800c70393623fe798604b Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Tue, 20 Aug 2024 13:24:31 +0530 Subject: [PATCH 42/67] Added quote inactive logic --- Controller/OneClick/AbandonedQuote.php | 3 ++- Controller/OneClick/CompleteOrder.php | 1 + Controller/Payment/Webhook.php | 3 +++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Controller/OneClick/AbandonedQuote.php b/Controller/OneClick/AbandonedQuote.php index 04e3e59f..f6719a2f 100644 --- a/Controller/OneClick/AbandonedQuote.php +++ b/Controller/OneClick/AbandonedQuote.php @@ -179,11 +179,12 @@ public function execute() public function updateQuote($quote, $rzpOrderData) { + $quote->setIsActive(true)->save(); + $carrierCode = $rzpOrderData->notes->carrier_code ?? 'freeshipping'; $methodCode = $rzpOrderData->notes->method_code ?? 'freeshipping'; $email = $rzpOrderData->customer_details->email ?? ''; - $quote->setCustomerEmail($email); if (empty($rzpOrderData->customer_details->shipping_address) === false) { diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index 99818f58..dba26f43 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -189,6 +189,7 @@ public function execute() $email = $rzpOrderData->customer_details->email ?? null; $quote = $this->cartRepositoryInterface->get($cartId); + $quote->setIsActive(true)->save(); $this->updateQuote($quote, $rzpOrderData, $rzpPaymentData); diff --git a/Controller/Payment/Webhook.php b/Controller/Payment/Webhook.php index 593ee163..1561c86d 100644 --- a/Controller/Payment/Webhook.php +++ b/Controller/Payment/Webhook.php @@ -143,6 +143,7 @@ public function __construct( } } + /** * Processes the incoming webhook */ @@ -211,6 +212,8 @@ public function execute() if ($post['event'] === 'order.paid') { sleep(1); + $quote = $this->objectManagement->get('Magento\Quote\Model\Quote')->load($cartId); + $quote->setIsActive(false)->save(); } $merchantOrderId = $post['payload']['payment']['entity']['notes']['merchant_order_id']; From 4135b427c168a377eee330aae00d05adb59cdd91 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Tue, 20 Aug 2024 14:41:41 +0530 Subject: [PATCH 43/67] Bug fix and comment to identify the order placed through what process --- Controller/OneClick/CompleteOrder.php | 6 ++++++ Cron/UpdateOrdersToProcessingV2.php | 10 +++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index 99818f58..fa97c2cf 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -429,6 +429,12 @@ public function placeMagentoOrder($cartId, $rzpPaymentData, $rzpOrderData) $comment )->setStatus($order->getStatus())->setIsCustomerNotified(true); + $commentCallback = __('Razorpay magic order placed through callback.'); + + $order->addStatusHistoryComment( + $commentCallback + )->setStatus($order->getStatus())->setIsCustomerNotified(false); + $gstin = $rzpOrderData->notes->gstin ?? ''; if (empty($gstin) === false) { $gstinComment = __('Customer GSTIN number %1.', $gstin); diff --git a/Cron/UpdateOrdersToProcessingV2.php b/Cron/UpdateOrdersToProcessingV2.php index 06b49dcd..163f510e 100644 --- a/Cron/UpdateOrdersToProcessingV2.php +++ b/Cron/UpdateOrdersToProcessingV2.php @@ -271,7 +271,9 @@ public function placeMagentoOrderthroughCron($cartId, $rzpPaymentData, $rzpOrder { $merchantOrderId = isset($rzpOrderData->notes) ? $rzpOrderData->notes->merchant_order_id : null; - $orderLink = $this->_objectManager->get('Razorpay\Magento\Model\OrderLink') + $objectManagement = $this->getObjectManager(); + + $orderLink = $objectManagement->get('Razorpay\Magento\Model\OrderLink') ->getCollection() ->addFilter('order_id', $merchantOrderId) ->getFirstItem(); @@ -437,6 +439,12 @@ public function placeMagentoOrderthroughCron($cartId, $rzpPaymentData, $rzpOrder $comment )->setStatus($order->getStatus())->setIsCustomerNotified(true); + $commentCronjob = __('Razorpay magic order placed through cron job.'); + + $order->addStatusHistoryComment( + $commentCronjob + )->setStatus($order->getStatus())->setIsCustomerNotified(false); + $gstin = $rzpOrderData->notes->gstin ?? ''; if (empty($gstin) === false) { $gstinComment = __('Customer GSTIN number %1.', $gstin); From 32e06c66c64136b1a549c8f65e75cb82d2a4a91b Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Tue, 20 Aug 2024 18:31:57 +0530 Subject: [PATCH 44/67] Considering the address line 2 as well for street address --- Controller/OneClick/AbandonedQuote.php | 5 ++++- Controller/OneClick/CompleteOrder.php | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Controller/OneClick/AbandonedQuote.php b/Controller/OneClick/AbandonedQuote.php index f6719a2f..d0a71cee 100644 --- a/Controller/OneClick/AbandonedQuote.php +++ b/Controller/OneClick/AbandonedQuote.php @@ -245,12 +245,15 @@ protected function getAddress($rzpAddress, $regionCode, $email) { $name = explode(' ', $rzpAddress->name); + $streetRzp = $rzpAddress->line1 . ', ' . $rzpAddress->line2; + $street = substr($streetRzp, 0, 255); + return [ 'email' => $email, //buyer email id 'address' => [ 'firstname' => $name[0], //address Details 'lastname' => empty($name[1]) === false ? $name[1] : '.', - 'street' => $rzpAddress->line1, + 'street' => $street, 'city' => $rzpAddress->city, 'country_id' => strtoupper($rzpAddress->country), 'region' => $regionCode, diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index dba26f43..b558ae89 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -622,12 +622,15 @@ protected function getAddress($rzpAddress, $regionCode, $email) { $name = explode(' ', $rzpAddress->name); + $streetRzp = $rzpAddress->line1 . ', ' . $rzpAddress->line2; + $street = substr($streetRzp, 0, 255); + return [ 'email' => $email, //buyer email id 'address' => [ 'firstname' => $name[0], //address Details 'lastname' => empty($name[1]) === false ? $name[1] : '.', - 'street' => $rzpAddress->line1, + 'street' => $street, 'city' => $rzpAddress->city, 'country_id' => strtoupper($rzpAddress->country), 'region' => $regionCode, From b83e2668f4be3af48784e159f8100e2d91a2795c Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Wed, 21 Aug 2024 11:14:53 +0530 Subject: [PATCH 45/67] Removed invoice not generated status code update from callback logic --- Controller/OneClick/CompleteOrder.php | 1 - 1 file changed, 1 deletion(-) diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index 5fa2b7cf..e62354b4 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -415,7 +415,6 @@ public function placeMagentoOrder($cartId, $rzpPaymentData, $rzpOrderData) ($order->canInvoice() === false or $this->config->canAutoGenerateInvoice() === false)) { $this->logger->info('Invoice generation not possible for id : ' . $order->getIncrementId()); - $orderLink->setRzpUpdateOrderCronStatus(OrderCronStatus::INVOICE_GENERATION_NOT_POSSIBLE); } $comment = __('Razorpay order id %1.', $rzpOrderId); From eb5af647366e4472290cb7bdec55d60c5836c845 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Mon, 26 Aug 2024 17:20:28 +0530 Subject: [PATCH 46/67] Added retry logic in callback and address details to order comments in case of incomplete address data --- Controller/OneClick/AbandonedQuote.php | 40 ++++++++- Controller/OneClick/CompleteOrder.php | 117 ++++++++++++++++++------- Cron/UpdateOrdersToProcessingV2.php | 32 +++---- 3 files changed, 138 insertions(+), 51 deletions(-) diff --git a/Controller/OneClick/AbandonedQuote.php b/Controller/OneClick/AbandonedQuote.php index d0a71cee..95525c58 100644 --- a/Controller/OneClick/AbandonedQuote.php +++ b/Controller/OneClick/AbandonedQuote.php @@ -139,11 +139,40 @@ public function execute() $order->setState(static::STATE_PENDING_PAYMENT) ->setStatus(static::STATE_PENDING_PAYMENT); } + + //In case customer address not completely added to order details, we will set the address details in order comments. + $shippingRZPAddress = $rzpOrderData->customer_details->shipping_address; + $shippingStreetRzp = $shippingRZPAddress->line1 . ', ' . $shippingRZPAddress->line2; + + if (strlen($shippingStreetRzp) > 255) { + $shippingAddress = 'Customer Complete Shipping Address - '. $shippingRZPAddress->name. ', '. + $shippingStreetRzp. ', '. + $shippingRZPAddress->city. ', '. + strtoupper($shippingRZPAddress->country). ' - '. + $shippingRZPAddress->zipcode; + $order->addStatusHistoryComment( + $shippingAddress + )->setStatus($order->getStatus())->setIsCustomerNotified(false); + } + + $billingRZPAddress = $rzpOrderData->customer_details->billing_address; + $billingStreetRzp = $billingRZPAddress->line1 . ', ' . $billingRZPAddress->line2; + + if (strlen($billingStreetRzp) > 255) { + $billingAddress = 'Customer Complete Billing Address - '. $billingRZPAddress->name. ', '. + $billingStreetRzp. ', '. + $billingRZPAddress->city. ', '. + strtoupper($billingRZPAddress->country). ' - '. + $billingRZPAddress->zipcode; + $order->addStatusHistoryComment( + $billingAddress + )->setStatus($order->getStatus())->setIsCustomerNotified(false); + } $order->save(); $quote->setIsActive(true)->save(); } catch (\Exception $e) { - $this->logger->info('graphQL: magento pending order placement failed for AB cart and rzp order id: '.$rzpOrderId); + $this->logger->info('graphQL: magento pending order placement failed for AB cart and rzp order id: ' . $rzpOrderId); } return $resultJson->setData([ @@ -243,7 +272,14 @@ protected function getRegionCode($country, $state) protected function getAddress($rzpAddress, $regionCode, $email) { - $name = explode(' ', $rzpAddress->name); + $name = $rzpAddress->name; + // Find the position of the first non-whitespace character + $firstNonWhitespacePos = strpos($name, trim($name)[0]); + + // Trim the string up to the first non-whitespace character + $trimmedName = substr($name, $firstNonWhitespacePos); + + $name = explode(' ', $trimmedName); $streetRzp = $rzpAddress->line1 . ', ' . $rzpAddress->line2; $street = substr($streetRzp, 0, 255); diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index e62354b4..86ae80bd 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -99,6 +99,7 @@ class CompleteOrder extends Action const STATE_PROCESSING = 'processing'; const QUOTE_LINKED_RAZORPAY_ORDER_ID = "quote_linked_razorpay_order_id"; const INVENTORY_OUT_OF_STOCK = "Some of the products are out of stock"; + const MAX_ATTEMPTS = "3"; /** * CompleteOrder constructor. @@ -269,27 +270,45 @@ public function placeMagentoOrder($cartId, $rzpPaymentData, $rzpOrderData) ->addFilter('order_id', $merchantOrderId) ->getFirstItem(); - $order = $this->order->loadByIncrementId($merchantOrderId); - - if (!$order->getId()) { - $orderId = $this->cartManagement->placeOrder($cartId); - $order = $this->order->load($orderId); - } else { - $orderId = $order->getId(); - } + $rzpOrderId = $rzpOrderData->id; + $rzpPaymentId = $rzpPaymentData->id; $rzpOrderId = $rzpOrderData->id; $rzpPaymentId = $rzpPaymentData->id; + //Callback will retry MAX_ATTEMPTS to place order on magento. + $attempts = 0; + while ($attempts < self::MAX_ATTEMPTS) { + $attempts++; + try { + $order = $this->order->loadByIncrementId($merchantOrderId); + + if (!$order->getId()) { + $orderId = $this->cartManagement->placeOrder($cartId); + $order = $this->order->load($orderId); + } else { + $orderId = $order->getId(); + } + break; + } catch (\Exception $e) { + $this->logger->critical("Magento order placement is failed for ".$rzpOrderId." in ".$attempts." attempt and the error message is - " . $e->getMessage()); + + if ($attempts == self::MAX_ATTEMPTS) { + $this->logger->critical("All attempts to place the Magento order have failed for rzp order id ".$rzpOrderId." & rzp payment id ".$rzpPaymentId." & magento cart id ".$cartId); + + throw new \Exception("Magento order creation failed with error message.". $e->getMessage()); + } + continue; + } + } + $order->setEmailSent(0); if ($order) { // Return to failure page if payment is failed. if ($rzpPaymentData->status === 'failed') { - $result = [ - 'status' => 'failed' - ]; + $this->logger->critical("Razorpay payment is failed for the order id " . $rzpOrderId); - return $result; + throw new \Exception("Razorpay payment is failed for the order id " . $rzpOrderId); } if ($order->getStatus() === 'pending') { @@ -301,7 +320,7 @@ public function placeMagentoOrder($cartId, $rzpPaymentData, $rzpOrderData) ->setStatus(static::STATE_PROCESSING); } - $this->logger->info('graphQL: Order Status Updated to ' . $this->orderStatus); + $this->logger->info('graphQL: Order Status Updated to ' . $this->orderStatus ." for order id ".$rzpOrderId); } if (!empty($rzpOrderData->offers)) { @@ -444,6 +463,35 @@ public function placeMagentoOrder($cartId, $rzpPaymentData, $rzpOrderData) )->setStatus($order->getStatus())->setIsCustomerNotified(true); } + //In case customer address not completely added to order details, we will set the address details in order comments. + $shippingRZPAddress = $rzpOrderData->customer_details->shipping_address; + $shippingStreetRzp = $shippingRZPAddress->line1 . ', ' . $shippingRZPAddress->line2; + + if (strlen($shippingStreetRzp) > 255) { + $shippingAddress = 'Customer Complete Shipping Address - '. $shippingRZPAddress->name. ', '. + $shippingStreetRzp. ', '. + $shippingRZPAddress->city. ', '. + strtoupper($shippingRZPAddress->country). ' - '. + $shippingRZPAddress->zipcode; + $order->addStatusHistoryComment( + $shippingAddress + )->setStatus($order->getStatus())->setIsCustomerNotified(false); + } + + $billingRZPAddress = $rzpOrderData->customer_details->billing_address; + $billingStreetRzp = $billingRZPAddress->line1 . ', ' . $billingRZPAddress->line2; + + if (strlen($billingStreetRzp) > 255) { + $billingAddress = 'Customer Complete Billing Address - '. $billingRZPAddress->name. ', '. + $billingStreetRzp. ', '. + $billingRZPAddress->city. ', '. + strtoupper($billingRZPAddress->country). ' - '. + $billingRZPAddress->zipcode; + $order->addStatusHistoryComment( + $billingAddress + )->setStatus($order->getStatus())->setIsCustomerNotified(false); + } + try { $this->checkoutSession->setRazorpayMailSentOnSuccess(true); $this->orderSender->send($order); @@ -528,18 +576,17 @@ public function updateDiscountAmount($orderId, $newDiscountAmount, $offerAmount, // Load the order $order = $this->order->load($orderId); - // TODO: Commenting this temp to unblock navya fashion. -// // Update discount amount -// $order->setDiscountAmount($newDiscountAmount); -// $order->setBaseDiscountAmount($newDiscountAmount); -// -// $totalBaseGrandTotal = $order->getBaseGrandTotal(); -// $totalGrandTotal = $order->getGrandTotal(); -// -// $order->setBaseGrandTotal($totalBaseGrandTotal - $offerAmount); -// $order->setGrandTotal($totalGrandTotal - $offerAmount); -// -// $order->setTotalPaid($totalPaid / 100);*/ + // Update discount amount + $order->setDiscountAmount($newDiscountAmount); + $order->setBaseDiscountAmount($newDiscountAmount); + + $totalBaseGrandTotal = $order->getBaseGrandTotal(); + $totalGrandTotal = $order->getGrandTotal(); + + $order->setBaseGrandTotal($totalBaseGrandTotal - $offerAmount); + $order->setGrandTotal($totalGrandTotal - $offerAmount); + + $order->setTotalPaid($totalPaid / 100); $comment = __('Razorpay offer applied ₹%1.', $offerAmount); @@ -605,7 +652,6 @@ protected function updateQuote($quote, $rzpOrderData, $rzpPaymentData) $quote->getPayment()->importData(['method' => $paymentMethod]); $quote->save(); - } protected function getRegionCode($country, $state) @@ -625,7 +671,14 @@ protected function getRegionCode($country, $state) protected function getAddress($rzpAddress, $regionCode, $email) { - $name = explode(' ', $rzpAddress->name); + $name = $rzpAddress->name; + // Find the position of the first non-whitespace character + $firstNonWhitespacePos = strpos($name, trim($name)[0]); + + // Trim the string up to the first non-whitespace character + $trimmedName = substr($name, $firstNonWhitespacePos); + + $name = explode(' ', $trimmedName); $streetRzp = $rzpAddress->line1 . ', ' . $rzpAddress->line2; $street = substr($streetRzp, 0, 255); @@ -649,13 +702,9 @@ protected function getAddress($rzpAddress, $regionCode, $email) protected function validateSignature($request, $cartMaskId) { if (empty($request['error']) === false) { - $this - ->logger - ->critical("Validate: Payment Failed or error from gateway"); - $this - ->messageManager - ->addError(__('Payment Failed')); - throw new \Exception("Payment Failed or error from gateway"); + $this->logger->critical("Validate: Payment Failed or error from gateway" . $request['razorpay_order_id']); + $this->messageManager->addError(__('Payment Failed')); + throw new \Exception("Payment Failed or error from gateway for ". $request['razorpay_order_id']); } $catalogRzpKey = static::QUOTE_LINKED_RAZORPAY_ORDER_ID . '_' . $cartMaskId; diff --git a/Cron/UpdateOrdersToProcessingV2.php b/Cron/UpdateOrdersToProcessingV2.php index 163f510e..3edc538d 100644 --- a/Cron/UpdateOrdersToProcessingV2.php +++ b/Cron/UpdateOrdersToProcessingV2.php @@ -278,27 +278,31 @@ public function placeMagentoOrderthroughCron($cartId, $rzpPaymentData, $rzpOrder ->addFilter('order_id', $merchantOrderId) ->getFirstItem(); - $order = $this->order->loadByIncrementId($merchantOrderId); - - if (!$order->getId()) { - $orderId = $this->cartManagement->placeOrder($cartId); - $order = $this->order->load($orderId); - } else { - $orderId = $order->getId(); - } - $rzpOrderId = $rzpOrderData->id; $rzpPaymentId = $rzpPaymentData->id; + try { + $order = $this->order->loadByIncrementId($merchantOrderId); + + if (!$order->getId()) { + $orderId = $this->cartManagement->placeOrder($cartId); + $order = $this->order->load($orderId); + } else { + $orderId = $order->getId(); + } + } catch (\Exception $e) { + $this->logger->critical("Cron failed to place the Magento order for rzp order id " . $rzpOrderId . " & rzp payment id " . $rzpPaymentId . " & magento cart id " . $cartId. " with error message - ".$e->getMessage()); + + throw new \Exception("Magento order creation failed with error message." . $e->getMessage()); + } + $order->setEmailSent(0); if ($order) { // Return to failure page if payment is failed. if ($rzpPaymentData->status === 'failed') { - $result = [ - 'status' => 'failed' - ]; + $this->logger->critical("Razorpay payment is failed for the order id " . $rzpOrderId); - return $result; + throw new \Exception("Razorpay payment is failed for the order id " . $rzpOrderId); } if ($order->getStatus() === 'pending') { @@ -424,7 +428,6 @@ public function placeMagentoOrderthroughCron($cartId, $rzpPaymentData, $rzpOrder ($order->canInvoice() === false or $this->config->canAutoGenerateInvoice() === false)) { $this->logger->info('Invoice generation not possible for id : ' . $order->getIncrementId()); - $orderLink->setRzpUpdateOrderCronStatus(OrderCronStatus::INVOICE_GENERATION_NOT_POSSIBLE); } $comment = __('Razorpay order id %1.', $rzpOrderId); @@ -510,7 +513,6 @@ public function placeMagentoOrderthroughCron($cartId, $rzpPaymentData, $rzpOrder } - protected function checkMagicOrder($razorpayOrderData) { $carrierCode = $razorpayOrderData->notes->carrier_code ?? null; From 87dc6f57f2e8f9fe863e5b2421a91c30984942df Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Thu, 29 Aug 2024 16:08:45 +0530 Subject: [PATCH 47/67] Bug fix for mini cart checkout button issue --- .../frontend/web/template/magic/minicart.html | 30 ++++--------------- 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/view/frontend/web/template/magic/minicart.html b/view/frontend/web/template/magic/minicart.html index 23d018ce..f3d05d0a 100644 --- a/view/frontend/web/template/magic/minicart.html +++ b/view/frontend/web/template/magic/minicart.html @@ -79,34 +79,16 @@
-
- - - isDisabled()) : ?> - - disabled="disabled" - - > - - escapeHtml(__('Proceed to Checkout')) ?> -
-
From 6e73d7141fb88ebb97318ef8a41e050c0c740124 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Thu, 29 Aug 2024 18:32:09 +0530 Subject: [PATCH 48/67] Converting item qty as int --- Controller/OneClick/PlaceOrder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Controller/OneClick/PlaceOrder.php b/Controller/OneClick/PlaceOrder.php index 4477e1e7..4a4c06dc 100644 --- a/Controller/OneClick/PlaceOrder.php +++ b/Controller/OneClick/PlaceOrder.php @@ -269,7 +269,7 @@ public function execute() 'price' => $quoteItem->getPrice() * 100, 'offer_price' => $offerPrice, 'tax_amount' => 0, - 'quantity' => $quoteItem->getQty(), + 'quantity' => (int)$quoteItem->getQty(), 'name' => $quoteItem->getName(), 'description' => $quoteItem->getName(), 'image_url' => $productImageUrl, From 3f82c025afd13c2d47f7ebed8a19d176308b9671 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Wed, 18 Sep 2024 18:51:10 +0530 Subject: [PATCH 49/67] Added COD fee support in magento order --- Block/Adminhtml/Order/Totals.php | 26 +++++++++ Controller/OneClick/CompleteOrder.php | 4 ++ Model/Total/CustomCodFee.php | 53 +++++++++++++++++++ Setup/UpgradeSchema.php | 26 +++++++++ etc/di.xml | 23 ++++++++ view/adminhtml/layout/sales_order_view.xml | 12 +++++ .../templates/oneclick/custom_cod_fee.phtml | 14 +++++ 7 files changed, 158 insertions(+) create mode 100644 Block/Adminhtml/Order/Totals.php create mode 100644 Model/Total/CustomCodFee.php create mode 100644 view/adminhtml/layout/sales_order_view.xml create mode 100644 view/adminhtml/templates/oneclick/custom_cod_fee.phtml diff --git a/Block/Adminhtml/Order/Totals.php b/Block/Adminhtml/Order/Totals.php new file mode 100644 index 00000000..23933133 --- /dev/null +++ b/Block/Adminhtml/Order/Totals.php @@ -0,0 +1,26 @@ +getOrder(); + $customAmount = $order->getData('razorpay_cod_fee'); // Use your custom field here + if ($customAmount) { + $this->addTotal(new DataObject([ + 'code' => 'razorpay_cod_fee', + 'label' => __('COD Fee'), + 'value' => $customAmount, + 'area' => 'footer' + ]), 'shipping'); + } + + return $this; + } +} diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index 86ae80bd..2b04707b 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -642,6 +642,10 @@ protected function updateQuote($quote, $rzpOrderData, $rzpPaymentData) if ($rzpPaymentData->method === 'cod') { $paymentMethod = static::COD; + // Set the custom fee in the quote + $codFee = $rzpOrderData->cod_fee ?? 0; + + $quote->setData('razorpay_cod_fee', $codFee); } else { $paymentMethod = static::RAZORPAY; } diff --git a/Model/Total/CustomCodFee.php b/Model/Total/CustomCodFee.php new file mode 100644 index 00000000..8c15116a --- /dev/null +++ b/Model/Total/CustomCodFee.php @@ -0,0 +1,53 @@ +getData('razorpay_cod_fee'); + if ($customFee) { + $total->setTotalAmount('razorpay_cod_fee', $customFee); + $total->setBaseTotalAmount('razorpay_cod_fee', $customFee); + + $total->setGrandTotal($total->getGrandTotal() + $customFee); + $total->setBaseGrandTotal($total->getBaseGrandTotal() + $customFee); + } + + return $this; + } + + /** + * Fetch the custom total data + * + * @param \Magento\Quote\Model\Quote $quote + * @param \Magento\Quote\Model\Quote\Address\Total $total + * @return array + */ + public function fetch(\Magento\Quote\Model\Quote $quote, \Magento\Quote\Model\Quote\Address\Total $total) + { + $customFee = $quote->getData('razorpay_cod_fee'); + return [ + 'code' => 'razorpay_cod_fee', + 'title' => __('Shipping & Handling Fee'), + 'value' => $customFee + ]; + } +} diff --git a/Setup/UpgradeSchema.php b/Setup/UpgradeSchema.php index c93f89a6..62a5ec3a 100755 --- a/Setup/UpgradeSchema.php +++ b/Setup/UpgradeSchema.php @@ -118,6 +118,32 @@ public function upgrade( 'comment' => 'RZP Update Order Processing Cron # of times executed' ] ); + + $setup->getConnection()->addColumn( + $tableName, + 'razorpay_cod_fee', + [ + 'nullable' => true, + 'default' => 0, + 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, + 'comment' => 'RZP custom cod fee' + ] + ); + } + + $tableNameForQuote = $setup->getTable('quote'); + if ($setup->getConnection()->isTableExists($tableNameForQuote) == true) + { + $setup->getConnection()->addColumn( + $tableName, + 'razorpay_cod_fee', + [ + 'nullable' => true, + 'default' => 0, + 'type' => \Magento\Framework\DB\Ddl\Table::TYPE_DECIMAL, + 'comment' => 'RZP custom cod fee' + ] + ); } $table = $setup->getConnection()->newTable($setup->getTable(OrderLink::TABLE_NAME)); diff --git a/etc/di.xml b/etc/di.xml index f48dc4d1..4b9325e2 100644 --- a/etc/di.xml +++ b/etc/di.xml @@ -75,4 +75,27 @@ RazorpayLogger + + + + + + Razorpay\Magento\Model\Total\CustomCodFee + 250 + + + + + + + + + + + Razorpay\Magento\Model\Total\CustomCodFee + 250 + + + + diff --git a/view/adminhtml/layout/sales_order_view.xml b/view/adminhtml/layout/sales_order_view.xml new file mode 100644 index 00000000..d227b82b --- /dev/null +++ b/view/adminhtml/layout/sales_order_view.xml @@ -0,0 +1,12 @@ + + + + + + + COD Fee + + + + + diff --git a/view/adminhtml/templates/oneclick/custom_cod_fee.phtml b/view/adminhtml/templates/oneclick/custom_cod_fee.phtml new file mode 100644 index 00000000..92332128 --- /dev/null +++ b/view/adminhtml/templates/oneclick/custom_cod_fee.phtml @@ -0,0 +1,14 @@ +getParentBlock()->getOrder(); +$amount = $order->getData('razorpay_cod_fee'); +?> + + + + escapeHtml(__('COD Fee')) ?> + + + escapeHtml(__('INR')) ?> + + + From 563f1efcef71825f6fa26a0229c7790fda93c1bb Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Thu, 19 Sep 2024 16:46:18 +0530 Subject: [PATCH 50/67] Added cod fee in order comment --- Controller/OneClick/CompleteOrder.php | 9 +++++++++ Cron/UpdateOrdersToProcessingV2.php | 11 ++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index 2b04707b..dfe6bae8 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -463,6 +463,15 @@ public function placeMagentoOrder($cartId, $rzpPaymentData, $rzpOrderData) )->setStatus($order->getStatus())->setIsCustomerNotified(true); } + $codFee = $rzpOrderData->cod_fee; + if ($codFee > 0) { + $codFeeComment = __('Razorpay COD Fee %1.', $codFee / 100); + + $order->addStatusHistoryComment( + $codFeeComment + )->setStatus($order->getStatus())->setIsCustomerNotified(true); + } + //In case customer address not completely added to order details, we will set the address details in order comments. $shippingRZPAddress = $rzpOrderData->customer_details->shipping_address; $shippingStreetRzp = $shippingRZPAddress->line1 . ', ' . $shippingRZPAddress->line2; diff --git a/Cron/UpdateOrdersToProcessingV2.php b/Cron/UpdateOrdersToProcessingV2.php index 3edc538d..b9e98137 100644 --- a/Cron/UpdateOrdersToProcessingV2.php +++ b/Cron/UpdateOrdersToProcessingV2.php @@ -291,7 +291,7 @@ public function placeMagentoOrderthroughCron($cartId, $rzpPaymentData, $rzpOrder $orderId = $order->getId(); } } catch (\Exception $e) { - $this->logger->critical("Cron failed to place the Magento order for rzp order id " . $rzpOrderId . " & rzp payment id " . $rzpPaymentId . " & magento cart id " . $cartId. " with error message - ".$e->getMessage()); + $this->logger->critical("Cron failed to place the Magento order for rzp order id " . $rzpOrderId . " & rzp payment id " . $rzpPaymentId . " & magento cart id " . $cartId . " with error message - " . $e->getMessage()); throw new \Exception("Magento order creation failed with error message." . $e->getMessage()); } @@ -457,6 +457,15 @@ public function placeMagentoOrderthroughCron($cartId, $rzpPaymentData, $rzpOrder )->setStatus($order->getStatus())->setIsCustomerNotified(true); } + $codFee = $rzpOrderData->cod_fee; + if ($codFee > 0) { + $codFeeComment = __('Razorpay COD Fee %1.', $codFee / 100); + + $order->addStatusHistoryComment( + $codFeeComment + )->setStatus($order->getStatus())->setIsCustomerNotified(true); + } + try { $this->checkoutSession->setRazorpayMailSentOnSuccess(true); $this->orderSender->send($order); From 7e190ff7387842e1c1ef1d541a57a7279e3662e5 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Thu, 19 Sep 2024 16:50:47 +0530 Subject: [PATCH 51/67] Added magic-integration param --- view/frontend/layout/default.xml | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/view/frontend/layout/default.xml b/view/frontend/layout/default.xml index 830eb9f8..958ad04d 100644 --- a/view/frontend/layout/default.xml +++ b/view/frontend/layout/default.xml @@ -1,8 +1,30 @@ - + + ]]> + + + + From fc092d8edc09f61e5e21bb6035e8f9a982fb7545 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Mon, 23 Sep 2024 15:01:24 +0530 Subject: [PATCH 52/67] Version bump to 4.1.7 with COD support --- composer.json | 2 +- etc/module.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index cb60ad8a..ffef340a 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "razorpay/magento", "description": "Razorpay Magento 2.0 plugin for accepting payments.", - "version": "4.1.6", + "version": "4.1.7", "require": { "php": "7.*|^8.1", "razorpay/razorpay": "2.9.*" diff --git a/etc/module.xml b/etc/module.xml index e5c05d79..46d7b7b2 100644 --- a/etc/module.xml +++ b/etc/module.xml @@ -1,6 +1,6 @@ - + From db7e2ac02824d91e99452d97ec81976638f96899 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Tue, 8 Oct 2024 17:05:39 +0530 Subject: [PATCH 53/67] Updated customer consent logic --- Controller/OneClick/CompleteOrder.php | 7 ++++--- Model/CustomerConsent.php | 25 ++++++++++++++++++------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index dfe6bae8..356e08cb 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -200,11 +200,12 @@ public function execute() $customerCartId = $this->cartConverter->convertGuestCartToCustomer($cartId); $this->logger->info('graphQL: customerCartId ' . $customerCartId); - $isCustomerConsentSet = false; - if ($isCustomerConsentSet === true) { + $isCustomerConsentSet = isset($rzpOrderData->notes) ? $rzpOrderData->notes->customer_consent_set : 'no'; + + if ($isCustomerConsentSet === "yes") { // Subscribe news letter based on customer consent data $subscribeNewsLetter = $this->customerConsent->subscribeCustomer($customerCartId, $email); - $this->logger->info('graphQL: subscribed ' . $subscribeNewsLetter); + $this->logger->info('graphQL: news letter subscribed? ' . $subscribeNewsLetter); } $result = $this->placeMagentoOrder($cartId, $rzpPaymentData, $rzpOrderData); diff --git a/Model/CustomerConsent.php b/Model/CustomerConsent.php index a689381d..317634a0 100644 --- a/Model/CustomerConsent.php +++ b/Model/CustomerConsent.php @@ -41,21 +41,32 @@ public function subscribeCustomer($customerId, $customerEmail) { try { $store = $this->storeManager->getStore(); - $storeId = $store->getStoreId(); + $storeId = $store->getId(); // get the current store ID /** @var \Magento\Newsletter\Model\Subscriber $subscriber */ $subscriber = $this->subscriberFactory->create(); - $subscriber->setStoreId($storeId) - ->setCustomerId($customerId) - ->setSubscriberEmail($customerEmail) - ->setSubscriberStatus(\Magento\Newsletter\Model\Subscriber::STATUS_SUBSCRIBED); + // Check if the customer is already subscribed + $existingSubscriber = $subscriber->loadByCustomerId($customerId); - $subscriber->save(); + // If the customer is already subscribed, update the existing subscription + if ($existingSubscriber && $existingSubscriber->getId()) { + $existingSubscriber->setSubscriberEmail($customerEmail) + ->setStoreId($storeId) + ->setSubscriberStatus(\Magento\Newsletter\Model\Subscriber::STATUS_SUBSCRIBED); + $existingSubscriber->save(); + } else { + // If no existing subscription, create a new one + $subscriber->setStoreId($storeId) + ->setCustomerId($customerId) + ->setSubscriberEmail($customerEmail) + ->setSubscriberStatus(\Magento\Newsletter\Model\Subscriber::STATUS_SUBSCRIBED); + $subscriber->save(); + } return true; } catch (\Exception $e) { - // Handle the exception + // Handle the exception (log it, etc.) return false; } } From b3a51ae905251f51d3a4b670ea7860ea0d868e65 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Tue, 8 Oct 2024 17:49:47 +0530 Subject: [PATCH 54/67] Removed magic script from PDP and cart layout --- view/frontend/layout/default.xml | 1 - view/frontend/templates/oneclick/buynow.phtml | 4 ---- view/frontend/templates/oneclick/magiccart.phtml | 2 -- 3 files changed, 7 deletions(-) diff --git a/view/frontend/layout/default.xml b/view/frontend/layout/default.xml index 958ad04d..124cda3e 100644 --- a/view/frontend/layout/default.xml +++ b/view/frontend/layout/default.xml @@ -2,7 +2,6 @@ - diff --git a/view/frontend/templates/oneclick/buynow.phtml b/view/frontend/templates/oneclick/buynow.phtml index 1c156f8f..5f95dba5 100644 --- a/view/frontend/templates/oneclick/buynow.phtml +++ b/view/frontend/templates/oneclick/buynow.phtml @@ -34,9 +34,5 @@ $isBuyNowEnabled = $configData->getMagicBuyNowStatus(); - - diff --git a/view/frontend/templates/oneclick/magiccart.phtml b/view/frontend/templates/oneclick/magiccart.phtml index e1e0f687..9360ca95 100644 --- a/view/frontend/templates/oneclick/magiccart.phtml +++ b/view/frontend/templates/oneclick/magiccart.phtml @@ -47,6 +47,4 @@ $cartDataCount = count($cartData); - - From 3b991d4f2a01c39033eb04574910e2122064eba3 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Wed, 16 Oct 2024 20:27:20 +0530 Subject: [PATCH 55/67] Updated consent fetch key and added logs --- Controller/OneClick/CompleteOrder.php | 6 +++--- Model/CustomerConsent.php | 25 +++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index 356e08cb..17cc9196 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -200,12 +200,12 @@ public function execute() $customerCartId = $this->cartConverter->convertGuestCartToCustomer($cartId); $this->logger->info('graphQL: customerCartId ' . $customerCartId); - $isCustomerConsentSet = isset($rzpOrderData->notes) ? $rzpOrderData->notes->customer_consent_set : 'no'; + $isCustomerConsentSet = isset($rzpOrderData->notes) ? $rzpOrderData->notes->customer_consent : false; - if ($isCustomerConsentSet === "yes") { + if ($isCustomerConsentSet) { // Subscribe news letter based on customer consent data $subscribeNewsLetter = $this->customerConsent->subscribeCustomer($customerCartId, $email); - $this->logger->info('graphQL: news letter subscribed? ' . $subscribeNewsLetter); + $this->logger->info('graphQL: news letter subscribed? ' . json_encode($subscribeNewsLetter)); } $result = $this->placeMagentoOrder($cartId, $rzpPaymentData, $rzpOrderData); diff --git a/Model/CustomerConsent.php b/Model/CustomerConsent.php index 317634a0..9934a745 100644 --- a/Model/CustomerConsent.php +++ b/Model/CustomerConsent.php @@ -35,7 +35,7 @@ public function __construct( * * @param int $customerId * @param strig $customerEmail - * @return bool + * @return array */ public function subscribeCustomer($customerId, $customerEmail) { @@ -55,6 +55,14 @@ public function subscribeCustomer($customerId, $customerEmail) ->setStoreId($storeId) ->setSubscriberStatus(\Magento\Newsletter\Model\Subscriber::STATUS_SUBSCRIBED); $existingSubscriber->save(); + + return [ + "subscribed" => true, + "customerId" => $customerId, + "customerEmail" => $customerEmail, + "storeId" => $storeId, + "isExistingSubscriber" => true, + ]; } else { // If no existing subscription, create a new one $subscriber->setStoreId($storeId) @@ -62,12 +70,25 @@ public function subscribeCustomer($customerId, $customerEmail) ->setSubscriberEmail($customerEmail) ->setSubscriberStatus(\Magento\Newsletter\Model\Subscriber::STATUS_SUBSCRIBED); $subscriber->save(); + return [ + "subscribed" => true, + "customerId" => $customerId, + "customerEmail" => $customerEmail, + "storeId" => $storeId, + "isExistingSubscriber" => false, + ]; } return true; } catch (\Exception $e) { // Handle the exception (log it, etc.) - return false; + + return [ + "subscribed" => false, + "customerId" => $customerId, + "customerEmail" => $customerEmail, + "errorMessage" => $e->getMessage(), + ]; } } } From 3163452421fe7e536e80824e6681623e553c3c43 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Thu, 5 Dec 2024 13:51:13 +0530 Subject: [PATCH 56/67] Email less checkout feature support --- Controller/OneClick/AbandonedQuote.php | 6 +++++- Controller/OneClick/CompleteOrder.php | 7 +++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Controller/OneClick/AbandonedQuote.php b/Controller/OneClick/AbandonedQuote.php index 95525c58..94beb03c 100644 --- a/Controller/OneClick/AbandonedQuote.php +++ b/Controller/OneClick/AbandonedQuote.php @@ -213,7 +213,11 @@ public function updateQuote($quote, $rzpOrderData) $carrierCode = $rzpOrderData->notes->carrier_code ?? 'freeshipping'; $methodCode = $rzpOrderData->notes->method_code ?? 'freeshipping'; - $email = $rzpOrderData->customer_details->email ?? ''; + //This change is to support email less checkout. + $email = $quote->getCustomerEmail(); + if($email == null) { + $email = $rzpOrderData->customer_details->email ?? ''; + } $quote->setCustomerEmail($email); if (empty($rzpOrderData->customer_details->shipping_address) === false) { diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index 17cc9196..d32f6ee7 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -616,8 +616,11 @@ protected function updateQuote($quote, $rzpOrderData, $rzpPaymentData) $carrierCode = $rzpOrderData->notes->carrier_code ?? 'freeshipping'; $methodCode = $rzpOrderData->notes->method_code ?? 'freeshipping'; - $email = $rzpOrderData->customer_details->email ?? ''; - + //This change is to support email less checkout. + $email = $quote->getCustomerEmail(); + if($email == null) { + $email = $rzpOrderData->customer_details->email ?? ''; + } $quote->setCustomerEmail($email); $shippingCountry = $rzpOrderData->customer_details->shipping_address->country; From 2b09f03230412e8c625c5e6dd22dfdda513c568a Mon Sep 17 00:00:00 2001 From: Alex Benny Date: Fri, 13 Dec 2024 14:10:56 +0530 Subject: [PATCH 57/67] loader fix on order success --- view/frontend/web/js/magic-buy-now.js | 516 +++++++++++++------------- view/frontend/web/js/magic-cart.js | 509 ++++++++++++------------- 2 files changed, 516 insertions(+), 509 deletions(-) diff --git a/view/frontend/web/js/magic-buy-now.js b/view/frontend/web/js/magic-buy-now.js index 2c37c710..d4d3f77f 100644 --- a/view/frontend/web/js/magic-buy-now.js +++ b/view/frontend/web/js/magic-buy-now.js @@ -1,265 +1,264 @@ define([ - 'jquery', - 'mage/translate', - 'Magento_Ui/js/modal/alert', - 'Magento_Checkout/js/model/full-screen-loader', - 'mage/url', - 'Razorpay_Magento/js/analytics', - 'underscore', - 'mage/cookies' + "jquery", + "mage/translate", + "Magento_Ui/js/modal/alert", + "Magento_Checkout/js/model/full-screen-loader", + "mage/url", + "Razorpay_Magento/js/analytics", + "underscore", + "mage/cookies", ], function ($, $t, alert, fullScreenLoader, url, analytics, _) { - "use strict"; - - $.widget('pmclain.oneClickButton', { - options: { - addToFormSelector: '#product_addtocart_form', - actionSelector: '.actions', - buttonTemplateSelector: '#occ-template', - buttonSelector: '#product-oneclick-button', - confirmationSelector: '#one-click-confirmation', - spinnerId: 'magic-razorpay-spinner' + "use strict"; + + $.widget("pmclain.oneClickButton", { + options: { + addToFormSelector: "#product_addtocart_form", + actionSelector: ".actions", + buttonTemplateSelector: "#occ-template", + buttonSelector: "#product-oneclick-button", + confirmationSelector: "#one-click-confirmation", + spinnerId: "magic-razorpay-spinner", + }, + + cookie: "occ_status", + cookieEnabled: "enabled", + cookieDisabled: "disabled", + + _create: function () { + this._initButton(); + }, + + _initButton: function () { + var self = this; + + switch ($.mage.cookies.get(this.cookie)) { + case this.cookieEnabled: + this._createButton(); + break; + case this.cookieDisabled: + break; + default: + self._createButton(); + } + }, + + initObservable: function () { + var self = this._super(); //Resolves UI Error on Checkout + + $.getScript( + "https://checkout.razorpay.com/v1/magic-checkout.js", + function () { + self.razorpayDataFrameLoaded = true; }, - - cookie: 'occ_status', - cookieEnabled: 'enabled', - cookieDisabled: 'disabled', - - _create: function () { - this._initButton(); + ); + + return self; + }, + + _createButton: function () { + var button = $(this.options.buttonTemplateSelector).html(); + this._parent().find(this.options.actionSelector).prepend(button); + this._bind(); + }, + + _bind: function () { + var self = this; + this._parent() + .find(self.options.buttonSelector) + .on("click touch", function () { + if (self._parent().valid()) { + self._buyNow(); + } + }); + }, + + _parent: function () { + return $(this.options.addToFormSelector); + }, + + _buyNow: function () { + var self = this; + self._disableButton(); + self.showRazorpayLoader(true); + + var placeOrder = url.build("razorpay/oneclick/placeorder", {}); + + $.ajax({ + url: placeOrder, + data: self._parent().serialize(), + type: "POST", + dataType: "json", + success: function (data) { + self.renderIframe(data); }, - - _initButton: function () { - var self = this; - - switch ($.mage.cookies.get(this.cookie)) { - case this.cookieEnabled: - this._createButton(); - break; - case this.cookieDisabled: - break; - default: - self._createButton(); - } + error: function (request) { + self._orderError(request); + self.enableButton(); }, - - initObservable: function() { - var self = this._super(); //Resolves UI Error on Checkout - - $.getScript("https://checkout.razorpay.com/v1/magic-checkout.js", function() { - self.razorpayDataFrameLoaded = true; + }); + }, + + orderSuccess: function (data) { + var self = this; + self.enableButton(); + fullScreenLoader.startLoader(); + + var completeOrder = url.build("razorpay/oneclick/completeorder", {}); + + $.ajax({ + url: completeOrder, + data: data, + type: "POST", + dataType: "json", + success: function (data) { + self.toggleLoader(true); + + if (analytics.MagicMxAnalytics.purchase) { + analytics.MagicMxAnalytics.purchase({ + ...data, + merchantAnalyticsConfigs: {}, + }).finally(() => { + continueRedirection(); }); - - return self; + } else { + continueRedirection(); + } + + function continueRedirection() { + var successUrl = url.build("checkout/onepage/success", {}); + window.location.href = successUrl; + } }, - - _createButton: function () { - var button = $(this.options.buttonTemplateSelector).html(); - this._parent().find(this.options.actionSelector).prepend(button); - this._bind(); + error: function (error) { + console.log("Payment complete fail"); + console.log(error); }, - - _bind: function () { - var self = this; - this._parent().find(self.options.buttonSelector).on('click touch', function() { - if (self._parent().valid()) { - self._buyNow(); - } - }); + }); + }, + + abandonedCart: function (rzp_order_id) { + var self = this; + + var abandonedQuote = url.build("razorpay/oneclick/abandonedQuote", {}); + $.ajax({ + url: abandonedQuote, + data: { rzp_order_id: rzp_order_id }, + type: "POST", + dataType: "json", + success: function (data) { + console.log(data); }, - - _parent: function () { - return $(this.options.addToFormSelector); + error: function (error) { + console.log("Payment complete fail"); + console.log(error); }, - - _buyNow: function () { - var self = this; - self._disableButton(); - self.toggleLoader(true); - - var placeOrder = url.build('razorpay/oneclick/placeorder', {}) - - $.ajax({ - url: placeOrder, - data: self._parent().serialize(), - type: 'POST', - dataType: 'json', - success: function (data) { - self.renderIframe(data); - }, - error: function (request) { - self._orderError(request); - self.enableButton(); - } - }) + }); + }, + + renderIframe: function (data) { + var self = this; + var rzp_order_id = data.rzp_order_id; + + var options = { + key: data.rzp_key_id, + name: "", + amount: data.totalAmount, + one_click_checkout: true, + show_coupons: data.allow_coupon_application, + handler: function (data) { + self.showLoader(true); + self.orderSuccess(data); }, - - orderSuccess: function (data) { - var self = this; + order_id: data.rzp_order_id, + modal: { + ondismiss: function (data) { + //reset the cart + // self.resetCart(data); + // fullScreenLoader.stopLoader(); + // self.isPaymentProcessing.reject("Payment Closed"); + // self.isPlaceOrderActionAllowed(true); + self.abandonedCart(rzp_order_id); self.enableButton(); - fullScreenLoader.startLoader(); - - var completeOrder = url.build('razorpay/oneclick/completeorder', {}) - - $.ajax({ - url: completeOrder, - data: data, - type: 'POST', - dataType: 'json', - success: function (data) { - self.toggleLoader(true); - - if (analytics.MagicMxAnalytics.purchase) { - analytics.MagicMxAnalytics.purchase({ - ...data, - merchantAnalyticsConfigs: {}, - }).finally(() => { - continueRedirection(); - }) - } else { - continueRedirection(); - } - - function continueRedirection(){ - var successUrl = url.build('checkout/onepage/success', {}) - window.location.href = successUrl; - } - - }, - error: function (error) { - console.log("Payment complete fail") - console.log(error) - } - }) - }, - - abandonedCart: function (rzp_order_id) { - var self = this; - - var abandonedQuote = url.build('razorpay/oneclick/abandonedQuote', {}) - $.ajax({ - url: abandonedQuote, - data: {'rzp_order_id': rzp_order_id }, - type: 'POST', - dataType: 'json', - success: function (data) { - console.log(data) - }, - error: function (error) { - console.log("Payment complete fail") - console.log(error) - } - }) + }, }, - - renderIframe: function(data) { - var self = this; - var rzp_order_id = data.rzp_order_id; - - var options = { - key: data.rzp_key_id, - name: '', - amount: data.totalAmount, - one_click_checkout: true, - show_coupons: data.allow_coupon_application, - handler: function (data) { - self.toggleLoader(true); - self.orderSuccess(data); - }, - order_id: data.rzp_order_id, - modal: { - ondismiss: function(data) { - //reset the cart - // self.resetCart(data); - // fullScreenLoader.stopLoader(); - // self.isPaymentProcessing.reject("Payment Closed"); - // self.isPlaceOrderActionAllowed(true); - self.abandonedCart(rzp_order_id); - self.enableButton(); - - } - }, - notes: { - }, - // callback_url : self.options.callbackURL, - prefill: { - name: '', - contact: '', - email: '' - }, - _: { - integration: 'magento', - // integration_version: '', - // integration_parent_version: data.maze_version, - integration_type: 'plugin', - } - }; - - // if (data.quote_currency !== 'INR') - // { - // options.display_currency = data.quote_currency; - // options.display_amount = data.quote_amount; - // } - - this.rzp = new Razorpay(options); - - this.rzp.on('mx-analytics', eventData => { - console.log(analytics.MagicMxAnalytics); - console.log("mx-analytics data", eventData); - const enabledAnalyticsTools = { - ga4: window.gtag, - }; - - analytics.MagicMxAnalytics?.[eventData.event]?.( - { - ...eventData, - }, - data, - enabledAnalyticsTools - ); - }); - self.toggleLoader(false); - - this.rzp.open(); - }, - - _orderError: function (request) { - console.log(request); - this.enableButton(); - }, - - _disableButton: function () { - var button = this._parent().find(this.options.buttonSelector); - button.addClass('disabled'); - }, - - enableButton: function () { - var button = this._parent().find(this.options.buttonSelector); - button.removeClass('disabled'); - }, - - hide: function() { - document.getElementById(this.options.spinnerId)?.remove(); - // unblockPageScroll(); + notes: {}, + // callback_url : self.options.callbackURL, + prefill: { + name: "", + contact: "", + email: "", }, - - show: function() { - if (typeof (window.Razorpay)?.showLoader === 'function') { - (window.Razorpay).showLoader?.(); - } else { - if (this.isVisible()) { - return; - } - document.body.appendChild(this.createTemplate(this.options.spinnerId)); - } - // blockPageScroll(); + _: { + integration: "magento", + // integration_version: '', + // integration_parent_version: data.maze_version, + integration_type: "plugin", }, - - isVisible: function() { - return document.getElementById(this.options.spinnerId) !== null; - }, - - createTemplate: function(id) { - const templateStr = ` + }; + + // if (data.quote_currency !== 'INR') + // { + // options.display_currency = data.quote_currency; + // options.display_amount = data.quote_amount; + // } + + this.rzp = new Razorpay(options); + + this.rzp.on("mx-analytics", (eventData) => { + console.log(analytics.MagicMxAnalytics); + console.log("mx-analytics data", eventData); + const enabledAnalyticsTools = { + ga4: window.gtag, + }; + + analytics.MagicMxAnalytics?.[eventData.event]?.( + { + ...eventData, + }, + data, + enabledAnalyticsTools, + ); + }); + self.toggleLoader(false); + + this.rzp.open(); + }, + + _orderError: function (request) { + console.log(request); + this.enableButton(); + }, + + _disableButton: function () { + var button = this._parent().find(this.options.buttonSelector); + button.addClass("disabled"); + }, + + enableButton: function () { + var button = this._parent().find(this.options.buttonSelector); + button.removeClass("disabled"); + }, + + hide: function () { + document.getElementById(this.options.spinnerId)?.remove(); + // unblockPageScroll(); + }, + + show: function () { + if (this.isVisible()) { + return; + } + document.body.appendChild(this.createTemplate(this.options.spinnerId)); + + // blockPageScroll(); + }, + + isVisible: function () { + return document.getElementById(this.options.spinnerId) !== null; + }, + + createTemplate: function (id) { + const templateStr = `
`; - return document.createRange().createContextualFragment(templateStr); - }, + return document.createRange().createContextualFragment(templateStr); + }, - toggleLoader: function(flag) { - var self = this; + toggleLoader: function (flag) { + var self = this; - flag ? self.show() : self.hide(); - } - }); + flag ? self.show() : self.hide(); + }, + showRazorpayLoader: function () { + if (typeof window.Razorpay?.showLoader === "function") { + window.Razorpay.showLoader?.(); + } + }, + }); - return $.pmclain.oneClickButton; -}); \ No newline at end of file + return $.pmclain.oneClickButton; +}); diff --git a/view/frontend/web/js/magic-cart.js b/view/frontend/web/js/magic-cart.js index 4e3572ed..9f773864 100644 --- a/view/frontend/web/js/magic-cart.js +++ b/view/frontend/web/js/magic-cart.js @@ -1,263 +1,261 @@ define([ - 'jquery', - 'mage/translate', - 'Magento_Ui/js/modal/alert', - 'Magento_Checkout/js/model/full-screen-loader', - 'mage/url', - 'Razorpay_Magento/js/analytics', - 'underscore', - 'mage/cookies' + "jquery", + "mage/translate", + "Magento_Ui/js/modal/alert", + "Magento_Checkout/js/model/full-screen-loader", + "mage/url", + "Razorpay_Magento/js/analytics", + "underscore", + "mage/cookies", ], function ($, $t, alert, fullScreenLoader, url, analytics, _) { - "use strict"; - - $.widget('pmclain.oneClickButton', { - options: { - addToFormSelector: '#cart-occ-div', - actionSelector: '.action', - buttonTemplateSelector: '#cart-occ-div', - buttonSelector: '#cart-occ-template', - confirmationSelector: '#one-click-confirmation', - spinnerId: 'magic-razorpay-spinner' + "use strict"; + + $.widget("pmclain.oneClickButton", { + options: { + addToFormSelector: "#cart-occ-div", + actionSelector: ".action", + buttonTemplateSelector: "#cart-occ-div", + buttonSelector: "#cart-occ-template", + confirmationSelector: "#one-click-confirmation", + spinnerId: "magic-razorpay-spinner", + }, + + cookie: "occ_status", + cookieEnabled: "enabled", + cookieDisabled: "disabled", + + _create: function () { + this._initButton(); + }, + + _initButton: function () { + var self = this; + + switch ($.mage.cookies.get(this.cookie)) { + case this.cookieEnabled: + this._createButton(); + break; + case this.cookieDisabled: + break; + default: + self._createButton(); + } + }, + + initObservable: function () { + var self = this._super(); //Resolves UI Error on Checkout + + $.getScript( + "https://checkout.razorpay.com/v1/magic-checkout.js", + function () { + self.razorpayDataFrameLoaded = true; }, - - cookie: 'occ_status', - cookieEnabled: 'enabled', - cookieDisabled: 'disabled', - - _create: function () { - this._initButton(); + ); + + return self; + }, + + _createButton: function () { + var button = $(this.options.buttonTemplateSelector).html(); + this._bind(); + }, + + _bind: function () { + var self = this; + console.log(self.options.buttonSelector); + this._parent() + .find(self.options.buttonSelector) + .on("click touch", function () { + // if (self._parent().valid()) { + self._cartCheckout(); + // } + }); + }, + + _parent: function () { + return $(this.options.addToFormSelector); + }, + + _cartCheckout: function () { + var self = this; + self._disableButton(); + self.showRazorpayLoader(true); + + var placeOrder = url.build("razorpay/oneclick/placeorder", {}); + $.ajax({ + url: placeOrder, + data: { page: "cart" }, + type: "POST", + dataType: "json", + success: function (data) { + self.renderIframe(data); }, - - _initButton: function () { - var self = this; - - switch ($.mage.cookies.get(this.cookie)) { - case this.cookieEnabled: - this._createButton(); - break; - case this.cookieDisabled: - break; - default: - self._createButton(); - } + error: function (request) { + self.toggleLoader(false); + self._orderError(request); + self.enableButton(); }, - - initObservable: function() { - var self = this._super(); //Resolves UI Error on Checkout - - $.getScript("https://checkout.razorpay.com/v1/magic-checkout.js", function() { - self.razorpayDataFrameLoaded = true; + }); + }, + + orderSuccess: function (data) { + var self = this; + self.enableButton(); + + var completeOrder = url.build("razorpay/oneclick/completeorder", {}); + $.ajax({ + url: completeOrder, + data: data, + type: "POST", + dataType: "json", + success: function (data) { + self.toggleLoader(true); + + if (analytics.MagicMxAnalytics.purchase) { + analytics.MagicMxAnalytics.purchase({ + ...data, + merchantAnalyticsConfigs: {}, + }).finally(() => { + continueRedirection(); }); - - return self; + } else { + continueRedirection(); + } + + function continueRedirection() { + var successUrl = url.build("checkout/onepage/success", {}); + window.location.href = successUrl; + } }, - - _createButton: function () { - var button = $(this.options.buttonTemplateSelector).html(); - this._bind(); + error: function (error) { + self.toggleLoader(false); + console.log("Payment complete fail"); + var failureUrl = url.build("checkout/onepage/failure", {}); + window.location.href = failureUrl; }, - - _bind: function () { - var self = this; - console.log(self.options.buttonSelector) - this._parent().find(self.options.buttonSelector).on('click touch', function() { - // if (self._parent().valid()) { - self._cartCheckout(); - // } - }); + }); + }, + + abandonedCart: function (rzp_order_id) { + var self = this; + + var abandonedQuote = url.build("razorpay/oneclick/abandonedQuote", {}); + $.ajax({ + url: abandonedQuote, + data: { rzp_order_id: rzp_order_id }, + type: "POST", + dataType: "json", + success: function (data) { + console.log(data); }, - - _parent: function () { - return $(this.options.addToFormSelector); + error: function (error) { + console.log("Payment complete fail"); + console.log(error); }, - - _cartCheckout: function () { - var self = this; - self._disableButton(); - self.toggleLoader(true); - - var placeOrder = url.build('razorpay/oneclick/placeorder', {}) - $.ajax({ - url: placeOrder, - data: { 'page' : 'cart'}, - type: 'POST', - dataType: 'json', - success: function (data) { - self.renderIframe(data); - }, - error: function (request) { - self.toggleLoader(false); - self._orderError(request); - self.enableButton(); - } - }) + }); + }, + + renderIframe: function (data) { + var self = this; + var rzp_order_id = data.rzp_order_id; + + var options = { + key: data.rzp_key_id, + name: "", + amount: data.totalAmount, + one_click_checkout: true, + show_coupons: data.allow_coupon_application, + handler: function (data) { + console.log("data in handler", data); + self.showLoader(true); + self.orderSuccess(data); }, - - orderSuccess: function (data) { - var self = this; + order_id: data.rzp_order_id, + modal: { + ondismiss: function (data) { + self.abandonedCart(rzp_order_id); self.enableButton(); - var completeOrder = url.build('razorpay/oneclick/completeorder', {}) - $.ajax({ - url: completeOrder, - data: data, - type: 'POST', - dataType: 'json', - success: function (data) { - self.toggleLoader(true); - - if (analytics.MagicMxAnalytics.purchase) { - analytics.MagicMxAnalytics.purchase({ - ...data, - merchantAnalyticsConfigs: {}, - }).finally(() => { - continueRedirection(); - }) - } else { - continueRedirection(); - } - - function continueRedirection(){ - var successUrl = url.build('checkout/onepage/success', {}) - window.location.href = successUrl; - } - - }, - error: function (error) { - self.toggleLoader(false); - console.log("Payment complete fail") - var failureUrl = url.build('checkout/onepage/failure', {}) - window.location.href = failureUrl; - } - }) - }, - - abandonedCart: function (rzp_order_id) { - var self = this; - - var abandonedQuote = url.build('razorpay/oneclick/abandonedQuote', {}) - $.ajax({ - url: abandonedQuote, - data: {'rzp_order_id': rzp_order_id }, - type: 'POST', - dataType: 'json', - success: function (data) { - console.log(data) - - }, - error: function (error) { - console.log("Payment complete fail") - console.log(error) - } - }) - }, - - renderIframe: function(data) { - var self = this; - var rzp_order_id = data.rzp_order_id; - - var options = { - key: data.rzp_key_id, - name: '', - amount: data.totalAmount, - one_click_checkout: true, - show_coupons: data.allow_coupon_application, - handler: function (data) { - - console.log("data in handler", data) - self.toggleLoader(true); - self.orderSuccess(data); - }, - order_id: data.rzp_order_id, - modal: { - ondismiss: function (data) { - self.abandonedCart(rzp_order_id); - self.enableButton(); - - //reset the cart - // self.resetCart(data); - // fullScreenLoader.stopLoader(); - // self.isPaymentProcessing.reject("Payment Closed"); - // self.isPlaceOrderActionAllowed(true); - } - }, - notes: {}, - // callback_url : self.options.callbackURL, - prefill: { - name: '', - contact: '', - email: '' - }, - _: { - integration: 'magento', - // integration_version: '', - // integration_parent_version: data.maze_version, - integration_type: 'plugin', - } - }; - - // if (data.quote_currency !== 'INR') - // { - // options.display_currency = data.quote_currency; - // options.display_amount = data.quote_amount; - // } - - - this.rzp = new Razorpay(options); - this.rzp.on('mx-analytics', eventData => { - const enabledAnalyticsTools = { - ga4: window.gtag, - }; - - analytics.MagicMxAnalytics?.[eventData.event]?.( - { - ...eventData, - }, - data, - enabledAnalyticsTools - ); - }); - self.toggleLoader(false); - this.rzp.open(); + //reset the cart + // self.resetCart(data); + // fullScreenLoader.stopLoader(); + // self.isPaymentProcessing.reject("Payment Closed"); + // self.isPlaceOrderActionAllowed(true); + }, }, - - _orderError: function (request) { - this.enableButton(); + notes: {}, + // callback_url : self.options.callbackURL, + prefill: { + name: "", + contact: "", + email: "", }, - - _disableButton: function () { - var button = this._parent().find(this.options.buttonTemplateSelector); - button.addClass('disabled'); - }, - - enableButton: function () { - var button = this._parent().find(this.options.buttonTemplateSelector); - button.removeClass('disabled'); + _: { + integration: "magento", + // integration_version: '', + // integration_parent_version: data.maze_version, + integration_type: "plugin", }, - - hide: function() { - document.getElementById(this.options.spinnerId)?.remove(); - // unblockPageScroll(); - }, - - show: function() { - if (typeof (window.Razorpay)?.showLoader === 'function') { - (window.Razorpay).showLoader?.(); - } else { - if (this.isVisible()) { - return; - } - document.body.appendChild(this.createTemplate(this.options.spinnerId)); - } - // blockPageScroll(); - }, - - isVisible: function() { - return document.getElementById(this.options.spinnerId) !== null; - }, - - createTemplate: function(id) { - const templateStr = ` + }; + + // if (data.quote_currency !== 'INR') + // { + // options.display_currency = data.quote_currency; + // options.display_amount = data.quote_amount; + // } + + this.rzp = new Razorpay(options); + this.rzp.on("mx-analytics", (eventData) => { + const enabledAnalyticsTools = { + ga4: window.gtag, + }; + + analytics.MagicMxAnalytics?.[eventData.event]?.( + { + ...eventData, + }, + data, + enabledAnalyticsTools, + ); + }); + self.toggleLoader(false); + this.rzp.open(); + }, + + _orderError: function (request) { + this.enableButton(); + }, + + _disableButton: function () { + var button = this._parent().find(this.options.buttonTemplateSelector); + button.addClass("disabled"); + }, + + enableButton: function () { + var button = this._parent().find(this.options.buttonTemplateSelector); + button.removeClass("disabled"); + }, + + hide: function () { + document.getElementById(this.options.spinnerId)?.remove(); + // unblockPageScroll(); + }, + + show: function () { + if (this.isVisible()) { + return; + } + document.body.appendChild(this.createTemplate(this.options.spinnerId)); + + // blockPageScroll(); + }, + + isVisible: function () { + return document.getElementById(this.options.spinnerId) !== null; + }, + + createTemplate: function (id) { + const templateStr = `
`; - return document.createRange().createContextualFragment(templateStr); - }, + return document.createRange().createContextualFragment(templateStr); + }, - toggleLoader: function(flag) { - var self = this; + toggleLoader: function (flag) { + var self = this; - flag ? self.show() : self.hide(); - } - }); + flag ? self.show() : self.hide(); + }, + showRazorpayLoader: function () { + if (typeof window.Razorpay?.showLoader === "function") { + window.Razorpay.showLoader?.(); + } + }, + }); - return $.pmclain.oneClickButton; -}); \ No newline at end of file + return $.pmclain.oneClickButton; +}); From 51211939fd238dbd71956d8293557a6e525128dd Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Fri, 13 Dec 2024 17:10:03 +0530 Subject: [PATCH 58/67] Loader fix --- view/frontend/web/js/magic-buy-now.js | 2 +- view/frontend/web/js/magic-cart.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/view/frontend/web/js/magic-buy-now.js b/view/frontend/web/js/magic-buy-now.js index d4d3f77f..bbf5bdaf 100644 --- a/view/frontend/web/js/magic-buy-now.js +++ b/view/frontend/web/js/magic-buy-now.js @@ -166,7 +166,7 @@ define([ one_click_checkout: true, show_coupons: data.allow_coupon_application, handler: function (data) { - self.showLoader(true); + self.toggleLoader(true); self.orderSuccess(data); }, order_id: data.rzp_order_id, diff --git a/view/frontend/web/js/magic-cart.js b/view/frontend/web/js/magic-cart.js index 9f773864..b57f1598 100644 --- a/view/frontend/web/js/magic-cart.js +++ b/view/frontend/web/js/magic-cart.js @@ -167,7 +167,7 @@ define([ show_coupons: data.allow_coupon_application, handler: function (data) { console.log("data in handler", data); - self.showLoader(true); + self.toggleLoader(true); self.orderSuccess(data); }, order_id: data.rzp_order_id, From 549eaf4fbc258c4816ced6ed671f3b93b0034565 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Tue, 17 Dec 2024 12:03:57 +0530 Subject: [PATCH 59/67] Bug fix for incomplete name of customer in order --- Controller/OneClick/AbandonedQuote.php | 10 ++++++++-- Controller/OneClick/CompleteOrder.php | 10 ++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Controller/OneClick/AbandonedQuote.php b/Controller/OneClick/AbandonedQuote.php index 94beb03c..30c91248 100644 --- a/Controller/OneClick/AbandonedQuote.php +++ b/Controller/OneClick/AbandonedQuote.php @@ -285,14 +285,20 @@ protected function getAddress($rzpAddress, $regionCode, $email) $name = explode(' ', $trimmedName); + // Extract the first word as the first name + $firstName = $name[0]; + + // Combine the rest of the words as the last name + $lastName = implode(' ', array_slice($name, 1)); + $streetRzp = $rzpAddress->line1 . ', ' . $rzpAddress->line2; $street = substr($streetRzp, 0, 255); return [ 'email' => $email, //buyer email id 'address' => [ - 'firstname' => $name[0], //address Details - 'lastname' => empty($name[1]) === false ? $name[1] : '.', + 'firstname' => $firstName, //address Details + 'lastname' => empty($lastName) === false ? $lastName : '.', 'street' => $street, 'city' => $rzpAddress->city, 'country_id' => strtoupper($rzpAddress->country), diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index d32f6ee7..a44c0db8 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -697,14 +697,20 @@ protected function getAddress($rzpAddress, $regionCode, $email) $name = explode(' ', $trimmedName); + // Extract the first word as the first name + $firstName = $name[0]; + + // Combine the rest of the words as the last name + $lastName = implode(' ', array_slice($name, 1)); + $streetRzp = $rzpAddress->line1 . ', ' . $rzpAddress->line2; $street = substr($streetRzp, 0, 255); return [ 'email' => $email, //buyer email id 'address' => [ - 'firstname' => $name[0], //address Details - 'lastname' => empty($name[1]) === false ? $name[1] : '.', + 'firstname' => $firstName, //address Details + 'lastname' => empty($lastName) === false ? $lastName : '.', 'street' => $street, 'city' => $rzpAddress->city, 'country_id' => strtoupper($rzpAddress->country), From ced2d14759994affcfd9cfd74912685c479c6290 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Tue, 17 Dec 2024 15:09:46 +0530 Subject: [PATCH 60/67] Bug fix for address line 2 error --- Controller/OneClick/AbandonedQuote.php | 20 +++++++++-- Controller/OneClick/CompleteOrder.php | 48 +++++++++++++++++--------- 2 files changed, 48 insertions(+), 20 deletions(-) diff --git a/Controller/OneClick/AbandonedQuote.php b/Controller/OneClick/AbandonedQuote.php index 30c91248..6991a5a0 100644 --- a/Controller/OneClick/AbandonedQuote.php +++ b/Controller/OneClick/AbandonedQuote.php @@ -142,7 +142,12 @@ public function execute() //In case customer address not completely added to order details, we will set the address details in order comments. $shippingRZPAddress = $rzpOrderData->customer_details->shipping_address; - $shippingStreetRzp = $shippingRZPAddress->line1 . ', ' . $shippingRZPAddress->line2; + + if (isset($shippingRZPAddress->line2)) { + $shippingStreetRzp = $shippingRZPAddress->line1 . ', ' . $shippingRZPAddress->line2; + } else { + $shippingStreetRzp = $shippingRZPAddress->line1; + } if (strlen($shippingStreetRzp) > 255) { $shippingAddress = 'Customer Complete Shipping Address - '. $shippingRZPAddress->name. ', '. @@ -156,8 +161,12 @@ public function execute() } $billingRZPAddress = $rzpOrderData->customer_details->billing_address; - $billingStreetRzp = $billingRZPAddress->line1 . ', ' . $billingRZPAddress->line2; + if (isset($billingRZPAddress->line2)) { + $billingStreetRzp = $billingRZPAddress->line1 . ', ' . $billingRZPAddress->line2; + } else { + $billingStreetRzp = $billingRZPAddress->line1; + } if (strlen($billingStreetRzp) > 255) { $billingAddress = 'Customer Complete Billing Address - '. $billingRZPAddress->name. ', '. $billingStreetRzp. ', '. @@ -291,7 +300,12 @@ protected function getAddress($rzpAddress, $regionCode, $email) // Combine the rest of the words as the last name $lastName = implode(' ', array_slice($name, 1)); - $streetRzp = $rzpAddress->line1 . ', ' . $rzpAddress->line2; + if (isset($rzpAddress->line2)) { + $streetRzp = $rzpAddress->line1 . ', ' . $rzpAddress->line2; + } else { + $streetRzp = $rzpAddress->line1; + } + $street = substr($streetRzp, 0, 255); return [ diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index a44c0db8..206b2793 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -292,12 +292,12 @@ public function placeMagentoOrder($cartId, $rzpPaymentData, $rzpOrderData) } break; } catch (\Exception $e) { - $this->logger->critical("Magento order placement is failed for ".$rzpOrderId." in ".$attempts." attempt and the error message is - " . $e->getMessage()); + $this->logger->critical("Magento order placement is failed for " . $rzpOrderId . " in " . $attempts . " attempt and the error message is - " . $e->getMessage()); if ($attempts == self::MAX_ATTEMPTS) { - $this->logger->critical("All attempts to place the Magento order have failed for rzp order id ".$rzpOrderId." & rzp payment id ".$rzpPaymentId." & magento cart id ".$cartId); + $this->logger->critical("All attempts to place the Magento order have failed for rzp order id " . $rzpOrderId . " & rzp payment id " . $rzpPaymentId . " & magento cart id " . $cartId); - throw new \Exception("Magento order creation failed with error message.". $e->getMessage()); + throw new \Exception("Magento order creation failed with error message." . $e->getMessage()); } continue; } @@ -321,7 +321,7 @@ public function placeMagentoOrder($cartId, $rzpPaymentData, $rzpOrderData) ->setStatus(static::STATE_PROCESSING); } - $this->logger->info('graphQL: Order Status Updated to ' . $this->orderStatus ." for order id ".$rzpOrderId); + $this->logger->info('graphQL: Order Status Updated to ' . $this->orderStatus . " for order id " . $rzpOrderId); } if (!empty($rzpOrderData->offers)) { @@ -475,13 +475,18 @@ public function placeMagentoOrder($cartId, $rzpPaymentData, $rzpOrderData) //In case customer address not completely added to order details, we will set the address details in order comments. $shippingRZPAddress = $rzpOrderData->customer_details->shipping_address; - $shippingStreetRzp = $shippingRZPAddress->line1 . ', ' . $shippingRZPAddress->line2; + + if (isset($shippingRZPAddress->line2)) { + $shippingStreetRzp = $shippingRZPAddress->line1 . ', ' . $shippingRZPAddress->line2; + } else { + $shippingStreetRzp = $shippingRZPAddress->line1; + } if (strlen($shippingStreetRzp) > 255) { - $shippingAddress = 'Customer Complete Shipping Address - '. $shippingRZPAddress->name. ', '. - $shippingStreetRzp. ', '. - $shippingRZPAddress->city. ', '. - strtoupper($shippingRZPAddress->country). ' - '. + $shippingAddress = 'Customer Complete Shipping Address - ' . $shippingRZPAddress->name . ', ' . + $shippingStreetRzp . ', ' . + $shippingRZPAddress->city . ', ' . + strtoupper($shippingRZPAddress->country) . ' - ' . $shippingRZPAddress->zipcode; $order->addStatusHistoryComment( $shippingAddress @@ -489,13 +494,17 @@ public function placeMagentoOrder($cartId, $rzpPaymentData, $rzpOrderData) } $billingRZPAddress = $rzpOrderData->customer_details->billing_address; - $billingStreetRzp = $billingRZPAddress->line1 . ', ' . $billingRZPAddress->line2; + if (isset($billingRZPAddress->line2)) { + $billingStreetRzp = $billingRZPAddress->line1 . ', ' . $billingRZPAddress->line2; + } else { + $billingStreetRzp = $billingRZPAddress->line1; + } if (strlen($billingStreetRzp) > 255) { - $billingAddress = 'Customer Complete Billing Address - '. $billingRZPAddress->name. ', '. - $billingStreetRzp. ', '. - $billingRZPAddress->city. ', '. - strtoupper($billingRZPAddress->country). ' - '. + $billingAddress = 'Customer Complete Billing Address - ' . $billingRZPAddress->name . ', ' . + $billingStreetRzp . ', ' . + $billingRZPAddress->city . ', ' . + strtoupper($billingRZPAddress->country) . ' - ' . $billingRZPAddress->zipcode; $order->addStatusHistoryComment( $billingAddress @@ -618,7 +627,7 @@ protected function updateQuote($quote, $rzpOrderData, $rzpPaymentData) //This change is to support email less checkout. $email = $quote->getCustomerEmail(); - if($email == null) { + if ($email == null) { $email = $rzpOrderData->customer_details->email ?? ''; } $quote->setCustomerEmail($email); @@ -703,7 +712,12 @@ protected function getAddress($rzpAddress, $regionCode, $email) // Combine the rest of the words as the last name $lastName = implode(' ', array_slice($name, 1)); - $streetRzp = $rzpAddress->line1 . ', ' . $rzpAddress->line2; + if (isset($rzpAddress->line2)) { + $streetRzp = $rzpAddress->line1 . ', ' . $rzpAddress->line2; + } else { + $streetRzp = $rzpAddress->line1; + } + $street = substr($streetRzp, 0, 255); return [ @@ -727,7 +741,7 @@ protected function validateSignature($request, $cartMaskId) if (empty($request['error']) === false) { $this->logger->critical("Validate: Payment Failed or error from gateway" . $request['razorpay_order_id']); $this->messageManager->addError(__('Payment Failed')); - throw new \Exception("Payment Failed or error from gateway for ". $request['razorpay_order_id']); + throw new \Exception("Payment Failed or error from gateway for " . $request['razorpay_order_id']); } $catalogRzpKey = static::QUOTE_LINKED_RAZORPAY_ORDER_ID . '_' . $cartMaskId; From b09bde140261174a92753fd0c2e423ddb0b3f634 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Tue, 17 Dec 2024 17:21:58 +0530 Subject: [PATCH 61/67] Bug fix for address id not found for logged in customer cart checkout --- Controller/OneClick/PlaceOrder.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Controller/OneClick/PlaceOrder.php b/Controller/OneClick/PlaceOrder.php index 4a4c06dc..ff9c4608 100644 --- a/Controller/OneClick/PlaceOrder.php +++ b/Controller/OneClick/PlaceOrder.php @@ -177,6 +177,11 @@ public function execute() $quote->save(); $connection->update($tableName, ['customer_id' => null, 'customer_is_guest' => 1], ['entity_id = ?' => $quoteId]); + + $tableQuoteAddressName = $this->resourceConnection->getTableName('quote_address'); + + $connection->update($tableQuoteAddressName, ['customer_id' => null, 'customer_address_id' => null], ['quote_id = ?' => $quoteId]); + } } else { /** @var QuoteBuilder $quoteBuilder */ From 21bfb9f98f76fdbc0476950e84ae691ae073c872 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Thu, 19 Dec 2024 20:36:33 +0530 Subject: [PATCH 62/67] Minicart handling in case magic is disabled --- view/frontend/layout/default.xml | 3 +++ view/frontend/templates/oneclick/buynow.phtml | 5 ----- .../templates/oneclick/magiccart.phtml | 5 ----- .../templates/oneclick/minicart.phtml | 22 +++++++++++++++++++ view/frontend/web/js/magic-cart.js | 10 +++++---- 5 files changed, 31 insertions(+), 14 deletions(-) create mode 100644 view/frontend/templates/oneclick/minicart.phtml diff --git a/view/frontend/layout/default.xml b/view/frontend/layout/default.xml index 124cda3e..7e428d67 100644 --- a/view/frontend/layout/default.xml +++ b/view/frontend/layout/default.xml @@ -24,6 +24,9 @@
+ + + diff --git a/view/frontend/templates/oneclick/buynow.phtml b/view/frontend/templates/oneclick/buynow.phtml index 5f95dba5..b18d01a4 100644 --- a/view/frontend/templates/oneclick/buynow.phtml +++ b/view/frontend/templates/oneclick/buynow.phtml @@ -1,10 +1,5 @@ get(\Razorpay\Magento\Model\Config::class); diff --git a/view/frontend/templates/oneclick/magiccart.phtml b/view/frontend/templates/oneclick/magiccart.phtml index 9360ca95..33f1c2e8 100644 --- a/view/frontend/templates/oneclick/magiccart.phtml +++ b/view/frontend/templates/oneclick/magiccart.phtml @@ -1,10 +1,5 @@ get(\Razorpay\Magento\Model\Config::class); diff --git a/view/frontend/templates/oneclick/minicart.phtml b/view/frontend/templates/oneclick/minicart.phtml new file mode 100644 index 00000000..d516ac1a --- /dev/null +++ b/view/frontend/templates/oneclick/minicart.phtml @@ -0,0 +1,22 @@ +get(\Razorpay\Magento\Model\Config::class); + +$isMagicEnabled = $configData->getMagicStatus(); + +?> + diff --git a/view/frontend/web/js/magic-cart.js b/view/frontend/web/js/magic-cart.js index b57f1598..7886ad75 100644 --- a/view/frontend/web/js/magic-cart.js +++ b/view/frontend/web/js/magic-cart.js @@ -62,13 +62,15 @@ define([ _bind: function () { var self = this; - console.log(self.options.buttonSelector); this._parent() .find(self.options.buttonSelector) .on("click touch", function () { - // if (self._parent().valid()) { - self._cartCheckout(); - // } + if(window.magicConfig.isMagicEnabled == true){ + self._cartCheckout(); + }else{ + var checkoutURL = url.build('checkout', {}) + window.location.href = checkoutURL; + } }); }, From c33883be43920fefa76db74391e916a465b93bb3 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Tue, 7 Jan 2025 11:17:16 +0530 Subject: [PATCH 63/67] Bug fix for cron job and status update --- Controller/OneClick/CompleteOrder.php | 9 ++++++--- Cron/UpdateOrdersToProcessingV2.php | 15 ++++++++++++--- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index 206b2793..5535711e 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -324,7 +324,8 @@ public function placeMagentoOrder($cartId, $rzpPaymentData, $rzpOrderData) $this->logger->info('graphQL: Order Status Updated to ' . $this->orderStatus . " for order id " . $rzpOrderId); } - if (!empty($rzpOrderData->offers)) { + //Check if any razorpay offer is applied or not + if (($rzpOrderData->amount !== $rzpOrderData->amount_paid) && $rzpPaymentData->method != 'cod') { $discountAmount = $order->getDiscountAmount(); $codFee = $rzpOrderData->cod_fee; @@ -340,7 +341,7 @@ public function placeMagentoOrder($cartId, $rzpPaymentData, $rzpOrderData) } } - $offerDiff = $rzpOrderData->line_items_total + $rzpOrderData->shipping_fee + $codFee - $totalPaid - $rzpPromotionAmount; + $offerDiff = $rzpOrderData->line_items_total + $rzpOrderData->shipping_fee - $totalPaid - $rzpPromotionAmount; if ($offerDiff > 0) { $offerDiscount = ($offerDiff / 100); @@ -430,13 +431,14 @@ public function placeMagentoOrder($cartId, $rzpPaymentData, $rzpOrderData) )->setIsCustomerNotified(true); $this->logger->info('Invoice generated for id : ' . $order->getIncrementId()); - $orderLink->setRzpUpdateOrderCronStatus(OrderCronStatus::INVOICE_GENERATED); } else if ($rzpOrderData->status === 'paid' and ($order->canInvoice() === false or $this->config->canAutoGenerateInvoice() === false)) { $this->logger->info('Invoice generation not possible for id : ' . $order->getIncrementId()); } + $orderLink->setRzpUpdateOrderCronStatus(OrderCronStatus::INVOICE_GENERATED); + $comment = __('Razorpay order id %1.', $rzpOrderId); $order->addStatusHistoryComment( @@ -591,6 +593,7 @@ public function getAppliedDiscounts($order) public function updateDiscountAmount($orderId, $newDiscountAmount, $offerAmount, $totalPaid) { + // TODO: Verify if total paid and order total is matching or not before updating the discount. try { // Load the order $order = $this->order->load($orderId); diff --git a/Cron/UpdateOrdersToProcessingV2.php b/Cron/UpdateOrdersToProcessingV2.php index b9e98137..ec7d6785 100644 --- a/Cron/UpdateOrdersToProcessingV2.php +++ b/Cron/UpdateOrdersToProcessingV2.php @@ -288,6 +288,14 @@ public function placeMagentoOrderthroughCron($cartId, $rzpPaymentData, $rzpOrder $orderId = $this->cartManagement->placeOrder($cartId); $order = $this->order->load($orderId); } else { + $payment = $order->getPayment(); + $paymentMethod = $payment->getMethod(); + + if(isset($paymentMethod)) { + $this->logger->critical("Cron failed to place the Magento order for rzp order id " . $rzpOrderId . " & rzp payment id " . $rzpPaymentId . " & magento cart id " . $cartId . " with error message - order was already placed" ); + + throw new \Exception("Magento order creation failed with error message - order was already placed"); + } $orderId = $order->getId(); } } catch (\Exception $e) { @@ -317,7 +325,8 @@ public function placeMagentoOrderthroughCron($cartId, $rzpPaymentData, $rzpOrder $this->logger->info('graphQL: Order Status Updated to ' . $this->orderStatus); } - if (!empty($rzpOrderData->offers)) { + //Check if any razorpay offer is applied or not + if (($rzpOrderData->amount !== $rzpOrderData->amount_paid) && $rzpPaymentData->method != 'cod') { $discountAmount = $order->getDiscountAmount(); $codFee = $rzpOrderData->cod_fee; @@ -333,7 +342,7 @@ public function placeMagentoOrderthroughCron($cartId, $rzpPaymentData, $rzpOrder } } - $offerDiff = $rzpOrderData->line_items_total + $rzpOrderData->shipping_fee + $codFee - $totalPaid - $rzpPromotionAmount; + $offerDiff = $rzpOrderData->line_items_total + $rzpOrderData->shipping_fee - $totalPaid - $rzpPromotionAmount; if ($offerDiff > 0) { $offerDiscount = ($offerDiff / 100); @@ -423,12 +432,12 @@ public function placeMagentoOrderthroughCron($cartId, $rzpPaymentData, $rzpOrder )->setIsCustomerNotified(true); $this->logger->info('Invoice generated for id : ' . $order->getIncrementId()); - $orderLink->setRzpUpdateOrderCronStatus(OrderCronStatus::INVOICE_GENERATED); } else if ($rzpOrderData->status === 'paid' and ($order->canInvoice() === false or $this->config->canAutoGenerateInvoice() === false)) { $this->logger->info('Invoice generation not possible for id : ' . $order->getIncrementId()); } + $orderLink->setRzpUpdateOrderCronStatus(OrderCronStatus::INVOICE_GENERATED); $comment = __('Razorpay order id %1.', $rzpOrderId); From 5b25048daffbd68f7d20fa9de75e0b5f5cb2b15c Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Wed, 12 Feb 2025 18:26:07 +0530 Subject: [PATCH 64/67] Handled cron fix --- Controller/OneClick/AbandonedQuote.php | 12 ++++++- Controller/OneClick/CompleteOrder.php | 2 -- Controller/OneClick/PlaceOrder.php | 4 +-- Cron/UpdateOrdersToProcessingV2.php | 44 +++++++++++++++++++++----- 4 files changed, 49 insertions(+), 13 deletions(-) diff --git a/Controller/OneClick/AbandonedQuote.php b/Controller/OneClick/AbandonedQuote.php index 6991a5a0..15aa2d5b 100644 --- a/Controller/OneClick/AbandonedQuote.php +++ b/Controller/OneClick/AbandonedQuote.php @@ -215,7 +215,7 @@ public function execute() } } - public function updateQuote($quote, $rzpOrderData) + public function updateQuote($quote, $rzpOrderData, $rzpPaymentData = array()) { $quote->setIsActive(true)->save(); @@ -259,6 +259,16 @@ public function updateQuote($quote, $rzpOrderData) } $paymentMethod = static::RAZORPAY; + if(empty($rzpPaymentData) === false) { + if ($rzpPaymentData->method === 'cod') { + $paymentMethod = static::COD; + // Set the custom fee in the quote + $codFee = $rzpOrderData->cod_fee ?? 0; + + $quote->setData('razorpay_cod_fee', $codFee); + } + } + $quote->setPaymentMethod($paymentMethod); $quote->setInventoryProcessed(false); // Set Sales Order Payment diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index 5535711e..a35d93c4 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -308,8 +308,6 @@ public function placeMagentoOrder($cartId, $rzpPaymentData, $rzpOrderData) // Return to failure page if payment is failed. if ($rzpPaymentData->status === 'failed') { $this->logger->critical("Razorpay payment is failed for the order id " . $rzpOrderId); - - throw new \Exception("Razorpay payment is failed for the order id " . $rzpOrderId); } if ($order->getStatus() === 'pending') { diff --git a/Controller/OneClick/PlaceOrder.php b/Controller/OneClick/PlaceOrder.php index ff9c4608..344fad02 100644 --- a/Controller/OneClick/PlaceOrder.php +++ b/Controller/OneClick/PlaceOrder.php @@ -275,8 +275,8 @@ public function execute() 'offer_price' => $offerPrice, 'tax_amount' => 0, 'quantity' => (int)$quoteItem->getQty(), - 'name' => $quoteItem->getName(), - 'description' => $quoteItem->getName(), + 'name' => substr($quoteItem->getName(), 0,125), + 'description' => substr($quoteItem->getName(), 0, 125), 'image_url' => $productImageUrl, 'product_url' => $productUrl, ]; diff --git a/Cron/UpdateOrdersToProcessingV2.php b/Cron/UpdateOrdersToProcessingV2.php index ec7d6785..461b03fc 100644 --- a/Cron/UpdateOrdersToProcessingV2.php +++ b/Cron/UpdateOrdersToProcessingV2.php @@ -217,7 +217,7 @@ public function execute() $this->debug->log("Cronjob: Razorpay Order data = " . json_encode($cartId)); $quote = $this->cartRepositoryInterface->get($cartId); - $this->quoteUpdate->updateQuote($quote, $razorpayOrderData); + $this->quoteUpdate->updateQuote($quote, $razorpayOrderData, $rzpPaymentData); $result = $this->placeMagentoOrderthroughCron($cartId, $rzpPaymentData, $razorpayOrderData); if ($result['status'] == 'success') { @@ -294,23 +294,54 @@ public function placeMagentoOrderthroughCron($cartId, $rzpPaymentData, $rzpOrder if(isset($paymentMethod)) { $this->logger->critical("Cron failed to place the Magento order for rzp order id " . $rzpOrderId . " & rzp payment id " . $rzpPaymentId . " & magento cart id " . $cartId . " with error message - order was already placed" ); - throw new \Exception("Magento order creation failed with error message - order was already placed"); + $result = [ + 'status' => 'failed', + 'message' => "Cron failed to place the Magento order for rzp order id " . $rzpOrderId . " & rzp payment id " . $rzpPaymentId . " & magento cart id " . $cartId . " with error message - order was already placed", + ]; + return $result; } $orderId = $order->getId(); } } catch (\Exception $e) { $this->logger->critical("Cron failed to place the Magento order for rzp order id " . $rzpOrderId . " & rzp payment id " . $rzpPaymentId . " & magento cart id " . $cartId . " with error message - " . $e->getMessage()); - - throw new \Exception("Magento order creation failed with error message." . $e->getMessage()); + $result = [ + 'status' => 'failed', + 'message' => "Cron failed to place the Magento order for rzp order id " . $rzpOrderId . " & rzp payment id " . $rzpPaymentId . " & magento cart id " . $cartId . " with error message - " . $e->getMessage(), + ]; + return $result; } $order->setEmailSent(0); if ($order) { // Return to failure page if payment is failed. if ($rzpPaymentData->status === 'failed') { + + $order->setState(static::STATE_PENDING_PAYMENT) + ->setStatus(static::STATE_PENDING_PAYMENT); + $order->save(); + $this->logger->critical("Razorpay payment is failed for the order id " . $rzpOrderId); - throw new \Exception("Razorpay payment is failed for the order id " . $rzpOrderId); + $result = [ + 'status' => 'failed', + 'message' => "Cron failed to place the Magento order for rzp order id " . $rzpOrderId . " & rzp payment id " . $rzpPaymentId . " & magento cart id " . $cartId . " with payment status - " . $rzpPaymentData->status, + ]; + return $result; + } + + if ($rzpPaymentData->status === 'refunded') { + + $order->setState(static::STATUS_CANCELED) + ->setStatus(static::STATUS_CANCELED); + $order->save(); + + $this->logger->critical("Razorpay payment is failed for the order id " . $rzpOrderId); + + $result = [ + 'status' => 'failed', + 'message' => "Cron failed to place the Magento order for rzp order id " . $rzpOrderId . " & rzp payment id " . $rzpPaymentId . " & magento cart id " . $cartId . " with payment status - " . $rzpPaymentData->status, + ]; + return $result; } if ($order->getStatus() === 'pending') { @@ -483,12 +514,9 @@ public function placeMagentoOrderthroughCron($cartId, $rzpPaymentData, $rzpOrder $this->logger->critical('graphQL: ' . 'Razorpay Error:' . $e->getMessage()); - throw new GraphQlInputException(__('Razorpay Error: %1.', $e->getMessage())); } catch (\Exception $e) { $this->logger->critical('graphQL: ' . 'Error:' . $e->getMessage()); - - throw new GraphQlInputException(__('Error: %1.', $e->getMessage())); } $this From 7c1a60a14b0043d2fd6ba15c03415e38cda98fee Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Fri, 14 Feb 2025 15:34:55 +0530 Subject: [PATCH 65/67] Bug fix for cart price rule discounts --- Controller/OneClick/PlaceOrder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Controller/OneClick/PlaceOrder.php b/Controller/OneClick/PlaceOrder.php index 344fad02..bdfd23d0 100644 --- a/Controller/OneClick/PlaceOrder.php +++ b/Controller/OneClick/PlaceOrder.php @@ -248,7 +248,7 @@ public function execute() // Check if the item has applied discounts if ($quoteItem->getDiscountAmount()) { // Get the discount amount applied to the item - $discountAmount = abs($quoteItem->getDiscountAmount()); + $discountAmount = abs($quoteItem->getDiscountAmount() / (int)$quoteItem->getQty()); $offerPrice = ($quoteItem->getPrice() - $discountAmount) * 100; } From 3cfcdcf2e5585ee05151e96d94eedc8a9e7e1d89 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Fri, 14 Feb 2025 15:44:01 +0530 Subject: [PATCH 66/67] Status update to sales table to handle stop cron job for stock unavailable products --- Constants/OrderCronStatus.php | 1 + Controller/OneClick/CompleteOrder.php | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/Constants/OrderCronStatus.php b/Constants/OrderCronStatus.php index fe35d623..9ceedb8c 100644 --- a/Constants/OrderCronStatus.php +++ b/Constants/OrderCronStatus.php @@ -10,4 +10,5 @@ class OrderCronStatus const INVOICE_GENERATED = 3; const INVOICE_GENERATION_NOT_POSSIBLE = 4; const PAYMENT_AUTHORIZED_CRON_REPEAT = 5; + const ORDER_NOT_PLACED_DUE_TO_STOCK_UNAVAILABILITY = 6; } diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index a35d93c4..00114a5c 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -242,6 +242,15 @@ public function execute() ] ]; + $orderLink = $this->_objectManager->get('Razorpay\Magento\Model\OrderLink') + ->getCollection() + ->addFilter('order_id', $rzpOrderData['receipt']) + ->getFirstItem(); + + $orderLink->setRzpUpdateOrderCronStatus(OrderCronStatus::ORDER_NOT_PLACED_DUE_TO_STOCK_UNAVAILABILITY); + + $orderLink->save(); + try { $refund = $this->rzp->payment ->fetch($rzpPaymentId) From 284c7be51a39ec601064ef40962ffc5ca64dcbc4 Mon Sep 17 00:00:00 2001 From: ChetanGN Date: Wed, 16 Apr 2025 17:04:11 +0530 Subject: [PATCH 67/67] Error handling and logging upgradation --- Controller/OneClick/AbandonedQuote.php | 58 ++++++++++++++++++++------ Controller/OneClick/CompleteOrder.php | 37 +++++++++++++--- Controller/Payment/Webhook.php | 4 +- Cron/UpdateOrdersToProcessingV2.php | 4 +- Model/QuoteBuilder/ItemBuilder.php | 19 ++++++--- 5 files changed, 95 insertions(+), 27 deletions(-) diff --git a/Controller/OneClick/AbandonedQuote.php b/Controller/OneClick/AbandonedQuote.php index 15aa2d5b..55436214 100644 --- a/Controller/OneClick/AbandonedQuote.php +++ b/Controller/OneClick/AbandonedQuote.php @@ -120,12 +120,13 @@ public function execute() $quoteId = $rzpOrderData->notes->cart_mask_id; - // Set customer to quote - $customerCartId = $this->cartConverter->convertGuestCartToCustomer($cartId); - $this->logger->info('graphQL: customerCartId ' . $customerCartId); $orderPlacement = false; try { + // Set customer to quote + $customerCartId = $this->cartConverter->convertGuestCartToCustomer($cartId); + $this->logger->info('graphQL: customerCartId ' . $customerCartId); + $order = $this->order->loadByIncrementId($reservedOrderId); if (!$order->getId()) { @@ -182,6 +183,11 @@ public function execute() } catch (\Exception $e) { $this->logger->info('graphQL: magento pending order placement failed for AB cart and rzp order id: ' . $rzpOrderId); + return $resultJson->setData([ + 'status' => 'Failed', + 'code' => 'BAD_REQUEST', + 'message' => __('Quote update failed for the reason : ' . $e->getMessage()), + ])->setHttpResponseCode(422); } return $resultJson->setData([ @@ -199,8 +205,8 @@ public function execute() return $resultJson->setData([ 'status' => 'error', 'code' => $code, - 'message' => __('An error occurred on the server. Please try again after sometime.' . $e->getMessage()), - ])->setHttpResponseCode(500); + 'message' => __('Quote update failed for the reason : ' . $e->getMessage()), + ])->setHttpResponseCode(422); } catch (\Exception $e) { $this->logger->critical("Validate: Exception Error message:" . $e->getMessage()); $this->messageManager->addError(__('Payment Failed.')); @@ -208,10 +214,10 @@ public function execute() $code = $e->getCode(); return $resultJson->setData([ - 'status' => 'error', + 'status' => 'failed', 'code' => $code, - 'message' => __('An error occurred on the server. Please try again.'), - ])->setHttpResponseCode(500); + 'message' => __('Quote update failed for the reason : '.$e->getMessage()), + ])->setHttpResponseCode(422); } } @@ -219,8 +225,8 @@ public function updateQuote($quote, $rzpOrderData, $rzpPaymentData = array()) { $quote->setIsActive(true)->save(); - $carrierCode = $rzpOrderData->notes->carrier_code ?? 'freeshipping'; - $methodCode = $rzpOrderData->notes->method_code ?? 'freeshipping'; + $carrierCode = $rzpOrderData->notes->carrier_code ?? null; + $methodCode = $rzpOrderData->notes->method_code ?? null; //This change is to support email less checkout. $email = $quote->getCustomerEmail(); @@ -229,8 +235,8 @@ public function updateQuote($quote, $rzpOrderData, $rzpPaymentData = array()) } $quote->setCustomerEmail($email); - if (empty($rzpOrderData->customer_details->shipping_address) === false) { - + if (empty($rzpOrderData->customer_details->shipping_address) === false) + { $shippingCountry = $rzpOrderData->customer_details->shipping_address->country; $shippingState = $rzpOrderData->customer_details->shipping_address->state; @@ -246,6 +252,34 @@ public function updateQuote($quote, $rzpOrderData, $rzpPaymentData = array()) $quote->getBillingAddress()->addData($billing['address']); $quote->getShippingAddress()->addData($shipping['address']); + // If shipping method is not provided, find the least expensive one + if ((empty($carrierCode) || empty($methodCode))) { + $shippingAddress = $quote->getShippingAddress(); + + // Force shipping rate collection + $shippingAddress + ->setCollectShippingRates(true) // <-- THIS IS CRITICAL + ->collectShippingRates(); // Collects rates + + $shippingRates = $shippingAddress->getAllShippingRates(); + + if (empty($shippingRates)) { + // Log error for debugging + $this->logger->critical("No shipping rates found. Address: " . json_encode($shippingAddress->getData())); + } + + $lowestRate = null; + foreach ($shippingRates as $rate) { + if ($lowestRate === null || $rate->getPrice() < $lowestRate->getPrice()) { + $lowestRate = $rate; + } + } + + if ($lowestRate) { + $carrierCode = $lowestRate->getCarrier(); + $methodCode = $lowestRate->getMethod(); + } + } $shippingMethod = 'NA'; if (empty($carrierCode) === false && empty($methodCode) === false) { $shippingMethod = $carrierCode . "_" . $methodCode; diff --git a/Controller/OneClick/CompleteOrder.php b/Controller/OneClick/CompleteOrder.php index 00114a5c..ea8be598 100644 --- a/Controller/OneClick/CompleteOrder.php +++ b/Controller/OneClick/CompleteOrder.php @@ -632,8 +632,8 @@ public function updateDiscountAmount($orderId, $newDiscountAmount, $offerAmount, protected function updateQuote($quote, $rzpOrderData, $rzpPaymentData) { - $carrierCode = $rzpOrderData->notes->carrier_code ?? 'freeshipping'; - $methodCode = $rzpOrderData->notes->method_code ?? 'freeshipping'; + $carrierCode = $rzpOrderData->notes->carrier_code ?? null; + $methodCode = $rzpOrderData->notes->method_code ?? null; //This change is to support email less checkout. $email = $quote->getCustomerEmail(); @@ -657,11 +657,38 @@ protected function updateQuote($quote, $rzpOrderData, $rzpPaymentData) $quote->getBillingAddress()->addData($billing['address']); $quote->getShippingAddress()->addData($shipping['address']); - $shippingMethod = 'NA'; - if (empty($carrierCode) === false && empty($methodCode) === false) { - $shippingMethod = $carrierCode . "_" . $methodCode; + // If shipping method is not provided, find the least expensive one + if (empty($carrierCode) || empty($methodCode)) { + $shippingAddress = $quote->getShippingAddress(); + + // Force shipping rate collection + $shippingAddress + ->setCollectShippingRates(true) // <-- THIS IS CRITICAL + ->collectShippingRates(); // Collects rates + + $shippingRates = $shippingAddress->getAllShippingRates(); + + if (empty($shippingRates)) { + // Log error for debugging + $this->logger->critical("No shipping rates found. Address: " . json_encode($shippingAddress->getData())); + throw new \Exception("No shipping methods available for the given address."); + } + + $lowestRate = null; + foreach ($shippingRates as $rate) { + if ($lowestRate === null || $rate->getPrice() < $lowestRate->getPrice()) { + $lowestRate = $rate; + } + } + + if ($lowestRate) { + $carrierCode = $lowestRate->getCarrier(); + $methodCode = $lowestRate->getMethod(); + } } + $shippingMethod = ($carrierCode && $methodCode) ? $carrierCode . "_" . $methodCode : 'NA'; + $shippingAddress = $quote->getShippingAddress(); $shippingAddress->setCollectShippingRates(true) ->collectShippingRates() diff --git a/Controller/Payment/Webhook.php b/Controller/Payment/Webhook.php index 1561c86d..661d3902 100644 --- a/Controller/Payment/Webhook.php +++ b/Controller/Payment/Webhook.php @@ -203,7 +203,7 @@ public function execute() exit; } - if (isset($post['payload']['payment']['entity']['notes']['carrier_code']) === true) { + if (isset($post['payload']['payment']['entity']['notes']['cart_mask_id']) === true) { $rzpOrderId = $post['payload']['payment']['entity']['order_id']; $cartId = $post['payload']['payment']['entity']['notes']['cart_id']; $razorpayOrderData = $this->rzp->order->fetch($rzpOrderId); @@ -225,7 +225,7 @@ public function execute() } if (isset($post['payload']['payment']['entity']['notes']['merchant_order_id']) === true && - isset($post['payload']['payment']['entity']['notes']['carrier_code']) === false) + isset($post['payload']['payment']['entity']['notes']['cart_mask_id']) === false) { $orderId = $post['payload']['payment']['entity']['notes']['merchant_order_id']; $paymentId = $post['payload']['payment']['entity']['id']; diff --git a/Cron/UpdateOrdersToProcessingV2.php b/Cron/UpdateOrdersToProcessingV2.php index 461b03fc..8ae03cdb 100644 --- a/Cron/UpdateOrdersToProcessingV2.php +++ b/Cron/UpdateOrdersToProcessingV2.php @@ -561,9 +561,9 @@ public function placeMagentoOrderthroughCron($cartId, $rzpPaymentData, $rzpOrder protected function checkMagicOrder($razorpayOrderData) { - $carrierCode = $razorpayOrderData->notes->carrier_code ?? null; + $cartMaskId = $razorpayOrderData->notes->cart_mask_id ?? null; - if ($carrierCode) { + if ($cartMaskId) { return true; } return false; diff --git a/Model/QuoteBuilder/ItemBuilder.php b/Model/QuoteBuilder/ItemBuilder.php index 2bdbabad..42915a92 100644 --- a/Model/QuoteBuilder/ItemBuilder.php +++ b/Model/QuoteBuilder/ItemBuilder.php @@ -42,6 +42,7 @@ class ItemBuilder */ protected $requestInfoFilter; + protected $logger; /** * ItemBuilder constructor. * @param Http $request @@ -52,12 +53,13 @@ class ItemBuilder * @param RequestInfoFilterInterface $requestInfoFilter */ public function __construct( - Http $request, - Quote $quote, - ResolverInterface $resolver, + Http $request, + Quote $quote, + ResolverInterface $resolver, ProductRepositoryInterface $productRepository, - StoreManagerInterface $storeManager, - RequestInfoFilterInterface $requestInfoFilter + StoreManagerInterface $storeManager, + RequestInfoFilterInterface $requestInfoFilter, + \Psr\Log\LoggerInterface $logger ) { $this->request = $request; $this->quote = $quote; @@ -65,6 +67,7 @@ public function __construct( $this->productRepository = $productRepository; $this->storeManager = $storeManager; $this->requestInfoFilter = $requestInfoFilter; + $this->logger = $logger; } /** @@ -85,7 +88,8 @@ public function addItems() __('We found an invalid request for adding product to quote.') ); } - + $this->logger->info('Magic Buy Now request params:' . json_encode($params)); + $requestInfo = $this->getProductRequest($params); $this->quote->addProduct($product, $requestInfo); @@ -97,7 +101,10 @@ public function addItems() protected function initProduct() { $productId = (int)$this->request->getParam('product'); + if ($productId) { + $this->logger->info('Magic Buy Now request product id:' . json_encode($productId)); + $storeId = $this->storeManager->getStore()->getId(); try { return $this->productRepository->getById($productId, false, $storeId);