diff --git a/Block/Webpayment.php b/Block/Webpayment.php new file mode 100644 index 0000000..e53aba2 --- /dev/null +++ b/Block/Webpayment.php @@ -0,0 +1,215 @@ +_helper = $helper; + $this->_cart = $cart; + parent::__construct( + $context, + $data + ); + $this->_customerSession = $customerSession; + $this->_tokenModelFactory = $tokenModelFactory; + $this->scopeConfig = $scopeConfig; + $this->_messageManager = $messageManager; + } + + /** + * @return string + */ + public function getCurrency(){ + $currency = $this->_cart->getQuote()->getQuoteCurrencyCode(); + return $currency; + } + + public function getAllItems(){ + $allItems = $this->_cart->getQuote()->getAllVisibleItems(); + return $allItems; + } + + public function getTotal(){ + $quote = $this->_cart->getTotalsCache(); + $getGrandTotal = $quote['grand_total']->getData('value'); + + return $getGrandTotal; + } + + public function getShippingRate(){ + $quote = $this->_cart->getTotalsCache(); + $getShippingRate = $quote['shipping']->getData('value'); + + return $getShippingRate; + } + + public function getTaxRate(){ + $quote = $this->_cart->getTotalsCache(); + $getShippingRate = $quote['tax']->getData('value'); + + return $getShippingRate; + } + + public function getSubTotal(){ + $quote = $this->_cart->getTotalsCache(); + $getSubTotal = $quote['subtotal']->getData('value'); + + return $getSubTotal; + } + + + public function getCustomerToken() + { + $customerId = $this->_customerSession->getCustomer()->getId(); + $customerToken = $this->_tokenModelFactory->create(); + return $customerToken->createCustomerToken($customerId)->getToken(); + + } + + public function getshippingRequired() + { + // Disable shipping for downloadable and virtual products + $shippingReq = 'true'; + $allItems = $this->_cart->getQuote()->getAllItems(); + if($allItems) { + $productType = array(); + if($allItems) { + foreach($allItems as $item) { + $productType[] = $item->getProductType(); + } + + $count = count($allItems); + + + // remove duplicates in array + $productType = array_unique($productType); + // remove downloadable product types in array + $productType = array_diff( $productType, ['downloadable'] ); + + // remove virtual product types in array + $productType = array_diff( $productType, ['virtual'] ); + + // Now check if any other product types are still there in array, if no disable shipping + if( sizeof($productType) == 0 ) { + $shippingReq = 'false'; + } + } + + return $shippingReq; + + } + + } + + public function checkDownloadableProduct() + { + // Login required for downloadable and virtual products + $allItems = $this->_cart->getQuote()->getAllItems(); + $productType = array(); + if($allItems) { + foreach($allItems as $item) { + $productType[] = $item->getProductType(); + } + + $productType = array_unique($productType); + + $isDownloadable = 'false'; + + if (in_array("downloadable", $productType)) { + $isDownloadable = 'true'; + } + if (in_array("virtual", $productType)) { + $isDownloadable = 'true'; + } + + return $isDownloadable; + } + return 'false'; + + } + + + public function getProductCount() + { + $allItems = $this->_cart->getQuote()->getAllVisibleItems(); + return $count = count($allItems); + } + + public function getChromepayButtonName() { + $storeScope = \Magento\Store\Model\ScopeInterface::SCOPE_STORE; + + return $this->scopeConfig->getValue('worldpay/cc_config/chromepay_button_name', $storeScope); + } + + public function getChromepayEnabled() { + $storeScope = \Magento\Store\Model\ScopeInterface::SCOPE_STORE; + + return $this->scopeConfig->getValue('worldpay/cc_config/chromepay', $storeScope); + } + + public function getPaymentMode() { + $storeScope = \Magento\Store\Model\ScopeInterface::SCOPE_STORE; + + return $this->scopeConfig->getValue('worldpay/cc_config/integration_mode', $storeScope); + } + +} \ No newline at end of file diff --git a/Controller/Cartdetails/Chromepay.php b/Controller/Cartdetails/Chromepay.php new file mode 100644 index 0000000..b5ae2f9 --- /dev/null +++ b/Controller/Cartdetails/Chromepay.php @@ -0,0 +1,56 @@ +_pageFactory = $pageFactory; + $this->_request = $request; + $this->_paymentservicerequest = $paymentservicerequest; + $this->_authSession = $authSession; + $this->worldpayHelper = $worldpayHelper; + return parent::__construct($context); + } + + public function execute() + { + $data = $this->getRequest()->getParams(); + $orderCode = $this->_authSession->getOrderCode(); + $currencyCode = $this->_authSession->getCurrencyCode(); + if($data && $orderCode){ + $reqData = json_decode($data['data']); + $paymentDetails = $reqData->details; + $shippingAddress = $reqData->shippingAddress; + $billingAddress = $paymentDetails->billingAddress; + $chromeOrderParams = array(); + $chromeOrderParams['orderCode'] = $orderCode; + $chromeOrderParams['merchantCode'] = $this->worldpayHelper->getMerchantCode(); + $chromeOrderParams['orderDescription'] = $this->worldpayHelper->getOrderDescription(); + $chromeOrderParams['currencyCode'] = $currencyCode; + $chromeOrderParams['amount'] = $data['totalAmount']; + $chromeOrderParams['paymentType'] = $data['cardType']; + $chromeOrderParams['paymentDetails'] = $paymentDetails; + $chromeOrderParams['shopperEmail'] = $reqData->payerEmail; + $chromeOrderParams['shippingAddress'] = $shippingAddress; + $chromeOrderParams['billingAddress'] = $billingAddress; + if($chromeOrderParams){ + $response = $this->_paymentservicerequest->chromepayOrder($chromeOrderParams); + } + } else{ + $response = false; + } + return $response; + } +} \ No newline at end of file diff --git a/Controller/Savedcard/Edit.php b/Controller/Savedcard/Edit.php index 02a87ce..4f8c4a7 100644 --- a/Controller/Savedcard/Edit.php +++ b/Controller/Savedcard/Edit.php @@ -50,7 +50,19 @@ public function execute() return; } $resultPage = $this->_resultPageFactory->create(); - $resultPage->getConfig()->getTitle()->set(__('Update Saved Card')); - return $resultPage; + $id = $this->getRequest()->getParam('id'); + $customerId = $this->customerSession->getCustomer()->getId(); + if($id){ + $cardDetails = $this->savecard->create()->load($id); + if($cardDetails->getCustomerId() != $customerId){ + $this->_redirect('404notfound'); + return; + } + $resultPage->getConfig()->getTitle()->set(__('Update Saved Card')); + return $resultPage; + } else{ + $this->_redirect('404notfound'); + return; + } } } diff --git a/Controller/Wallets/Success.php b/Controller/Wallets/Success.php new file mode 100644 index 0000000..5d767c8 --- /dev/null +++ b/Controller/Wallets/Success.php @@ -0,0 +1,36 @@ +wplogger = $wplogger; + $this->_resultPageFactory = $resultPageFactory; + parent::__construct($context); + } + + /** + * Renders the 3D Secure page, responsible for forwarding + * all necessary order data to worldpay. + */ + public function execute() + { + return $this->resultRedirectFactory->create()->setPath('checkout/onepage/success', ['_current' => true]); + } +} diff --git a/Cron/OrderSyncStatus.php b/Cron/OrderSyncStatus.php new file mode 100644 index 0000000..ea37c69 --- /dev/null +++ b/Cron/OrderSyncStatus.php @@ -0,0 +1,212 @@ +_logger = $wplogger; + $this->_orderCollectionFactory = $orderCollectionFactory; + $this->worldpayhelper = $worldpayhelper; + $this->paymentservice = $paymentservice; + $this->orderservice = $orderservice; + $this->resultJsonFactory = $resultJsonFactory; + $this->worldpaytoken = $worldpaytoken; + + } + + /** + * Get the list of orders to be sync the status + */ + public function execute() + { + $this->_logger->info('Orders sync status executed on - '.date('Y-m-d H:i:s')); + $orderIds = $this->getOrderIds(); + + if (!empty($orderIds)) { + foreach ($orderIds as $order) { + $this->_loadOrder($order); + $this->createSyncRequest(); + } + } + return $this; + } + + /** + * Get the list of orders to be Sync + * + * @return array List of order IDs + */ + public function getOrderIds() + { + // Complete order status for downloadable products + $orderStatus = array('pending','processing','complete'); + $orders = $this->getOrderCollectionFactory()->create(); + $orders->distinct(true); + $orders->addFieldToSelect(array('entity_id','increment_id','created_at')); + $orders->addFieldToFilter('main_table.status', array('in' => $orderStatus)); + $orderIds = array_reduce($orders->getItems(), array($this, '_filterOrder')); + return $orderIds; + } + + /** + * @return CollectionFactoryInterface + */ + private function getOrderCollectionFactory() + { + if ($this->orderCollectionFactory === null) { + + $this->orderCollectionFactory = ObjectManager::getInstance()->get(CollectionFactoryInterface::class); + } + return $this->orderCollectionFactory; + } + + /** + * Returns orders have creation date exceeded the allowed limit + * + * @param array $carry Result of previous filter call + * @param \Magento\Sales\Model\Order + * + * @return array List of order IDs + */ + protected function _filterOrder($carry, \Magento\Sales\Model\Order $order) + { + if ($this->getCreationDate($order) > $this->getLimitDateForMethod()) { + $carry[] = $order->getEntityId(); + } + return $carry; + } + + /** + * Computes the latest valid date + * + * @return DateTime + */ + protected function getLimitDateForMethod() + { + $timelimit = 24; + $date = new \DateTime('now'); + $interval = new \DateInterval(sprintf('PT%dH', $timelimit)); + $date->sub($interval); + return $date; + } + + /** + * @param \Magento\Sales\Model\Order $order + * + * @return float|mixed + */ + protected function getCreationDate(\Magento\Sales\Model\Order $order) + { + return \DateTime::createFromFormat('Y-m-d H:i:s', $order->getData('created_at')); + } + + /** + * Computes the latest valid date + *@return DateTime + */ + protected function getLimitDate() + { + $cleanUpInterval = $this->worldpayhelper->orderCleanUpInterval(); + $date = new \DateTime('now'); + $interval = new \DateInterval(sprintf('PT%dH', $cleanUpInterval)); + $date->sub($interval); + return $date; + } + + private function _loadOrder($orderId) + { + $this->_orderId = $orderId; + $this->_order = $this->orderservice->getById($this->_orderId); + } + + /** + * Computes the latest valid date + *@return DateTime + */ + + public function createSyncRequest(){ + try { + $this->_fetchPaymentUpdate(); + $this->_registerWorldPayModel(); + $this->_applyPaymentUpdate(); + $this->_applyTokenUpdate(); + } catch (Exception $e) { + $this->_logger->error($e->getMessage()); + if ($e->getMessage() == 'same state') { + $this->_logger->error('Payment synchronized successfully!!'); + } else { + $this->_logger->error('Synchronising Payment Status failed: ' . $e->getMessage()); + } + } + return true; + } + + private function _fetchPaymentUpdate() + { + $xml = $this->paymentservice->getPaymentUpdateXmlForOrder($this->_order); + $this->_paymentUpdate = $this->paymentservice->createPaymentUpdateFromWorldPayXml($xml); + $this->_tokenState = new \Sapient\Worldpay\Model\Token\StateXml($xml); + } + + private function _registerWorldPayModel() + { + $this->paymentservice->setGlobalPaymentByPaymentUpdate($this->_paymentUpdate); + } + + private function _applyPaymentUpdate() + { + try { + $this->_paymentUpdate->apply($this->_order->getPayment(),$this->_order); + } catch (Exception $e) { + throw new Exception($e->getMessage()); + } + } + + private function _applyTokenUpdate() + { + $this->worldpaytoken->updateOrInsertToken($this->_tokenState, $this->_order->getPayment()); + } + + +} \ No newline at end of file diff --git a/Helper/Data.php b/Helper/Data.php index d03f3ef..3b68c22 100644 --- a/Helper/Data.php +++ b/Helper/Data.php @@ -150,6 +150,20 @@ public function getApmTypes($code) } return $activeMethods; } + public function getWalletsTypes($code) + { + $activeMethods = array(); + if($this->isGooglePayEnable()){ + $activeMethods['PAYWITHGOOGLE-SSL'] = 'Google Pay'; + } + if($this->isSamsungPayEnable()){ + $activeMethods['SAMSUNGPAY-SSL'] = 'Samsung Pay'; + } + if($this->isApplePayEnable()){ + $activeMethods['APPLEPAY-SSL'] = 'Apple Pay'; + } + return $activeMethods; + } public function getCsePublicKey(){ return trim($this->_scopeConfig->getValue('worldpay/cc_config/cse_public_key', \Magento\Store\Model\ScopeInterface::SCOPE_STORE)); } @@ -330,6 +344,8 @@ public function getPaymentTitleForOrders($order, $paymentCode, \Sapient\Worldpay return $this->getCcTitle()."\n".$item->getPaymentType(); } else if($paymentCode == 'worldpay_apm') { return $this->getApmTitle()."\n".$item->getPaymentType(); + }else if($paymentCode == 'worldpay_wallets') { + return $this->getWalletsTitle()."\n".$item->getPaymentType(); }else if($paymentCode == 'worldpay_moto') { return $this->getMotoTitle()."\n".$item->getPaymentType(); } @@ -338,7 +354,56 @@ public function getPaymentTitleForOrders($order, $paymentCode, \Sapient\Worldpay public function getOrderByOrderId($orderId){ return $this->orderFactory->create()->load($orderId); } + + public function getWalletsTitle() + { + return $this->_scopeConfig->getValue('worldpay/wallets_config/title', \Magento\Store\Model\ScopeInterface::SCOPE_STORE); + } + + public function isGooglePayEnable() + { + return (bool) $this->_scopeConfig->getValue('worldpay/wallets_config/google_pay_wallets_config/enabled', \Magento\Store\Model\ScopeInterface::SCOPE_STORE); + } + + public function googlePaymentMethods() + { + return $this->_scopeConfig->getValue('worldpay/wallets_config/google_pay_wallets_config/paymentmethods', \Magento\Store\Model\ScopeInterface::SCOPE_STORE); + } + public function googleAuthMethods() + { + return $this->_scopeConfig->getValue('worldpay/wallets_config/google_pay_wallets_config/authmethods', \Magento\Store\Model\ScopeInterface::SCOPE_STORE); + } + + public function googleGatewayMerchantname() + { + return $this->_scopeConfig->getValue('worldpay/wallets_config/google_pay_wallets_config/gateway_merchantname', \Magento\Store\Model\ScopeInterface::SCOPE_STORE); + } + + public function googleGatewayMerchantid() + { + return $this->_scopeConfig->getValue('worldpay/wallets_config/google_pay_wallets_config/gateway_merchantid', \Magento\Store\Model\ScopeInterface::SCOPE_STORE); + } + + public function googleMerchantname() + { + return $this->_scopeConfig->getValue('worldpay/wallets_config/google_pay_wallets_config/merchant_name', \Magento\Store\Model\ScopeInterface::SCOPE_STORE); + } + + public function googleMerchantid() + { + return $this->_scopeConfig->getValue('worldpay/wallets_config/google_pay_wallets_config/merchant_id', \Magento\Store\Model\ScopeInterface::SCOPE_STORE); + } + + public function isApplePayEnable() + { + return (bool) $this->_scopeConfig->getValue('worldpay/wallets_config/apple_pay_wallets_config/enabled', \Magento\Store\Model\ScopeInterface::SCOPE_STORE); + } + + public function isSamsungPayEnable() + { + return (bool) $this->_scopeConfig->getValue('worldpay/wallets_config/samsung_pay_wallets_config/enabled', \Magento\Store\Model\ScopeInterface::SCOPE_STORE); + } } diff --git a/Model/Authorisation/WalletService.php b/Model/Authorisation/WalletService.php new file mode 100644 index 0000000..97e3636 --- /dev/null +++ b/Model/Authorisation/WalletService.php @@ -0,0 +1,89 @@ +mappingservice = $mappingservice; + $this->paymentservicerequest = $paymentservicerequest; + $this->wplogger = $wplogger; + $this->directResponse = $directResponse; + $this->paymentservice = $paymentservice; + $this->checkoutSession = $checkoutSession; + $this->updateWorldPayPayment = $updateWorldPayPayment; + $this->worldpayHelper = $worldpayHelper; + $this->registryhelper = $registryhelper; + $this->urlBuilders = $urlBuilder; + } + + /** + * handles provides authorization data for redirect + * It initiates a XML request to WorldPay and registers worldpayRedirectUrl + */ + public function authorizePayment( + $mageOrder, + $quote, + $orderCode, + $orderStoreId, + $paymentDetails, + $payment + ) { + $this->checkoutSession->setauthenticatedOrderId($mageOrder->getIncrementId()); + if($paymentDetails['additional_data']['cc_type'] == 'PAYWITHGOOGLE-SSL'){ + $walletOrderParams = $this->mappingservice->collectWalletOrderParameters( + $orderCode, + $quote, + $orderStoreId, + $paymentDetails + ); + + $response = $this->paymentservicerequest->walletsOrder($walletOrderParams); + $directResponse = $this->directResponse->setResponse($response); + $this->updateWorldPayPayment->create()->updateWorldpayPayment($directResponse, $payment); + $this->_applyPaymentUpdate($directResponse, $payment); + } + } + + private function _applyPaymentUpdate( + \Sapient\Worldpay\Model\Response\DirectResponse $directResponse, + $payment + ) { + $paymentUpdate = $this->paymentservice->createPaymentUpdateFromWorldPayXml($directResponse->getXml()); + $paymentUpdate->apply($payment); + $this->_abortIfPaymentError($paymentUpdate); + } + + private function _abortIfPaymentError($paymentUpdate) + { + if ($paymentUpdate instanceof \Sapient\WorldPay\Model\Payment\Update\Refused) { + throw new Exception(sprintf('Payment REFUSED')); + } + + if ($paymentUpdate instanceof \Sapient\WorldPay\Model\Payment\Update\Cancelled) { + throw new Exception(sprintf('Payment CANCELLED')); + } + + if ($paymentUpdate instanceof \Sapient\WorldPay\Model\Payment\Update\Error) { + throw new Exception(sprintf('Payment ERROR')); + } + } +} diff --git a/Model/Config/Source/AuthMethods.php b/Model/Config/Source/AuthMethods.php new file mode 100644 index 0000000..7307649 --- /dev/null +++ b/Model/Config/Source/AuthMethods.php @@ -0,0 +1,21 @@ + 'PAN_ONLY', 'label' => __('Pan Only')], + ['value' => 'CRYPTOGRAM_3DS', 'label' => __('Cryptogram 3ds')] + ]; + } + +} \ No newline at end of file diff --git a/Model/Config/Source/PaymentMethods.php b/Model/Config/Source/PaymentMethods.php new file mode 100644 index 0000000..74fbeb9 --- /dev/null +++ b/Model/Config/Source/PaymentMethods.php @@ -0,0 +1,22 @@ + 'AMEX', 'label' => __('American Express')], + ['value' => 'VISA', 'label' => __('Visa')], + ['value' => 'DISCOVER', 'label' => __('Discover')], + ['value' => 'JCB', 'label' => __('Japanese Credit Bank')], + ['value' => 'MASTERCARD', 'label' => __('Master Card')] + ]; + } +} diff --git a/Model/Mapping/Service.php b/Model/Mapping/Service.php index fdbc1c5..c9955d1 100644 --- a/Model/Mapping/Service.php +++ b/Model/Mapping/Service.php @@ -301,7 +301,10 @@ private function _getCardAddress($quote) private function _getPaymentDetails($paymentDetails) { $method = $paymentDetails['method']; - + if ($paymentDetails['additional_data']['cc_type'] == "PAYWITHGOOGLE-SSL") { + return $paymentDetails['additional_data']['cc_type']; + } + if ($paymentDetails['additional_data']['cse_enabled']) { $details = array( 'cseEnabled' => $paymentDetails['additional_data']['cse_enabled'], @@ -389,5 +392,34 @@ private function _getClientIPAddress() $remoteAddresses = explode(',', $_SERVER['REMOTE_ADDR']); return trim($remoteAddresses[0]); } + public function collectWalletOrderParameters( + $orderCode, + $quote, + $orderStoreId, + $paymentDetails + ) + { + $reservedOrderId = $quote->getReservedOrderId(); + if($paymentDetails['additional_data']['walletResponse']){ + $walletResponse = (array)json_decode($paymentDetails['additional_data']['walletResponse']); + $paymentMethodData = (array)$walletResponse['paymentMethodData']; + $tokenizationData = (array)$paymentMethodData['tokenizationData']; + $token = (array)json_decode($tokenizationData['token']); + return array( + 'orderCode' => $orderCode, + 'merchantCode' => $this->worldpayHelper->getMerchantCode($paymentDetails['additional_data']['cc_type']), + 'orderDescription' => $this->_getOrderDescription($reservedOrderId), + 'currencyCode' => $quote->getQuoteCurrencyCode(), + 'amount' => $quote->getGrandTotal(), + 'paymentType' => $this->_getRedirectPaymentType($paymentDetails), + 'shopperEmail' => $quote->getCustomerEmail(), + 'method' => $paymentDetails['method'], + 'orderStoreId' => $orderStoreId, + 'protocolVersion' => $token['protocolVersion'], + 'signature' => $token['signature'], + 'signedMessage' => $token['signedMessage'] + ); + } + } } diff --git a/Model/Observer/Redirect.php b/Model/Observer/Redirect.php index ffee135..10da723 100644 --- a/Model/Observer/Redirect.php +++ b/Model/Observer/Redirect.php @@ -26,6 +26,7 @@ public function execute(\Magento\Framework\Event\Observer $observer) $redirecturl = $this->checkoutsession->getAdminWpRedirecturl(); $this->checkoutsession->unsAdminWpRedirecturl(); $this->_responseFactory->create()->setRedirect($redirecturl)->sendResponse(); + die(); return; } } diff --git a/Model/PaymentMethods/AbstractMethod.php b/Model/PaymentMethods/AbstractMethod.php index 5433d7c..8dfefac 100644 --- a/Model/PaymentMethods/AbstractMethod.php +++ b/Model/PaymentMethods/AbstractMethod.php @@ -45,6 +45,7 @@ abstract class AbstractMethod extends \Magento\Payment\Model\Method\AbstractMeth const DIRECT_MODEL = 'direct'; const WORLDPAY_CC_TYPE = 'worldpay_cc'; const WORLDPAY_APM_TYPE = 'worldpay_apm'; + const WORLDPAY_WALLETS_TYPE = 'worldpay_wallets'; const WORLDPAY_MOTO_TYPE = 'worldpay_moto'; /** * Constructor @@ -64,6 +65,7 @@ abstract class AbstractMethod extends \Magento\Payment\Model\Method\AbstractMeth * @param \Sapient\Worldpay\Model\Authorisation\TokenService $tokenservice * @param \Sapient\Worldpay\Model\Authorisation\MotoRedirectService $motoredirectservice * @param \Sapient\Worldpay\Model\Authorisation\HostedPaymentPageService $hostedpaymentpageservice + * @param \Sapient\Worldpay\Model\Authorisation\WalletService $walletService * @param \Sapient\Worldpay\Helper\Registry $registryhelper * @param \Magento\Framework\UrlInterface $urlBuilder * @param \Sapient\Worldpay\Helper\Data $worldpayhelper @@ -95,6 +97,7 @@ public function __construct( \Sapient\Worldpay\Model\Authorisation\TokenService $tokenservice, \Sapient\Worldpay\Model\Authorisation\MotoRedirectService $motoredirectservice, \Sapient\Worldpay\Model\Authorisation\HostedPaymentPageService $hostedpaymentpageservice, + \Sapient\Worldpay\Model\Authorisation\WalletService $walletService, \Sapient\Worldpay\Helper\Registry $registryhelper, \Magento\Framework\UrlInterface $urlBuilder, \Sapient\Worldpay\Helper\Data $worldpayhelper, @@ -129,6 +132,7 @@ public function __construct( $this->redirectservice = $redirectservice; $this->tokenservice = $tokenservice; $this->hostedpaymentpageservice = $hostedpaymentpageservice; + $this->walletService = $walletService; $this->quoteRepository = $quoteRepository; $this->registryhelper = $registryhelper; $this->urlbuilder = $urlBuilder; @@ -174,6 +178,7 @@ public function getOrderPlaceRedirectUrl() public function authorize(\Magento\Payment\Model\InfoInterface $payment, $amount){ + $mageOrder = $payment->getOrder(); $quote = $this->quoteRepository->get($mageOrder->getQuoteId()); if($this->authSession->isLoggedIn()) { @@ -184,11 +189,13 @@ public function authorize(\Magento\Payment\Model\InfoInterface $payment, $amount } $orderCode = $this->_generateOrderCode($quote); + $this->authSession->setCurrencyCode($quote->getQuoteCurrencyCode()); $this->paymentdetailsdata = self::$paymentDetails; - try { $this->validatePaymentData(self::$paymentDetails); - $this->_checkpaymentapplicable($quote); + if(self::$paymentDetails['method'] != self::WORLDPAY_WALLETS_TYPE){ + $this->_checkpaymentapplicable($quote); + } $this->_checkShippingApplicable($quote); $this->_createWorldPayPayment($payment,$orderCode,$quote->getStoreId(),$quote->getReservedOrderId()); $authorisationService = $this->getAuthorisationService($quote->getStoreId()); @@ -200,6 +207,7 @@ public function authorize(\Magento\Payment\Model\InfoInterface $payment, $amount self::$paymentDetails, $payment ); + $this->authSession->setOrderCode($orderCode); } catch (Exception $e) { $this->_wplogger->error($e->getMessage()); $this->_wplogger->error('Authorising payment failed.'); @@ -208,6 +216,7 @@ public function authorize(\Magento\Payment\Model\InfoInterface $payment, $amount throw new \Magento\Framework\Exception\LocalizedException( __($errormessage) ); + $this->authSession->setOrderCode(false); } } @@ -249,6 +258,8 @@ public function validatePaymentData($paymentData){ } } elseif ($method == self::WORLDPAY_APM_TYPE && !isset($paymentData['additional_data']['cc_type'])) { throw new Exception($generalErrorMessage, 1); + } elseif ($method == self::WORLDPAY_WALLETS_TYPE && !isset($paymentData['additional_data']['cc_type'])) { + throw new Exception($generalErrorMessage, 1); } } @@ -274,6 +285,9 @@ private function _createWorldPayPayment(\Magento\Payment\Model\InfoInterface $pa { $paymentdetails = self::$paymentDetails; $integrationType = $this->worlpayhelper->getIntegrationModelByPaymentMethodCode($payment->getMethod(),$storeId); + if ($paymentdetails['method'] == self::WORLDPAY_WALLETS_TYPE) { + $integrationType = 'direct'; + } $wpp = $this->worldpaypayment->create(); $wpp->setData('order_id',$orderId); $wpp->setData('payment_status',\Sapient\Worldpay\Model\Payment\State::STATUS_SENT_FOR_AUTHORISATION); @@ -395,9 +409,9 @@ protected function _checkpaymentapplicable($quote){ $billingaddress = $quote->getBillingAddress(); $countryId = $billingaddress->getCountryId(); $paymenttypes = json_decode($this->paymenttypes->getPaymentType($countryId)); - if(!in_array($type, $paymenttypes)){ - throw new Exception('Payment Type not valid for the billing country'); - } +// if(!in_array($type, $paymenttypes)){ +// throw new Exception('Payment Type not valid for the billing country'); +// } } /** @@ -464,4 +478,4 @@ protected function _addtransaction($payment, $amount) -} +} \ No newline at end of file diff --git a/Model/PaymentMethods/Wallets.php b/Model/PaymentMethods/Wallets.php new file mode 100644 index 0000000..708653b --- /dev/null +++ b/Model/PaymentMethods/Wallets.php @@ -0,0 +1,73 @@ +_wplogger->info('WorldPay Wallets Payment Method Executed:'); + parent::authorize($payment, $amount); + return $this; + } + + public function getAuthorisationService($storeId) + { + return $this->walletService; + } + + /** + * check if apm is enabled + * @return bool + */ + public function isAvailable(\Magento\Quote\Api\Data\CartInterface $quote = null) + { + if ($this->worlpayhelper->isWorldPayEnable()) { + return true; + } + return false; + } + + public function getTitle() + { + if($order = $this->registry->registry('current_order')) { + return $this->worlpayhelper->getPaymentTitleForOrders($order, $this->_code, $this->worldpaypayment); + }else if($invoice = $this->registry->registry('current_invoice')){ + $order = $this->worlpayhelper->getOrderByOrderId($invoice->getOrderId()); + return $this->worlpayhelper->getPaymentTitleForOrders($order, $this->_code, $this->worldpaypayment); + }else if($creditMemo = $this->registry->registry('current_creditmemo')){ + $order = $this->worlpayhelper->getOrderByOrderId($creditMemo->getOrderId()); + return $this->worlpayhelper->getPaymentTitleForOrders($order, $this->_code, $this->worldpaypayment); + }else{ + return $this->worlpayhelper->getWalletsTitle(); + } + } + + + +// public function getTitle() +// { +// return 'worldpay_wallets'; +// } +} diff --git a/Model/Request/PaymentServiceRequest.php b/Model/Request/PaymentServiceRequest.php index 23864c9..2d5655f 100644 --- a/Model/Request/PaymentServiceRequest.php +++ b/Model/Request/PaymentServiceRequest.php @@ -460,4 +460,66 @@ public function paymentOptionsByCountry($paymentOptionsParams) $this->worldpayhelper->getXmlPassword($paymentOptionsParams['paymentType']) ); } + + /** + * Send wallet order XML to Worldpay server + * + * @param array $walletOrderParams + * @return mixed + */ + public function walletsOrder($walletOrderParams) + { + $this->_wplogger->info('########## Submitting wallet order request. OrderCode: ' . $walletOrderParams['orderCode'] . ' ##########'); + + $this->xmlredirectorder = new \Sapient\Worldpay\Model\XmlBuilder\WalletOrder(); + $walletSimpleXml = $this->xmlredirectorder->build( + $walletOrderParams['merchantCode'], + $walletOrderParams['orderCode'], + $walletOrderParams['orderDescription'], + $walletOrderParams['currencyCode'], + $walletOrderParams['amount'], + $walletOrderParams['paymentType'], + $walletOrderParams['shopperEmail'], + $walletOrderParams['protocolVersion'], + $walletOrderParams['signature'], + $walletOrderParams['signedMessage'] + ); + + return $this->_sendRequest( + dom_import_simplexml($walletSimpleXml)->ownerDocument, + $this->worldpayhelper->getXmlUsername($walletOrderParams['paymentType']), + $this->worldpayhelper->getXmlPassword($walletOrderParams['paymentType']) + ); + } + + /** + * Send chromepay order XML to Worldpay server + * + * @param array $chromepayOrderParams + * @return mixed + */ + public function chromepayOrder($chromeOrderParams) + { + $this->_wplogger->info('########## Submitting chromepay order request. OrderCode: ' . $chromeOrderParams['orderCode'] . ' ##########'); + $paymentType = 'worldpay_cc'; + $this->xmlredirectorder = new \Sapient\Worldpay\Model\XmlBuilder\ChromePayOrder(); + $chromepaySimpleXml = $this->xmlredirectorder->build( + $chromeOrderParams['merchantCode'], + $chromeOrderParams['orderCode'], + $chromeOrderParams['orderDescription'], + $chromeOrderParams['currencyCode'], + $chromeOrderParams['amount'], + $chromeOrderParams['paymentType'], + $chromeOrderParams['paymentDetails'], + $chromeOrderParams['shippingAddress'], + $chromeOrderParams['billingAddress'], + $chromeOrderParams['shopperEmail'] + ); + //echo $this->worldpayhelper->getXmlUsername($paymentType);exit; + return $this->_sendRequest( + dom_import_simplexml($chromepaySimpleXml)->ownerDocument, + $this->worldpayhelper->getXmlUsername($paymentType), + $this->worldpayhelper->getXmlPassword($paymentType) + ); + } } diff --git a/Model/Utilities/PaymentMethods.php b/Model/Utilities/PaymentMethods.php index 3713765..d7bb64a 100644 --- a/Model/Utilities/PaymentMethods.php +++ b/Model/Utilities/PaymentMethods.php @@ -79,6 +79,8 @@ protected function _getConfigCode($type) return 'cc_config'; case 'worldpay_apm': return 'apm_config'; + case 'worldpay_wallets': + return 'wallets_config'; default: return 'apm_config'; } diff --git a/Model/WorldpayConfigProvider.php b/Model/WorldpayConfigProvider.php index 9c20ee6..04e974c 100644 --- a/Model/WorldpayConfigProvider.php +++ b/Model/WorldpayConfigProvider.php @@ -24,7 +24,8 @@ class WorldpayConfigProvider implements ConfigProviderInterface */ protected $methodCodes = [ 'worldpay_cc', - 'worldpay_apm' + 'worldpay_apm', + 'worldpay_wallets' ]; /** @@ -110,7 +111,10 @@ public function getConfig() $config['payment']['minimum_amount'] = $this->payment->getMinimumAmount(); if ($code=='worldpay_cc') { $config['payment']['ccform']["availableTypes"][$code] = $this->getCcTypes(); - } else { + } else if ($code=='worldpay_wallets') { + $config['payment']['ccform']["availableTypes"][$code] = $this->getWalletsTypes($code); + } + else { $config['payment']['ccform']["availableTypes"][$code] = $this->getApmTypes($code); } $config['payment']['ccform']["hasVerification"][$code] = true; @@ -132,11 +136,25 @@ public function getConfig() $config['payment']['ccform']['savedCardList'] = $this->getSaveCardList(); $config['payment']['ccform']['saveCardAllowed'] = $this->worldpayHelper->getSaveCard(); $config['payment']['ccform']['apmtitle'] = $this->getApmtitle(); + $config['payment']['ccform']['walletstitle'] = $this->getWalletstitle(); $config['payment']['ccform']['paymentMethodSelection'] = $this->getPaymentMethodSelection(); $config['payment']['ccform']['paymentTypeCountries'] = $this->paymentmethodutils->getPaymentTypeCountries(); $config['payment']['ccform']['savedCardCount'] = count($this->getSaveCardList()); $config['payment']['ccform']['apmIdealBanks'] = $this->getApmIdealBankList(); $config['payment']['ccform']['wpicons'] = $this->getIcons(); + + $config['payment']['ccform']['isGooglePayEnable'] = $this->worldpayHelper->isGooglePayEnable(); + $config['payment']['ccform']['googlePaymentMethods'] = $this->worldpayHelper->googlePaymentMethods(); + $config['payment']['ccform']['googleAuthMethods'] = $this->worldpayHelper->googleAuthMethods(); + $config['payment']['ccform']['googleGatewayMerchantname'] = $this->worldpayHelper->googleGatewayMerchantname(); + $config['payment']['ccform']['googleGatewayMerchantid'] = $this->worldpayHelper->googleGatewayMerchantid(); + $config['payment']['ccform']['googleMerchantname'] = $this->worldpayHelper->googleMerchantname(); + $config['payment']['ccform']['googleMerchantid'] = $this->worldpayHelper->googleMerchantid(); + if ($this->worldpayHelper->getEnvironmentMode()=='Live Mode'){ + $config['payment']['general']['environmentMode'] = "PRODUCTION"; + }else{ + $config['payment']['general']['environmentMode'] = "TEST"; + } } } return $config; @@ -193,6 +211,14 @@ public function getApmTypes($code) { return $this->worldpayHelper->getApmTypes($code); } + + /** + * @return Array + */ + public function getWalletsTypes($code) + { + return $this->worldpayHelper->getWalletsTypes($code); + } public function getMonths() { @@ -253,6 +279,14 @@ public function getApmtitle() { return $this->worldpayHelper->getApmTitle(); } + + /** + * @return String + */ + public function getWalletstitle() + { + return $this->worldpayHelper->getWalletstitle(); + } /** * @return boolean @@ -298,7 +332,9 @@ public function getIcons() } $types = $this->worldpayHelper->getCcTypes(); + $types['VISA_DEBIT-SSL'] = 'Visa debit'; $apmTypes = $this->worldpayHelper->getApmTypes('worldpay_apm'); + $walletsTypes = $this->worldpayHelper->getWalletsTypes('worldpay_wallets'); $allTypePayments = array_unique (array_merge ($types, $apmTypes)); foreach (array_keys($allTypePayments) as $code) { if (!array_key_exists($code, $this->icons)) { diff --git a/Model/XmlBuilder/ChromePayOrder.php b/Model/XmlBuilder/ChromePayOrder.php new file mode 100644 index 0000000..78fdfcc --- /dev/null +++ b/Model/XmlBuilder/ChromePayOrder.php @@ -0,0 +1,396 @@ + +EOD; + + private $merchantCode; + private $orderCode; + private $orderDescription; + private $currencyCode; + private $amount; + protected $paymentDetails; + //private $cardAddress; + protected $shopperEmail; + protected $acceptHeader; + protected $userAgentHeader; + private $shippingAddress; + private $billingAddress; + private $echoData = null; + + /** + * @var Sapient\Worldpay\Model\XmlBuilder\Config\TokenConfiguration + */ + protected $tokenRequestConfig; + + /** + * Constructor + * + * @param array $args + */ + public function __construct(array $args = array()) + { + //$this->tokenRequestConfig = new \Sapient\Worldpay\Model\XmlBuilder\Config\TokenConfiguration($args['tokenRequestConfig']); + } + + /** + * Build xml for processing Request + * + * @param string $merchantCode + * @param string $orderCode + * @param string $orderDescription + * @param string $currencyCode + * @param float $amount + * @param array $paymentDetails + * @param array $cardAddress + * @param string $shopperEmail + * @param string $acceptHeader + * @param string $userAgentHeader + * @param string $shippingAddress + * @param float $billingAddress + * @param string $shopperId + * @return SimpleXMLElement $xml + */ + public function build( + $merchantCode, + $orderCode, + $orderDescription, + $currencyCode, + $amount, + $paymentType, + $paymentDetails, + //$cardAddress, + //$acceptHeader, + //$userAgentHeader, + $shippingAddress, + $billingAddress, + //$shopperId, + $shopperEmail + ) { + $this->merchantCode = $merchantCode; + $this->orderCode = $orderCode; + $this->orderDescription = $orderDescription; + $this->currencyCode = $currencyCode; + $this->amount = $amount; + $this->paymentType = $paymentType; + $this->paymentDetails = $paymentDetails; + //$this->cardAddress = $cardAddress; + $this->shippingAddress = $shippingAddress; + $this->billingAddress = $billingAddress; + $this->shopperEmail = $shopperEmail; + //$this->acceptHeader = $acceptHeader; + //$this->userAgentHeader = $userAgentHeader; + + $xml = new \SimpleXMLElement(self::ROOT_ELEMENT); + $xml['merchantCode'] = $this->merchantCode; + $xml['version'] = '1.4'; + + $submit = $this->_addSubmitElement($xml); + $this->_addOrderElement($submit); + + return $xml; + } + + /** + * Add submit tag to xml + * + * @param SimpleXMLElement $xml + * @return SimpleXMLElement + */ + private function _addSubmitElement($xml) + { + return $xml->addChild('submit'); + } + + /** + * Add order and its child tag to xml + * + * @param SimpleXMLElement $submit + * @return SimpleXMLElement $order + */ + private function _addOrderElement($submit) + { + $order = $submit->addChild('order'); + $order['orderCode'] = $this->orderCode; + $this->_addDescriptionElement($order); + $this->_addAmountElement($order); + $this->_addPaymentDetailsElement($order); + $this->_addShopperElement($order); + $this->_addShippingElement($order); + $this->_addBillingElement($order); + + + if ($this->echoData) { + $order->addChild('echoData', $this->echoData); + } + + //$this->_addCreateTokenElement($order); + //$this->_addDynamicInteractionTypeElement($order); + + return $order; + } + + /** + * Add description tag to xml + * + * @param SimpleXMLElement $order + */ + private function _addDescriptionElement($order) + { + $description = $order->addChild('description'); + $this->_addCDATA($description, $this->orderDescription); + } + + /** + * Add amount and its child tag to xml + * + * @param SimpleXMLElement $order + */ + private function _addAmountElement($order) + { + $amountElement = $order->addChild('amount'); + $amountElement['currencyCode'] = $this->currencyCode; + $amountElement['exponent'] = self::EXPONENT; + $amountElement['value'] = $this->_amountAsInt($this->amount); + } + + /** + * Add paymentDetails and its child tag to xml + * + * @param SimpleXMLElement $order + */ + protected function _addPaymentDetailsElement($order) + { + $paymentDetailsElement = $order->addChild('paymentDetails'); + + $this->_addPaymentDetailsForCreditCardOrder($paymentDetailsElement); + //$session = $paymentDetailsElement->addChild('session'); + //$session['id'] = $this->paymentDetails['sessionId']; + //$session['shopperIPAddress'] = $this->paymentDetails['shopperIpAddress']; + } + + /** + * Add dynamicInteractionType and its child tag to xml + * + * @param SimpleXMLElement $order + */ + private function _addDynamicInteractionTypeElement($order) + { + if (self::ALLOW_INTERACTION_TYPE == $this->paymentDetails['dynamicInteractionType']) { + $interactionElement = $order->addChild('dynamicInteractionType'); + $interactionElement['type'] = $this->paymentDetails['dynamicInteractionType']; + } + } + + /** + * Add createToken and its child tag to xml + * + * @param SimpleXMLElement $order + */ + private function _addCreateTokenElement($order) + { + + $createTokenElement = $order->addChild('createToken'); + $createTokenElement['tokenScope'] = self::TOKEN_SCOPE; + + if ($this->tokenRequestConfig->getTokenReason($this->orderCode)) { + $createTokenElement->addChild( + 'tokenReason', + $this->tokenRequestConfig->getTokenReason($this->orderCode) + ); + } + } + + /** + * Add paymentDetailsElement and its child tag to xml + * + * @param SimpleXMLElement $paymentDetailsElement + */ + protected function _addPaymentDetailsForCreditCardOrder($paymentDetailsElement) + { + $paymentTypeElement = $this->_addPaymentTypeElement($paymentDetailsElement); + $cardAddress = $paymentTypeElement->addChild('cardAddress'); + + $this->_addAddressElement( + $cardAddress, + $this->billingAddress->recipient, + $this->billingAddress->addressLine[0], + $this->billingAddress->postalCode, + $this->billingAddress->city, + $this->billingAddress->country + ); + } + + + + /** + * Add CSE-DATA and its child tag to xml + * + * @param SimpleXMLElement $paymentDetailsElement + * @return SimpleXMLElement cseElement + */ + protected function _addCseElement($paymentDetailsElement) + { + $cseElement = $paymentDetailsElement->addChild('CSE-DATA'); + $cseElement->addChild('encryptedData', $this->paymentDetails['encryptedData']); + + return $cseElement; + } + + /** + * Add paymentType and its child tag to xml + * + * @param SimpleXMLElement $paymentDetailsElement + * @return SimpleXMLElement $paymentTypeElement + */ + protected function _addPaymentTypeElement($paymentDetailsElement) + { + $paymentTypeElement = $paymentDetailsElement->addChild($this->paymentType); + $paymentTypeElement->addChild('cardNumber', $this->paymentDetails->cardNumber); + + $expiryDate = $paymentTypeElement->addChild('expiryDate'); + $date = $expiryDate->addChild('date'); + $date['month'] = $this->paymentDetails->expiryMonth; + $date['year'] = $this->paymentDetails->expiryYear; + + $paymentTypeElement->addChild('cardHolderName', $this->paymentDetails->cardholderName); + + if (isset($this->paymentDetails->cardSecurityCode)) { + $paymentTypeElement->addChild('cvc', $this->paymentDetails->cardSecurityCode); + } + + return $paymentTypeElement; + } + + /** + * Add shopper and its child tag to xml + * + * @param SimpleXMLElement $order + */ + protected function _addShopperElement($order) + { + $shopper = $order->addChild(self::TOKEN_SCOPE); + + $shopper->addChild('shopperEmailAddress', $this->shopperEmail); + + //$shopper->addChild('authenticatedShopperID', $this->paymentDetails['customerId']); + + $browser = $shopper->addChild('browser'); + +// $acceptHeader = $browser->addChild('acceptHeader'); +// $this->_addCDATA($acceptHeader, $this->acceptHeader); +// +// $userAgentHeader = $browser->addChild('userAgentHeader'); +// $this->_addCDATA($userAgentHeader, $this->userAgentHeader); + + return $shopper; + } + + /** + * Add shippingAddress and its child tag to xml + * + * @param SimpleXMLElement $order + */ + private function _addShippingElement($order) + { + $shippingAddress = $order->addChild('shippingAddress'); + $this->_addAddressElement( + $shippingAddress, + $this->shippingAddress->recipient, + $this->shippingAddress->addressLine[0], + $this->shippingAddress->postalCode, + $this->shippingAddress->city, + $this->shippingAddress->country + ); + } + + /** + * Add billing and its child tag to xml + * + * @param SimpleXMLElement $order + */ + private function _addBillingElement($order) + { + $billingAddress = $order->addChild('billingAddress'); + $this->_addAddressElement( + $billingAddress, + $this->billingAddress->recipient, + $this->billingAddress->addressLine[0], + $this->billingAddress->postalCode, + $this->billingAddress->city, + $this->billingAddress->country + ); + } + + /** + * Add address and its child tag to xml + * + * @param SimpleXMLElement $parentElement + * @param string $firstName + * @param string $lastName + * @param string $street + * @param string $postalCode + * @param string $city + * @param string $countryCode + */ + private function _addAddressElement($parentElement, $firstName, $street, $postalCode, $city, $countryCode) + { + $address = $parentElement->addChild('address'); + + $firstNameElement = $address->addChild('firstName'); + $this->_addCDATA($firstNameElement, $firstName); + +// $lastNameElement = $address->addChild('lastName'); +// $this->_addCDATA($lastNameElement, $lastName); + + $streetElement = $address->addChild('street'); + $this->_addCDATA($streetElement, $street); + + $postalCodeElement = $address->addChild('postalCode'); + $this->_addCDATA($postalCodeElement, $postalCode); + + $cityElement = $address->addChild('city'); + $this->_addCDATA($cityElement, $city); + + $countryCodeElement = $address->addChild('countryCode'); + $this->_addCDATA($countryCodeElement, $countryCode); + } + + /** + * @param SimpleXMLElement $element + * @param string $content + */ + protected function _addCDATA($element, $content) + { + $node = dom_import_simplexml($element); + $no = $node->ownerDocument; + $node->appendChild($no->createCDATASection($content)); + } + + /** + * @param float $amount + * @return int + */ + private function _amountAsInt($amount) + { + return round($amount, self::EXPONENT, PHP_ROUND_HALF_EVEN) * pow(10, self::EXPONENT); + } +} diff --git a/Model/XmlBuilder/WalletOrder.php b/Model/XmlBuilder/WalletOrder.php new file mode 100644 index 0000000..be1d994 --- /dev/null +++ b/Model/XmlBuilder/WalletOrder.php @@ -0,0 +1,170 @@ + +EOD; + + private $merchantCode; + private $orderCode; + private $orderDescription; + private $currencyCode; + private $amount; + private $paymentType; + + /** + * Build xml for processing Request + * + * @param string $merchantCode + * @param string $orderCode + * @param string $orderDescription + * @param string $currencyCode + * @param float $amount + * @param string $paymentType + * @return SimpleXMLElement $xml + */ + public function build( + $merchantCode, + $orderCode, + $orderDescription, + $currencyCode, + $amount, + $paymentType, + $shopperEmail, + $protocolVersion, + $signature, + $signedMessage + ) { + $this->merchantCode = $merchantCode; + $this->orderCode = $orderCode; + $this->orderDescription = $orderDescription; + $this->currencyCode = $currencyCode; + $this->amount = $amount; + $this->paymentType = $paymentType; + $this->shopperEmail = $shopperEmail; + $this->protocolVersion = $protocolVersion; + $this->signature = $signature; + $this->signedMessage = $signedMessage; + $xml = new \SimpleXMLElement(self::ROOT_ELEMENT); + $xml['merchantCode'] = $this->merchantCode; + $xml['version'] = '1.4'; + + $submit = $this->_addSubmitElement($xml); + $this->_addOrderElement($submit); + + return $xml; + } + + /** + * Add submit tag to xml + * + * @param SimpleXMLElement $xml + * @return SimpleXMLElement + */ + private function _addSubmitElement($xml) + { + return $xml->addChild('submit'); + } + + /** + * Add order tag to xml + * + * @param SimpleXMLElement $submit + * @return SimpleXMLElement $order + */ + private function _addOrderElement($submit) + { + $order = $submit->addChild('order'); + $order['orderCode'] = $this->orderCode; + $order['shopperLanguageCode'] = "en"; + + $this->_addDescriptionElement($order); + $this->_addAmountElement($order); + $this->_addPaymentDetailsElement($order); + $this->_addShopperElement($order); + return $order; + } + + /** + * Add description tag to xml + * + * @param SimpleXMLElement $order + */ + private function _addDescriptionElement($order) + { + $description = $order->addChild('description'); + $this->_addCDATA($description, $this->orderDescription); + } + + /** + * Add amount tag to xml + * + * @param SimpleXMLElement $order + */ + private function _addAmountElement($order) + { + $amountElement = $order->addChild('amount'); + $amountElement['currencyCode'] = $this->currencyCode; + $amountElement['exponent'] = self::EXPONENT; + $amountElement['value'] = $this->_amountAsInt($this->amount); + } + + /** + * Add PaymentDetails and its child tag to xml + * + * @param SimpleXMLElement $order + */ + private function _addPaymentDetailsElement($order) + { + $paymentDetails = $order->addChild('paymentDetails'); + + $paymentType = $paymentDetails->addChild($this->paymentType); + $paymentType->addChild('protocolVersion', $this->protocolVersion); + $paymentType->addChild('signature', $this->signature); + $paymentType->addChild('signedMessage', $this->signedMessage); + } + + /** + * Add shopper and its child tag to xml + * + * @param SimpleXMLElement $order + */ + private function _addShopperElement($order) + { + $shopper = $order->addChild('shopper'); + + $shopper->addChild('shopperEmailAddress', $this->shopperEmail); + } + + /** + * @param SimpleXMLElement $element + * @param string $content + */ + private function _addCDATA($element, $content) + { + $node = dom_import_simplexml($element); + $no = $node->ownerDocument; + $node->appendChild($no->createCDATASection($content)); + } + + /** + * @param float $amount + * @return int + */ + private function _amountAsInt($amount) + { + return round($amount, self::EXPONENT, PHP_ROUND_HALF_EVEN) * pow(10, self::EXPONENT); + } +} diff --git a/Plugin/CsrfValidatorDisable.php b/Plugin/CsrfValidatorDisable.php new file mode 100644 index 0000000..17759ff --- /dev/null +++ b/Plugin/CsrfValidatorDisable.php @@ -0,0 +1,23 @@ +getModuleName() == 'worldpay') { + return; // Disable CSRF check + } + $proceed($request, $action); // Proceed Magento 2 core functionalities + } +} \ No newline at end of file diff --git a/Plugin/PaymentInformationManagement.php b/Plugin/PaymentInformationManagement.php index d17f512..afbd342 100644 --- a/Plugin/PaymentInformationManagement.php +++ b/Plugin/PaymentInformationManagement.php @@ -74,8 +74,8 @@ public function aroundSavePaymentInformationAndPlaceOrder( $orderId = $this->cartManagement->placeOrder($cartId); } catch (LocalizedException $exception) { $this->logger->error($exception->getMessage()); - //throw new CouldNotSaveException(__($exception->getMessage())); - throw new CouldNotSaveException(__('Mentioned card details are already saved, try with other card!'),$exception); + throw new CouldNotSaveException(__($exception->getMessage())); + //throw new CouldNotSaveException(__('Mentioned card details are already saved, try with other card!'),$exception); } catch (\Exception $exception) { $this->logger->error($exception->getMessage()); throw new CouldNotSaveException( diff --git a/Worldpay User Document.pdf b/Worldpay User Document.pdf index fc8d552..997643d 100644 Binary files a/Worldpay User Document.pdf and b/Worldpay User Document.pdf differ diff --git a/composer.json b/composer.json index bf9d04d..3d22890 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,7 @@ "magento/module-quote": ">=100.0.0", "magento/module-vault": ">=100.0.0" }, - "version": "1.5.5", + "version": "2.0", "license":"proprietary", "autoload":{ "files":[ diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml index d250c73..95e745b 100644 --- a/etc/adminhtml/system.xml +++ b/etc/adminhtml/system.xml @@ -103,6 +103,14 @@ Magento\Config\Model\Config\Source\Yesno + + + + Magento\Config\Model\Config\Source\Yesno + + + + @@ -120,8 +128,37 @@ + + + + + + + + + + + + Magento\Config\Model\Config\Source\Yesno + + + + Sapient\Worldpay\Model\Config\Source\PaymentMethods + + + + Sapient\Worldpay\Model\Config\Source\AuthMethods + + + + + + + + + - + @@ -136,7 +173,7 @@ - + @@ -144,7 +181,7 @@ Sapient\Worldpay\Model\System\Config\Backend\Merchantprofile - + @@ -158,7 +195,7 @@ Magento\Config\Model\Config\Source\Yesno - + diff --git a/etc/config.xml b/etc/config.xml index 15b6f4a..7dd019f 100644 --- a/etc/config.xml +++ b/etc/config.xml @@ -19,12 +19,21 @@ direct full_page 0 + 1 1 Alternative Payment Methods PAYPAL-EXPRESS,GIROPAY-SSL + + Wallets + + 1 + AMEX,VISA,DISCOVER,JCB,MASTERCARD + PAN_ONLY,CRYPTOGRAM_3DS + + 1 Moto @@ -94,6 +103,14 @@ authorize 11 + + Wallets + Sapient\Worldpay\Model\PaymentMethods\Wallets + 1 + 0 + authorize + 11 + MOTO Sapient\Worldpay\Model\PaymentMethods\Moto diff --git a/etc/cron_groups.xml b/etc/cron_groups.xml index 4c7f08f..e089296 100644 --- a/etc/cron_groups.xml +++ b/etc/cron_groups.xml @@ -9,4 +9,13 @@ 600 1 + + 1 + 4 + 2 + 10 + 60 + 600 + 1 + \ No newline at end of file diff --git a/etc/crontab.xml b/etc/crontab.xml index a76b433..e0bad5b 100644 --- a/etc/crontab.xml +++ b/etc/crontab.xml @@ -5,4 +5,9 @@ * * * * * + + + * * * * * + + \ No newline at end of file diff --git a/etc/di.xml b/etc/di.xml index d0636ff..be9a2b0 100644 --- a/etc/di.xml +++ b/etc/di.xml @@ -14,6 +14,12 @@ + + + + + + @@ -27,6 +33,7 @@ worldpay_apm worldpay_moto worldpay_cc_vault + worldpay_wallets diff --git a/etc/paymentmethods.xml b/etc/paymentmethods.xml index fba68a8..d351d6b 100644 --- a/etc/paymentmethods.xml +++ b/etc/paymentmethods.xml @@ -441,4 +441,144 @@ + + Wallets + + + Apple Pay + + AU + AT + BE + BR + CA + CN + DK + EG + FI + FR + DE + GH + GR + HK + IN + ID + IE + IT + JP + MY + MX + NL + NZ + NG + NO + PH + PL + PT + RU + SG + ZA + KR + ES + SE + CH + TH + GB + US + VN + + 1 + + + Google Pay + + AU + AT + BE + BR + CA + CN + DK + EG + FI + FR + DE + GH + GR + HK + IN + ID + IE + IT + JP + MY + MX + NL + NZ + NG + NO + PH + PL + PT + RU + SG + ZA + KR + ES + SE + CH + TH + GB + US + VN + + 1 + + + Samsung Pay + + AU + AT + BE + BR + CA + CN + DK + EG + FI + FR + DE + GH + GR + HK + IN + ID + IE + IT + JP + MY + MX + NL + NZ + NG + NO + PH + PL + PT + RU + SG + ZA + KR + ES + SE + CH + TH + GB + US + VN + + 1 + + + diff --git a/view/frontend/layout/checkout_cart_index.xml b/view/frontend/layout/checkout_cart_index.xml index d34e21f..adf8526 100644 --- a/view/frontend/layout/checkout_cart_index.xml +++ b/view/frontend/layout/checkout_cart_index.xml @@ -3,6 +3,13 @@ - + + + + + Sapient_Worldpay::onepage/link.phtml + + + \ No newline at end of file diff --git a/view/frontend/layout/checkout_index_index.xml b/view/frontend/layout/checkout_index_index.xml index 2d22ab3..83a3649 100644 --- a/view/frontend/layout/checkout_index_index.xml +++ b/view/frontend/layout/checkout_index_index.xml @@ -29,6 +29,9 @@ true + + true + diff --git a/view/frontend/layout/checkout_onepage_success.xml b/view/frontend/layout/checkout_onepage_success.xml new file mode 100644 index 0000000..4526c2f --- /dev/null +++ b/view/frontend/layout/checkout_onepage_success.xml @@ -0,0 +1,26 @@ + + + + + Success Page + + + + + + Thank you for your purchase! + + + + + + + + + + diff --git a/view/frontend/layout/default.xml b/view/frontend/layout/default.xml new file mode 100644 index 0000000..6ead6a9 --- /dev/null +++ b/view/frontend/layout/default.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/view/frontend/templates/onepage/link.phtml b/view/frontend/templates/onepage/link.phtml new file mode 100644 index 0000000..0451451 --- /dev/null +++ b/view/frontend/templates/onepage/link.phtml @@ -0,0 +1,36 @@ + +isPossibleOnepageCheckout()):?> + + + +

+ + + diff --git a/view/frontend/templates/success.phtml b/view/frontend/templates/success.phtml new file mode 100644 index 0000000..0741f86 --- /dev/null +++ b/view/frontend/templates/success.phtml @@ -0,0 +1,38 @@ + + + + +
+ getOrderId()):?> + getCanViewOrder()) :?> +

%s', $block->escapeHtml($block->getViewOrderUrl()), $block->escapeHtml($block->getOrderId()))) ?>

+ +

%1.', $block->escapeHtml($block->getOrderId())) ?>

+ +

+ + + getAdditionalInfoHtml() ?> + +
+
+ +
+
+
diff --git a/view/frontend/templates/webpayment.phtml b/view/frontend/templates/webpayment.phtml new file mode 100644 index 0000000..46387de --- /dev/null +++ b/view/frontend/templates/webpayment.phtml @@ -0,0 +1,451 @@ +getRequest()->getParams(); +if (array_key_exists('chromepay', $param)) { + ?> + + + _messageManager->addError(__("Error occurred, please check your card details.")); +} + +$cusToken = 'Bearer ' . $block->getCustomerToken(); + +/** @var $block \Sapient\Worldpay\Block\Webpayment */ +?> + + + + diff --git a/view/frontend/web/images/cc/visa_debit-ssl.png b/view/frontend/web/images/cc/visa_debit-ssl.png new file mode 100644 index 0000000..120f377 Binary files /dev/null and b/view/frontend/web/images/cc/visa_debit-ssl.png differ diff --git a/view/frontend/web/js/minicart.js b/view/frontend/web/js/minicart.js new file mode 100644 index 0000000..6616e0b --- /dev/null +++ b/view/frontend/web/js/minicart.js @@ -0,0 +1,202 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'uiComponent', + 'Magento_Customer/js/customer-data', + 'jquery', + 'ko', + 'underscore', + 'sidebar', + 'mage/translate', + 'mage/dropdown' +], function (Component, customerData, $, ko, _) { + 'use strict'; + + var sidebarInitialized = false, + addToCartCalls = 0, + miniCart; + + miniCart = $('[data-block=\'minicart\']'); + + /** + * @return {Boolean} + */ + function initSidebar() { + if (miniCart.data('mageSidebar')) { + miniCart.sidebar('update'); + } + + if (!$('[data-role=product-item]').length) { + return false; + } + miniCart.trigger('contentUpdated'); + + if (sidebarInitialized) { + return false; + } + sidebarInitialized = true; + miniCart.sidebar({ + 'targetElement': 'div.block.block-minicart', + 'url': { + 'checkout': window.checkout.checkoutUrl, + 'update': window.checkout.updateItemQtyUrl, + 'remove': window.checkout.removeItemUrl, + 'loginUrl': window.checkout.customerLoginUrl, + 'isRedirectRequired': window.checkout.isRedirectRequired + }, + 'button': { + 'checkout': '#top-cart-btn-checkout', + 'remove': '#mini-cart a.action.delete', + 'close': '#btn-minicart-close' + }, + 'showcart': { + 'parent': 'span.counter', + 'qty': 'span.counter-number', + 'label': 'span.counter-label' + }, + 'minicart': { + 'list': '#mini-cart', + 'content': '#minicart-content-wrapper', + 'qty': 'div.items-total', + 'subtotal': 'div.subtotal span.price', + 'maxItemsVisible': window.checkout.minicartMaxItemsVisible + }, + 'item': { + 'qty': ':input.cart-item-qty', + 'button': ':button.update-cart-item' + }, + 'confirmMessage': $.mage.__('Are you sure you would like to remove this item from the shopping cart?') + }); + } + + miniCart.on('dropdowndialogopen', function () { + initSidebar(); + }); + + + return Component.extend({ + shoppingCartUrl: window.checkout.shoppingCartUrl, + maxItemsToDisplay: window.checkout.maxItemsToDisplay, + checkoutNowUrl: window.checkout.shoppingCartUrl+'?chromepay=1', + proceedToCheckoutUrl: window.checkout.checkoutUrl, + + checkoutNowTitle: window.ChromepayButtonName, + chromepayEnabled: window.ChromepayEnabled, + chromePaymentMode: window.ChromePaymentMode, + + cart: {}, + + /** + * @override + */ + initialize: function () { + var self = this, + cartData = customerData.get('cart'); + + this.update(cartData()); + cartData.subscribe(function (updatedCart) { + addToCartCalls--; + this.isLoading(addToCartCalls > 0); + sidebarInitialized = false; + this.update(updatedCart); + initSidebar(); + }, this); + $('[data-block="minicart"]').on('contentLoading', function () { + addToCartCalls++; + self.isLoading(true); + }); + + if (cartData()['website_id'] !== window.checkout.websiteId) { + customerData.reload(['cart'], false); + } + + return this._super(); + }, + isLoading: ko.observable(false), + initSidebar: initSidebar, + + /** + * Close mini shopping cart. + */ + closeMinicart: function () { + $('[data-block="minicart"]').find('[data-role="dropdownDialog"]').dropdownDialog('close'); + }, + + /** + * @return {Boolean} + */ + closeSidebar: function () { + var minicart = $('[data-block="minicart"]'); + + minicart.on('click', '[data-action="close"]', function (event) { + event.stopPropagation(); + minicart.find('[data-role="dropdownDialog"]').dropdownDialog('close'); + }); + + return true; + }, + + /** + * @param {String} productType + * @return {*|String} + */ + getItemRenderer: function (productType) { + return this.itemRenderer[productType] || 'defaultRenderer'; + }, + + /** + * Update mini shopping cart content. + * + * @param {Object} updatedCart + * @returns void + */ + update: function (updatedCart) { + _.each(updatedCart, function (value, key) { + if (!this.cart.hasOwnProperty(key)) { + this.cart[key] = ko.observable(); + } + this.cart[key](value); + }, this); + }, + + /** + * Get cart param by name. + * @param {String} name + * @returns {*} + */ + getCartParam: function (name) { + if (!_.isUndefined(name)) { + if (!this.cart.hasOwnProperty(name)) { + this.cart[name] = ko.observable(); + } + } + + return this.cart[name](); + }, + + /** + * Returns array of cart items, limited by 'maxItemsToDisplay' setting + * @returns [] + */ + getCartItems: function () { + var items = this.getCartParam('items') || []; + + items = items.slice(parseInt(-this.maxItemsToDisplay, 10)); + + return items; + }, + + /** + * Returns count of cart line items + * @returns {Number} + */ + getCartLineItemsCount: function () { + var items = this.getCartParam('items') || []; + + return parseInt(items.length, 10); + } + }); +}); diff --git a/view/frontend/web/js/proceed-to-checkout.js b/view/frontend/web/js/proceed-to-checkout.js new file mode 100644 index 0000000..ad6bce5 --- /dev/null +++ b/view/frontend/web/js/proceed-to-checkout.js @@ -0,0 +1,37 @@ +define([ + 'jquery', + 'Magento_Customer/js/model/authentication-popup', + 'Magento_Customer/js/customer-data' +], function ($, authenticationPopup, customerData) { + 'use strict'; + + return function (config, element) { + + $(element).click(function (event) { + var cart = customerData.get('cart'), + customer = customerData.get('customer'); + + event.preventDefault(); + // + // if (!customer().firstname && cart().isGuestCheckoutAllowed === false) { + // authenticationPopup.showModal(); + // + // return false; + // } + + if(window.PaymentRequest && window.ChromepayEnabled == 1 && window.ChromePaymentMode == 'direct') { + var request = initPaymentRequest(); + onBuyClicked(request); + request = initPaymentRequest(); + + console.log('got it 111'); + + console.log(request); + //window.location = "http://worldpay.localhost:81/webpayment"; + } else { + location.href = this.options.url.checkout; + } + }); + + }; +}); \ No newline at end of file diff --git a/view/frontend/web/js/sidebar.js b/view/frontend/web/js/sidebar.js new file mode 100644 index 0000000..1926b77 --- /dev/null +++ b/view/frontend/web/js/sidebar.js @@ -0,0 +1,330 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'jquery', + 'Magento_Customer/js/model/authentication-popup', + 'Magento_Customer/js/customer-data', + 'Magento_Ui/js/modal/alert', + 'Magento_Ui/js/modal/confirm', + 'jquery/ui', + 'mage/decorate', + 'mage/collapsible', + 'mage/cookies' +], function ($, authenticationPopup, customerData, alert, confirm) { + 'use strict'; + + $.widget('mage.sidebar', { + options: { + isRecursive: true, + minicart: { + maxItemsVisible: 3 + } + }, + scrollHeight: 0, + + /** + * Create sidebar. + * @private + */ + _create: function () { + this._initContent(); + }, + + /** + * Update sidebar block. + */ + update: function () { + $(this.options.targetElement).trigger('contentUpdated'); + this._calcHeight(); + this._isOverflowed(); + }, + + /** + * @private + */ + _initContent: function () { + var self = this, + events = {}; + + this.element.decorate('list', this.options.isRecursive); + + /** + * @param {jQuery.Event} event + */ + events['click ' + this.options.button.close] = function (event) { + event.stopPropagation(); + $(self.options.targetElement).dropdownDialog('close'); + }; + events['click ' + this.options.button.checkout] = $.proxy(function () { + var cart = customerData.get('cart'), + customer = customerData.get('customer'); + + if (!customer().firstname && cart().isGuestCheckoutAllowed === false) { + // set URL for redirect on successful login/registration. It's postprocessed on backend. + $.cookie('login_redirect', this.options.url.checkout); + + if (this.options.url.isRedirectRequired) { + location.href = this.options.url.loginUrl; + } else { + authenticationPopup.showModal(); + } + + return false; + } + + if(window.PaymentRequest && window.ChromepayEnabled == 1 && window.ChromePaymentMode == 'direct') { + var request = initPaymentRequest(); + onBuyClicked(request); + // request = initPaymentRequest(); + } else { + location.href = this.options.url.checkout; + } + }, this); + + /** + * @param {jQuery.Event} event + */ + events['click ' + this.options.button.remove] = function (event) { + event.stopPropagation(); + confirm({ + content: self.options.confirmMessage, + actions: { + /** @inheritdoc */ + confirm: function () { + self._removeItem($(event.currentTarget)); + }, + + /** @inheritdoc */ + always: function (e) { + e.stopImmediatePropagation(); + } + } + }); + }; + + /** + * @param {jQuery.Event} event + */ + events['keyup ' + this.options.item.qty] = function (event) { + self._showItemButton($(event.target)); + }; + + /** + * @param {jQuery.Event} event + */ + events['click ' + this.options.item.button] = function (event) { + event.stopPropagation(); + self._updateItemQty($(event.currentTarget)); + }; + + /** + * @param {jQuery.Event} event + */ + events['focusout ' + this.options.item.qty] = function (event) { + self._validateQty($(event.currentTarget)); + }; + + this._on(this.element, events); + this._calcHeight(); + this._isOverflowed(); + }, + + /** + * Add 'overflowed' class to minicart items wrapper element + * + * @private + */ + _isOverflowed: function () { + var list = $(this.options.minicart.list), + cssOverflowClass = 'overflowed'; + + if (this.scrollHeight > list.innerHeight()) { + list.parent().addClass(cssOverflowClass); + } else { + list.parent().removeClass(cssOverflowClass); + } + }, + + /** + * @param {HTMLElement} elem + * @private + */ + _showItemButton: function (elem) { + var itemId = elem.data('cart-item'), + itemQty = elem.data('item-qty'); + + if (this._isValidQty(itemQty, elem.val())) { + $('#update-cart-item-' + itemId).show('fade', 300); + } else if (elem.val() == 0) { //eslint-disable-line eqeqeq + this._hideItemButton(elem); + } else { + this._hideItemButton(elem); + } + }, + + /** + * @param {*} origin - origin qty. 'data-item-qty' attribute. + * @param {*} changed - new qty. + * @returns {Boolean} + * @private + */ + _isValidQty: function (origin, changed) { + return origin != changed && //eslint-disable-line eqeqeq + changed.length > 0 && + changed - 0 == changed && //eslint-disable-line eqeqeq + changed - 0 > 0; + }, + + /** + * @param {Object} elem + * @private + */ + _validateQty: function (elem) { + var itemQty = elem.data('item-qty'); + + if (!this._isValidQty(itemQty, elem.val())) { + elem.val(itemQty); + } + }, + + /** + * @param {HTMLElement} elem + * @private + */ + _hideItemButton: function (elem) { + var itemId = elem.data('cart-item'); + + $('#update-cart-item-' + itemId).hide('fade', 300); + }, + + /** + * @param {HTMLElement} elem + * @private + */ + _updateItemQty: function (elem) { + var itemId = elem.data('cart-item'); + + this._ajax(this.options.url.update, { + 'item_id': itemId, + 'item_qty': $('#cart-item-' + itemId + '-qty').val() + }, elem, this._updateItemQtyAfter); + }, + + /** + * Update content after update qty + * + * @param {HTMLElement} elem + */ + _updateItemQtyAfter: function (elem) { + this._hideItemButton(elem); + }, + + /** + * @param {HTMLElement} elem + * @private + */ + _removeItem: function (elem) { + var itemId = elem.data('cart-item'); + + this._ajax(this.options.url.remove, { + 'item_id': itemId + }, elem, this._removeItemAfter); + }, + + /** + * Update content after item remove + * + * @param {Object} elem + * @private + */ + _removeItemAfter: function (elem) { + var productData = customerData.get('cart')().items.find(function (item) { + return Number(elem.data('cart-item')) === Number(item['item_id']); + }); + + $(document).trigger('ajax:removeFromCart', productData['product_sku']); + }, + + /** + * @param {String} url - ajax url + * @param {Object} data - post data for ajax call + * @param {Object} elem - element that initiated the event + * @param {Function} callback - callback method to execute after AJAX success + */ + _ajax: function (url, data, elem, callback) { + $.extend(data, { + 'form_key': $.mage.cookies.get('form_key') + }); + + $.ajax({ + url: url, + data: data, + type: 'post', + dataType: 'json', + context: this, + + /** @inheritdoc */ + beforeSend: function () { + elem.attr('disabled', 'disabled'); + }, + + /** @inheritdoc */ + complete: function () { + elem.attr('disabled', null); + } + }) + .done(function (response) { + var msg; + + if (response.success) { + callback.call(this, elem, response); + } else { + msg = response['error_message']; + + if (msg) { + alert({ + content: msg + }); + } + } + }) + .fail(function (error) { + console.log(JSON.stringify(error)); + }); + }, + + /** + * Calculate height of minicart list + * + * @private + */ + _calcHeight: function () { + var self = this, + height = 0, + counter = this.options.minicart.maxItemsVisible, + target = $(this.options.minicart.list), + outerHeight; + + self.scrollHeight = 0; + target.children().each(function () { + + if ($(this).find('.options').length > 0) { + $(this).collapsible(); + } + outerHeight = $(this).outerHeight(); + + if (counter-- > 0) { + height += outerHeight; + } + self.scrollHeight += outerHeight; + }); + + target.parent().height(height); + } + }); + + return $.mage.sidebar; +}); diff --git a/view/frontend/web/js/view/payment/method-renderer/apm-method.js b/view/frontend/web/js/view/payment/method-renderer/apm-method.js index 1e23157..0cd566b 100644 --- a/view/frontend/web/js/view/payment/method-renderer/apm-method.js +++ b/view/frontend/web/js/view/payment/method-renderer/apm-method.js @@ -74,35 +74,34 @@ define( serviceUrl, JSON.stringify(payload) ).done( function (apiresponse) { - var response = JSON.parse(apiresponse); - if(response.length){ - for (var responsekey in response) { - var found = false; - for(var key in ccavailabletypes) { - if(response[responsekey] == key.toUpperCase()){ - found = true; - cckey = key; - ccvalue = ccavailabletypes[key]; - break; - } - } - - if(found){ - filtercclist[cckey] = ccvalue; - } + var response = JSON.parse(apiresponse); + if(response.length){ + $.each(response, function(responsekey, value){ + var found = false; + $.each(ccavailabletypes, function(key, value){ + if(response[responsekey] == key.toUpperCase()){ + found = true; + cckey = key; + ccvalue = ccavailabletypes[key]; + return false; + } + }); + if(found){ + filtercclist[cckey] = ccvalue; } - }else{ - filtercclist = ccavailabletypes; - } + }); + }else{ + filtercclist = ccavailabletypes; + } - var ccTypesArr1 = _.map(filtercclist, function (value, key) { - return { - 'ccValue': key, - 'ccLabel': value + var ccTypesArr1 = _.map(filtercclist, function (value, key) { + return { + 'ccValue': key, + 'ccLabel': value }; - }); + }); - fullScreenLoader.stopLoader(); + fullScreenLoader.stopLoader(); ccTypesArr(ccTypesArr1); } ).fail( @@ -213,5 +212,3 @@ define( }); } ); - - diff --git a/view/frontend/web/js/view/payment/method-renderer/cc-method.js b/view/frontend/web/js/view/payment/method-renderer/cc-method.js index 2fb1cd6..f7b41fb 100644 --- a/view/frontend/web/js/view/payment/method-renderer/cc-method.js +++ b/view/frontend/web/js/view/payment/method-renderer/cc-method.js @@ -122,24 +122,27 @@ define( function (apiresponse) { var response = JSON.parse(apiresponse); if(response.length){ - if(savedcardlists.length > 0){ - for (var key in savedcardlists) { - var method = savedcardlists[key]['method']; - var found = false; - for (var responsekey in response) { - if(method.toUpperCase() == response[responsekey]){ - found = true; - break; + if (savedcardlists.length) { + $.each(savedcardlists, function(key, value){ + var method = savedcardlists[key]['method']; + if (typeof method == 'undefined') { + return true; } - } - - if(found){ - filtercards.push(savedcardlists[key]); - } + // commented for saved debit card access +// var found = false; +// $.each(response, function(responsekey, value){ +// if(method.toUpperCase() == response[responsekey]){ +// found = true; +// return false; +// } +// }); +// if(found){ + filtercards.push(savedcardlists[key]); + //} + }); } - } - for (var responsekey in response) { + for (var responsekey in response) { var found = false; for(var key in ccavailabletypes) { if(key != 'savedcard'){ @@ -350,23 +353,27 @@ define( }else if($form.validation() && $form.validation('isValid')){ //Direct form handle this.saveMyCard = $('#' + this.getCode() + '_save_card').is(":checked"); - if (this.isClientSideEncryptionEnabled() && this.intigrationmode == 'direct') { - var that = this; - require(["https://payments.worldpay.com/resources/cse/js/worldpay-cse-1.0.1.min.js"], function(worldpay){ - worldpay.setPublicKey(that.getCsePublicKey()); - var cseData = { - cvc: that.creditCardVerificationNumber(), - cardHolderName: $('#' + that.getCode() + '_cc_name').val(), - cardNumber: that.creditCardNumber(), - expiryMonth: that.creditCardExpMonth(), - expiryYear: that.creditCardExpYear() - }; - var encryptedData = worldpay.encrypt(cseData); - that.cseData = encryptedData; - //place order with direct CSE method - self.placeOrder(); - }); - } else if(this.intigrationmode == 'redirect'){ + if (this.intigrationmode == 'direct') { + var that = this; + if(this.isClientSideEncryptionEnabled()){ + require(["https://payments.worldpay.com/resources/cse/js/worldpay-cse-1.0.1.min.js"], function (worldpay) { + worldpay.setPublicKey(that.getCsePublicKey()); + var cseData = { + cvc: that.creditCardVerificationNumber(), + cardHolderName: $('#' + that.getCode() + '_cc_name').val(), + cardNumber: that.creditCardNumber(), + expiryMonth: that.creditCardExpMonth(), + expiryYear: that.creditCardExpYear() + }; + var encryptedData = worldpay.encrypt(cseData); + that.cseData = encryptedData; + //place order with direct CSE method + self.placeOrder(); + }); + } else{ + self.placeOrder(); + } + }else if(this.intigrationmode == 'redirect'){ //place order with Redirect CSE Method self.placeOrder(); } @@ -385,4 +392,4 @@ define( } }); } -); +); \ No newline at end of file diff --git a/view/frontend/web/js/view/payment/method-renderer/wallets-method.js b/view/frontend/web/js/view/payment/method-renderer/wallets-method.js new file mode 100644 index 0000000..83862cf --- /dev/null +++ b/view/frontend/web/js/view/payment/method-renderer/wallets-method.js @@ -0,0 +1,239 @@ +/*browser:true*/ +/*global define*/ +define( + [ + 'Magento_Payment/js/view/payment/cc-form', + 'jquery', + 'Magento_Checkout/js/model/quote', + 'Magento_Customer/js/model/customer', + 'Magento_Payment/js/model/credit-card-validation/validator', + 'mage/url', + 'Magento_Checkout/js/action/place-order', + 'Magento_Checkout/js/action/redirect-on-success', + 'ko', + 'Magento_Checkout/js/action/set-payment-information', + 'Magento_Checkout/js/model/error-processor', + 'Magento_Checkout/js/model/url-builder', + 'mage/storage', + 'Magento_Checkout/js/model/full-screen-loader', + 'googlePay' + ], + function (Component, $, quote, customer,validator, url, placeOrderAction, redirectOnSuccessAction,ko, setPaymentInformationAction, errorProcessor, urlBuilder, storage, fullScreenLoader, googlePay) { + 'use strict'; + var ccTypesArr = ko.observableArray([]); + var paymentService = false; + var billingAddressCountryId = ""; + var googleResponse = ""; + + /***** Google pay Elements Started */ + const baseRequest = {apiVersion: 2, apiVersionMinor: 0 }; + const allowedCardNetworks = window.checkoutConfig.payment.ccform.googlePaymentMethods.split(","); + const allowedCardAuthMethods = window.checkoutConfig.payment.ccform.googleAuthMethods.split(","); + const tokenizationSpecification = { + type: 'PAYMENT_GATEWAY', + parameters: { + 'gateway': window.checkoutConfig.payment.ccform.googleGatewayMerchantname, + 'gatewayMerchantId': window.checkoutConfig.payment.ccform.googleGatewayMerchantid + } + }; + + const baseCardPaymentMethod = { + type: 'CARD', + parameters: { + allowedAuthMethods: allowedCardAuthMethods, + allowedCardNetworks: allowedCardNetworks + } + }; + const cardPaymentMethod = Object.assign( + {}, + baseCardPaymentMethod, + { + tokenizationSpecification: tokenizationSpecification + } + ); + + var paymentDataRequest = null; + var paymentsClient = null; + /***** Google pay Elements End */ + + if (quote.billingAddress()) { + billingAddressCountryId = quote.billingAddress._latestValue.countryId; + } + + function getGooglePaymentDataRequest(){ + const paymentDataRequest = Object.assign({}, baseRequest); + paymentDataRequest.allowedPaymentMethods = [cardPaymentMethod]; + paymentDataRequest.transactionInfo = getGoogleTransactionInfo(); + paymentDataRequest.merchantInfo = { + // @todo a merchant ID is available for a production environment after approval by Google + // See {@link https://developers.google.com/pay/api/web/guides/test-and-deploy/integration-checklist|Integration checklist} + + merchantId: 'b21b1d14ba43077', + merchantName: window.checkoutConfig.payment.ccform.googleGatewayMerchantname + }; + return paymentDataRequest; + } + function getGoogleTransactionInfo(){ + return { + currencyCode: window.checkoutConfig.totalsData.base_currency_code, + totalPriceStatus: 'FINAL', + // set to cart total + totalPrice: parseFloat(window.checkoutConfig.totalsData.base_grand_total).toFixed(2) + }; + } + function getGooglePaymentsClient() { + if ( paymentsClient === null ) { + paymentsClient = new google.payments.api.PaymentsClient({environment: window.checkoutConfig.payment.general.environmentMode}); + } + return paymentsClient; + } + + return Component.extend({ + defaults: { + redirectAfterPlaceOrder: false, + direcTemplate: 'Sapient_Worldpay/payment/wallets', + cardHolderName:'', + SavedcreditCardVerificationNumber:'', + cseData:null + }, + + initialize: function () { + this._super(); + this.selectedCCType(null); + if(paymentService == false) { + this.filterwalletajax(1); + } + + }, + initObservable: function () { + var that = this; + this._super(); + quote.billingAddress.subscribe(function (newAddress) { + if (quote.billingAddress._latestValue != null && quote.billingAddress._latestValue.countryId != billingAddressCountryId) { + billingAddressCountryId = quote.billingAddress._latestValue.countryId; + that.filterwalletajax(1); + paymentService = true; + } + }); + return this; + }, + filterwalletajax: function(statusCheck = null){ + if(!statusCheck){ + return; + } + if (quote.billingAddress._latestValue == null) { + return; + } + var ccavailabletypes = this.getCcAvailableTypes(); + var filtercclist = {}; + + fullScreenLoader.startLoader(); + + filtercclist = ccavailabletypes; + + var ccTypesArr1 = _.map(filtercclist, function (value, key) { + return { + 'ccValue': key, + 'ccLabel': value + }; + }); + fullScreenLoader.stopLoader(); + ccTypesArr(ccTypesArr1); + //filtersavedcardLists(filtercards); + }, + + getCcAvailableTypesValues : function(){ + return ccTypesArr; + }, + + availableCCTypes : function(){ + return ccTypesArr; + }, + selectedCCType : ko.observable(), + //paymentToken:ko.observable(), + + getCode: function() { + return 'worldpay_wallets'; + }, + + getTemplate: function(){ + return this.direcTemplate; + }, + + /** + * Get payment icons + * @param {String} type + * @returns {Boolean} + */ + getIcons: function (type) { + return window.checkoutConfig.payment.ccform.wpicons.hasOwnProperty(type) ? + window.checkoutConfig.payment.ccform.wpicons[type] + : false; + }, + + getTitle: function() { + return window.checkoutConfig.payment.ccform.walletstitle ; + }, + isActive: function() { + return true; + }, + paymentMethodSelection: function() { + return window.checkoutConfig.payment.ccform.paymentMethodSelection; + }, + getselectedCCType : function(){ + if(this.paymentMethodSelection()=='radio'){ + return $("input[name='wallets_type']:checked").val(); + } else{ + return this.selectedCCType(); + } + }, + + /** + * @override + */ + getData: function () { + return { + 'method': "worldpay_wallets", + 'additional_data': { + 'cc_type': this.getselectedCCType(), + 'walletResponse' : googleResponse + } + }; + }, + preparePayment:function() { + var self = this; + var $form = $('#' + this.getCode() + '-form'); + if(this.getselectedCCType()== undefined){ + $('.mage-error').css({'display' : 'block','margin-bottom': '7px'}); + $('.mage-error').html('Please select one of the options.'); + return false; + } + if (this.getselectedCCType()=='PAYWITHGOOGLE-SSL') { + const paymentsClient = getGooglePaymentsClient(); + const paymentDataRequest = getGooglePaymentDataRequest(); + paymentDataRequest.transactionInfo = getGoogleTransactionInfo(); + paymentsClient.loadPaymentData(paymentDataRequest) + .then(function(paymentData) { + googleResponse = JSON.stringify(paymentData); + if($form.validation() && $form.validation('isValid')){ + self.placeOrder(); + }else { + return $form.validation() && $form.validation('isValid'); + } + }) + .catch(function(err) { + // show error in developer console for debugging + console.log('payment client resposnse else condition'); + console.error(err); + return false; + }); + } + + }, + afterPlaceOrder: function (data, event) { + window.location.replace(url.build('worldpay/wallets/success')); + } + + }); + } +); diff --git a/view/frontend/web/js/view/payment/methodrenderer.js b/view/frontend/web/js/view/payment/methodrenderer.js index 72f83f9..e0be796 100644 --- a/view/frontend/web/js/view/payment/methodrenderer.js +++ b/view/frontend/web/js/view/payment/methodrenderer.js @@ -18,10 +18,12 @@ define( 'use strict'; var CCcomponent = 'Sapient_Worldpay/js/view/payment/method-renderer/cc-method'; var APMcomponent = 'Sapient_Worldpay/js/view/payment/method-renderer/apm-method'; + var Walletscomponent = 'Sapient_Worldpay/js/view/payment/method-renderer/wallets-method'; var methods = [ {type: 'worldpay_cc', component: CCcomponent}, - {type: 'worldpay_apm', component: APMcomponent} + {type: 'worldpay_apm', component: APMcomponent}, + {type: 'worldpay_wallets', component: Walletscomponent} ]; $.each(methods, function (k, method) { diff --git a/view/frontend/web/template/minicart/content.html b/view/frontend/web/template/minicart/content.html new file mode 100644 index 0000000..7c6fb39 --- /dev/null +++ b/view/frontend/web/template/minicart/content.html @@ -0,0 +1,114 @@ + +
+ + + + + +
+ +
+ + + +
+ + + + + +
+ + + + +
+
+ + +
+
+
+ + + +
+
    + +
+
+
+ + + + +

+

+
+ + + +
+
+
+
+ +
+
+ + + +
+
+ +
+ +
+
+ diff --git a/view/frontend/web/template/payment/wallets.html b/view/frontend/web/template/payment/wallets.html new file mode 100644 index 0000000..3a33592 --- /dev/null +++ b/view/frontend/web/template/payment/wallets.html @@ -0,0 +1,82 @@ +
+
+ + + +
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + +
+
+
+
+ + + + +
+ + + +
+
+ + + +
+
+
+ +
+
+
+