'UK', 'de' => 'DE', ); function __construct(& $subject, $config) { //if (self::$_this) // return self::$_this; parent::__construct($subject, $config); $this->_loggable = TRUE; $this->tableFields = array_keys($this->getTableSQLFields()); $this->_tablepkey = 'id'; $this->_tableId = 'id'; $varsToPush = $this->getVarsToPush(); $this->setConfigParameterable($this->_configTableFieldName, $varsToPush); $this->setCryptedFields(array('accessKey', 'secretKey')); $amazon_library = JPATH_SITE . DS . 'plugins' . DS . 'vmpayment' . DS . 'amazon' . DS . 'library'; //set_include_path(get_include_path() . PATH_SEPARATOR . realpath(dirname(__FILE__) . "/../../.")); set_include_path($amazon_library); $this->loadAmazonClass('OffAmazonPaymentsService_Client'); if (!JFactory::getApplication()->isSite()) { vmJsApi::jQuery(); JFactory::getDocument()->addScript(JURI::root(true) . '/plugins/vmpayment/amazon/assets/js/admin.js'); JFactory::getDocument()->addStyleSheet(JURI::root(true) . '/plugins/vmpayment/amazon/assets/css/amazon-admin.css'); } } protected function getVmPluginCreateTableSQL () { return $this->createTableSQL('Payment Amazon Table'); } function getTableSQLFields() { $SQLfields = array( 'id' => 'int(1) unsigned NOT NULL AUTO_INCREMENT', 'virtuemart_order_id' => 'int(11) UNSIGNED', 'order_number' => 'char(64)', 'virtuemart_paymentmethod_id' => 'mediumint(1) UNSIGNED', 'payment_name' => 'varchar(5000)', 'amazonOrderReferenceId' => 'char(64)', //'payment_params' => 'varchar(5000)', 'order_is_digital' => 'smallint(1)', 'payment_order_total' => 'decimal(15,5)', 'payment_currency' => 'smallint(1)', 'email_currency' => 'smallint(1)', 'recurring' => 'varchar(512)', 'recurring_number' => 'smallint(1)', 'recurring_periodicity' => 'smallint(1)', 'cost_per_transaction' => 'decimal(10,2)', 'cost_percent_total' => 'decimal(10,2)', 'tax_id' => 'smallint(1)', 'amazon_response_amazonReferenceId' => 'char(64)', 'amazon_response_amazonAuthorizationId' => 'char(64)', 'amazon_response_amazonCaptureId' => 'char(64)', 'amazon_response_amazonRefundId' => 'char(64)', 'amazon_response_state' => 'char(64)', 'amazon_response_reasonCode' => 'char(64)', 'amazon_response_reasonDescription' => 'char(64)', 'amazon_class_request_type' => 'text', 'amazon_request' => 'text', 'amazon_class_response_type' => 'text', 'amazon_response' => 'text', 'amazon_class_notification_type' => 'text', 'amazon_notification' => 'text', ); return $SQLfields; } private function renderSignInButton($cart) { if (!$this->checkConditionSignIn($cart)) { return NULL; } //$cart->setOutOfCheckout(); $client = $this->getOffAmazonPaymentsService_Client(); if ($client == NULL) { return; } $buttonWidgetImageURL = $this->getButtonWidgetImageURL(); if (!empty($buttonWidgetImageURL)) { $this->addWidgetUrlScript($client); /** we do not need that. The button or the payment method do not appear atm in the displayListFE trigger * if ($selected == $this->_currentMethod->virtuemart_paymentmethod_id) { * $checked = 'checked="checked"'; * } else { * $checked = ''; * } */ $redirect_page = $this->getSignInRedirectPage(); $onlyDigitalGoods = $this->isOnlyDigitalGoods($cart); $signInButton = $this->renderByLayout('signin', array( 'buttonWidgetImageURL' => $buttonWidgetImageURL, 'virtuemart_paymentmethod_id' => $this->_currentMethod->virtuemart_paymentmethod_id, 'sellerId' => $this->_currentMethod->sellerId, 'sign_in_css' => $this->_currentMethod->sign_in_css, 'include_amazon_css' => $this->_currentMethod->include_amazon_css, 'renderAmazonAddressBook' => (!$onlyDigitalGoods), 'redirect_page' => $redirect_page, 'layout' => $cart->layout, )); return $signInButton; } } private function redisplayAddressbookWallet($client, $cart, $order_number) { if ($cart == NULL) { $cart = VirtueMartCart::getCart(); } $this->addWidgetUrlScript($client); if (empty($this->_amazonOrderReferenceId)) { $this->_amazonOrderReferenceId = $this->getAmazonOrderReferenceIdFromSession(); if (empty($this->_amazonOrderReferenceId)) { $this->leaveAmazonCheckout(); return; } } $html = $this->renderByLayout('addressbook_wallet', array( 'virtuemart_paymentmethod_id' => $this->_currentMethod->virtuemart_paymentmethod_id, 'sellerId' => $this->_currentMethod->sellerId, 'addressbook_designWidth' => $this->getPixelValue($this->_currentMethod->addressbook_designWidth), 'addressbook_designHeight' => $this->getPixelValue($this->_currentMethod->addressbook_designHeight), 'wallet_designWidth' => $this->getPixelValue($this->_currentMethod->wallet_designWidth), 'wallet_designHeight' => $this->getPixelValue($this->_currentMethod->wallet_designHeight), 'include_amazon_css' => $this->_currentMethod->include_amazon_css, 'amazonOrderReferenceId' => $this->_amazonOrderReferenceId, 'renderAddressBook' => false, 'renderWalletBook' => true, 'readOnlyWidgets' => "Edit", 'captureNow' => $this->isCaptureImmediate($cart) )); $html .= $this->renderByLayout('display_wallet', array( 'virtuemart_paymentmethod_id' => $this->_currentMethod->virtuemart_paymentmethod_id, 'order_number' => $order_number, 'include_amazon_css' => $this->_currentMethod->include_amazon_css, 'useXHTML' => $cart->useXHTML, 'useSSL' => $cart->useSSL, )); return $html; } private function renderAddressbookWallet($readOnlyWidgets = false) { //if ($this->getRenderAddressDoneFromSession()) { return;} $this->loadVmClass('VirtueMartCart', JPATH_VM_SITE . DS . 'helpers' . DS . 'cart.php'); $cart = VirtueMartCart::getCart(); $this->setCartLayout($cart); $client = $this->getOffAmazonPaymentsService_Client(); if ($client == NULL) { return; } $this->addWidgetUrlScript($client); if (empty($this->_amazonOrderReferenceId)) { $this->_amazonOrderReferenceId = $this->getAmazonOrderReferenceIdFromSession(); if (empty($this->_amazonOrderReferenceId)) { $this->leaveAmazonCheckout(); return; } } $renderWalletBook = $cart->virtuemart_shipmentmethod_id; //$this->setRenderAddressDoneInSession(); $this->_amazonOrderReferenceId = $this->getAmazonOrderReferenceIdFromSession(); $onlyDigitalGoods = $this->isOnlyDigitalGoods($cart); $html = $this->renderByLayout('addressbook_wallet', array( 'virtuemart_paymentmethod_id' => $this->_currentMethod->virtuemart_paymentmethod_id, 'sellerId' => $this->_currentMethod->sellerId, 'include_amazon_css' => $this->_currentMethod->include_amazon_css, 'addressbook_designWidth' => $this->getPixelValue($this->_currentMethod->addressbook_designWidth), 'addressbook_designHeight' => $this->getPixelValue($this->_currentMethod->addressbook_designHeight), 'wallet_designWidth' => $this->getPixelValue($this->_currentMethod->wallet_designWidth), 'wallet_designHeight' => $this->getPixelValue($this->_currentMethod->wallet_designHeight), 'amazonOrderReferenceId' => $this->_amazonOrderReferenceId, 'renderAddressBook' => !$onlyDigitalGoods, 'renderWalletBook' => $renderWalletBook, 'readOnlyWidgets' => $readOnlyWidgets ? 'Read' : "Edit", 'captureNow' => $this->isCaptureImmediate($cart) )); echo $html; } private function checkConditionSignIn($cart) { $cart_prices = array(); $cart_prices['salesPrice'] = $cart->pricesUnformatted['billTotal']; // atm, we only display the SignIn button via the trigger plgVmOnCheckoutAdvertise //if ($this->doSignInDisplay($sign_in_display) && $this->checkConditions($cart, $this->_currentMethod, $cart_prices) && $this->checkProductConditions($product, $this->_currentMethod)) { if ($this->checkConditions($cart, $this->_currentMethod, $cart_prices)) { return true; } return false; } /** * Check if the payment conditions are fulfilled for this payment method * * @author: Valerie Isaksen * * @param $cart_prices : cart prices * @param $payment * @return true: if the conditions are fulfilled, false otherwise * */ protected function checkConditions ($cart, $method, $cart_prices) { //vmTrace('checkConditions', true); //$this->debugLog( $cart_prices['salesPrice'], 'checkConditions','debug'); $this->_currentMethod = $method; if ($this->isValidLanguage() && $this->isValidAmount($cart_prices['salesPrice']) && $this->isValidProductCategories($cart) && $this->isValidIP() ) { return true; } return false; } /** * @return bool */ private function isValidCountry ($virtuemart_country_id) { $countries = array(); if (!empty($this->_currentMethod->countries)) { if (!is_array($this->_currentMethod->countries)) { $countries[0] = $this->_currentMethod->countries; } else { $countries = $this->_currentMethod->countries; } } if (count($countries) == 0 || in_array($virtuemart_country_id, $countries)) { return TRUE; } return false; } /** * Switch for enabling / disabling Hidden Button Mode. * @return bool */ private function isValidIP() { if (empty($this->_currentMethod->ip_whitelist)) { return true; } $ip_whitelist = explode(";", $this->_currentMethod->ip_whitelist); if (in_array($_SERVER['REMOTE_ADDR'], $ip_whitelist)) { return true; } return false; } /** * $requiredKeys = array('merchantId', * 'accessKey', * 'secretKey', * 'region', * 'environment', * 'applicationName', * 'applicationVersion' */ private function getOffAmazonPaymentsService_Client () { $config['serviceURL'] = ''; $config['widgetURL'] = ''; $config['caBundleFile'] = ''; $config['clientId'] = ''; $config['merchantId'] = $this->_currentMethod->sellerId; $config['accessKey'] = $this->_currentMethod->accessKey; $config['secretKey'] = $this->_currentMethod->secretKey; $config['applicationName'] = 'VirtueMart'; $config['applicationVersion'] = '${PHING.VM.RELEASE}'; $config['region'] = $this->_currentMethod->region; $config['environment'] = $this->_currentMethod->environment; if ($this->_currentMethod->region == "other") { $prefix = $this->_currentMethod->environment; $serviceURL = $prefix . "_serviceURL"; $widgetURL = $prefix . "_widgetURL"; $config['serviceURL'] = $this->_currentMethod->$serviceURL; $config['widgetURL'] == $this->_currentMethod->$widgetURL; } try { $client = new OffAmazonPaymentsService_Client($config); } catch (Exception $e) { $this->amazonError(__FUNCTION__ . ' ' . $e->getMessage(), $e->getCode()); return NULL; } return $client; } private function amazonError ($message, $code = '') { $public_msg = ''; if ($this->_currentMethod->debug) { $public_msg = $message; } vmError($message . " (" . $code . ")", $public_msg); } private function getButtonWidgetImageURL () { $region = $this->_currentMethod->region; $region_europe = array('UK', 'DE'); $url = ''; if (in_array($region, $region_europe)) { if ($region == "UK") { $domain = "co.uk"; } else { $domain = "de"; } if ($this->_currentMethod->environment == 'sandbox') { $mode = "-sandbox"; } else { //TODO $mode = ""; } $url = "https://payments" . $mode . ".amazon." . $domain . "/gp/widgets/button?sellerId=" . $this->_currentMethod->sellerId . "&size=" . $this->_currentMethod->sign_in_widget_size . "&color=" . $this->_currentMethod->sign_in_widget_color . ""; } else { if ($this->_currentMethod->environment == 'sandbox') { $url = $this->_currentMethod->sandbox_signin; } else { $url = $this->_currentMethod->production_signin; } } return $url; } private function addWidgetUrlScript ($client) { if (!self::$widgetScriptLoaded) { $widgetURL = $client->getMerchantValues()->getWidgetUrl(); JHTML::script($widgetURL, false); self::$widgetScriptLoaded = true; } } /** * @return */ private function getSignInRedirectPage () { $url = 'index.php?option=com_virtuemart&view=pluginresponse&task=pluginnotification&format=raw&nt=getAmazonSessionId&pm=' . $this->_currentMethod->virtuemart_paymentmethod_id . '&Itemid=' . vRequest::getInt('Itemid') . '&lang=' . vRequest::getCmd('lang', ''); //$_amazonOrderReferenceId = $this->getAmazonOrderReferenceId(); if ($this->_amazonOrderReferenceId) { //$url .= '&session=' . $this->_amazonOrderReferenceId; } $cart = VirtueMartCart::getCart(); return JRoute::_($url, $cart->useXHTML, $cart->useSSL); } /** * @param $product * @param $productDisplay * @return bool function plgVmOnProductDisplayPayment ($product, &$productDisplay) { * * $vendorId = 1; * if ($this->getPluginMethods($vendorId) === 0) { * return FALSE; * } * * $productDisplay = $this->renderSignInButton('product', false, $product); * return TRUE; * } */ /** * @return null */ public function plgVmOnPaymentNotification () { $virtuemart_paymentmethod_id = vRequest::getInt('pm', 0); if (!($this->_currentMethod = $this->getVmPluginMethod($virtuemart_paymentmethod_id))) { return NULL; // Another method was selected, do nothing } if (!$this->selectedThisElement($this->_currentMethod->payment_element)) { return FALSE; } $notificationTask = vRequest::getCmd('nt', ''); switch ($notificationTask) { case 'getAmazonSessionId': if (!class_exists('VirtueMartCart')) { require(JPATH_VM_SITE . DS . 'helpers' . DS . 'cart.php'); } $cart = VirtueMartCart::getCart(false); $this->saveAmazonOrderReferenceId($cart); $this->saveBTandSTInSession($cart); $this->setCartLayout($cart, false); $this->updateCartWithDefaultAmazonAddress($cart, $this->isOnlyDigitalGoods($cart)); $this->redirectToCart(); break; case 'ipn': $this->ipn(); break; default: $this->amazonError(vmText::_('VMPAYMENT_AMAZON_INVALID_NOTIFICATION_TASK')); return; } } /** * IPNs requires SSL. All merchant cannot have SSL. A system plugin simulate a cron job */ public function plgVmRetrieveIPN () { // check if table exists $db = JFactory::getDBO(); $query = 'SHOW TABLES LIKE "' . str_replace('#__', $db->getPrefix(), $this->_tablename) . '"'; $db->setQuery($query); if (!$db->loadResult()) { return false; } $q = "SELECT * FROM " . $this->_tablename . " WHERE ( ( `amazon_class_response_type` LIKE 'OffAmazonPaymentsService_Model_ConfirmOrderReferenceResponse' AND `amazon_response_state` IN ( 'Open', 'Suspended') ) OR ( `amazon_class_response_type` LIKE 'OffAmazonPaymentsService_Model_AuthorizeResponse' AND `amazon_response_state` IN ('Pending', 'Open') ) OR ( `amazon_class_response_type` LIKE 'OffAmazonPaymentsService_Model_CaptureResponse' AND `amazon_response_state` IN ('Pending') ) OR ( `amazon_class_response_type` LIKE 'OffAmazonPaymentsService_Model_RefundResponse' AND `amazon_response_state` IN ('Pending') ) ) AND `id` in (SELECT MAX( id ) FROM " . $this->_tablename . " GROUP BY virtuemart_order_id ) ORDER BY `created_on` DESC "; $db->setQuery($q); $payments = $db->loadObjectList(); $done = array(); //$this->debugLog("
" . var_export($payments, true) . "
", __FUNCTION__, 'debug'); $this->loadAmazonServicesClasses(); if (!$payments) { return; } foreach ($payments as $payment) { if (in_array($payment->order_number, $done)) { continue; } if (!$payment->amazon_request) { continue; } if (!($this->_currentMethod = $this->getVmPluginMethod($payment->virtuemart_paymentmethod_id))) { continue; } if ($payment->amazon_class_response_type == 'OffAmazonPaymentsService_Model_ConfirmOrderReferenceResponse') { $this->retrieveIPNConfirmOrderReference($payment); } elseif ($payment->amazon_class_response_type == 'OffAmazonPaymentsService_Model_RefundResponse') { $this->retrieveIPNRefund($payment); } elseif ($payment->amazon_class_response_type == 'OffAmazonPaymentsService_Model_AuthorizeResponse') { $this->retrieveIPNAuthorization($payment); } elseif ($payment->amazon_class_response_type == 'OffAmazonPaymentsService_Model_CaptureResponse') { $this->retrieveIPNCapture($payment); } $done[] = $payment->order_number; } } private function getNumberOfDays ($payments) { $created_on = strtotime($payments[0]->created_on); $now = date_create(date('Y-m-d')); $now = time(); //$number = date_diff($now, $created_on); //$number->format('%a'); $days_between = ceil(abs($created_on - $now) / 86400); return $days_between; } /** * if Open and > 180 days=> poll * if Suspended => poll * @param $payment */ private function retrieveIPNConfirmOrderReference ($payment) { $this->loadVmClass('VirtueMartModelOrders', JPATH_VM_ADMINISTRATOR . DS . 'models' . DS . 'orders.php'); $orderModel = VmModel::getModel('orders'); $order = $orderModel->getOrder($payment->virtuemart_order_id); if (!($payments = $this->getDatasByOrderId($payment->virtuemart_order_id))) { // JError::raiseWarning(500, $db->getErrorMsg()); return null; } if ($payment->amazon_response_state == 'Suspended' OR ($payment->amazon_response_state == 'Open' AND $this->getNumberOfDays($payments) > 180)) { $this->getAuthorizationState($payments, $order); } } /** * if Pending => poll * if closed or declined ==> fetch order * @param $payment */ private function retrieveIPNRefund ($payment) { $this->loadVmClass('VirtueMartModelOrders', JPATH_VM_ADMINISTRATOR . DS . 'models' . DS . 'orders.php'); $orderModel = VmModel::getModel('orders'); $order = $orderModel->getOrder($payment->virtuemart_order_id); //Load the payments if (!($payments = $this->getDatasByOrderId($payment->virtuemart_order_id))) { return null; } // poll because refund state = pending $refundState = $this->getRefundState($payment, $order); if ($refundState == 'Declined' or $refundState == 'Completed') { $this->capturePayment($payments, $order); } } private function getRefundState ($payment, $order) { $amazonRefundId = $payment->amazon_response_amazonRefundId; $this->loadAmazonClass('OffAmazonPaymentsService_Model_GetRefundDetailsRequest'); $client = $this->getOffAmazonPaymentsService_Client(); if ($client == NULL) { return; } try { $getRefundDetailsRequest = new OffAmazonPaymentsService_Model_GetRefundDetailsRequest(); $getRefundDetailsRequest->setSellerId($this->_currentMethod->sellerId); $getRefundDetailsRequest->setAmazonRefundId($amazonRefundId); $getRefundDetails = $client->getRefundDetails($getRefundDetailsRequest); } catch (Exception $e) { $this->amazonError(__FUNCTION__ . ' ' . $e->getMessage(), $e->getCode()); return; } $this->loadHelperClass('amazonHelperGetRefundDetailsResponse'); $amazonHelperGetRefundDetailsResponse = new amazonHelperGetRefundDetailsResponse($getRefundDetails, $this->_currentMethod); $storeInternalData = $amazonHelperGetRefundDetailsResponse->getStoreInternalData(); $this->storeAmazonInternalData($order, $getRefundDetailsRequest, $getRefundDetails, NULL, NULL, $storeInternalData); return $amazonHelperGetRefundDetailsResponse->getState(); } /** * if Pending, authorization > 30 days ==> poll * If Closed, Declined ==> fetch order * @param $payment */ private function retrieveIPNAuthorization ($payment) { $this->loadVmClass('VirtueMartModelOrders', JPATH_VM_ADMINISTRATOR . DS . 'models' . DS . 'orders.php'); if (!($payments = $this->getDatasByOrderId($payment->virtuemart_order_id))) { // JError::raiseWarning(500, $db->getErrorMsg()); return null; } $orderModel = VmModel::getModel('orders'); $order = $orderModel->getOrder($payment->virtuemart_order_id); if ($payment->amazon_response_state == 'Pending' OR ($payment->amazon_response_state == 'Open' AND $this->getNumberOfDays($payments) > 30)) { $amazonAuthorizationId = $this->getAmazonAuthorizationId($payments); if (!$amazonAuthorizationId) { return false; } $authorizationDetailsResponse = $this->getAuthorizationDetails($amazonAuthorizationId, $order); $this->loadHelperClass('amazonHelperGetAuthorizationDetailsResponse'); $amazonHelperAuthorizationDetailsResponse = new amazonHelperGetAuthorizationDetailsResponse($authorizationDetailsResponse, $this->_currentMethod); $authorizationState = $amazonHelperAuthorizationDetailsResponse->getState(); if ($authorizationState == 'Closed' OR $authorizationState == 'Declined') { // check if status has changed // fetch Order //$this->_amazonOrderReferenceId = $payments[0]->amazonOrderReferenceId; //$this->vmConfirmedOrder(NULL, $order, FALSE); $getAuthorizationDetailsResult = $authorizationDetailsResponse->getGetAuthorizationDetailsResult(); $getAuthorizationDetails = $getAuthorizationDetailsResult->getAuthorizationDetails(); $this->closeAuthorization($getAuthorizationDetails->getAmazonAuthorizationId(), $order); return; } if (!$authorizationDetailsResponse->isSetGetAuthorizationDetailsResult()) { return; } $getAuthorizationDetailsResult = $authorizationDetailsResponse->getGetAuthorizationDetailsResult(); if (!$getAuthorizationDetailsResult->isSetAuthorizationDetails()) { return; } $getAuthorizationDetails = $getAuthorizationDetailsResult->getAuthorizationDetails(); $this->updateAuthorizeBillingAddressInOrder($getAuthorizationDetails, $order); $amazonState = $amazonHelperAuthorizationDetailsResponse->onResponseUpdateOrderHistory($order); } } /** * if Pending => poll * if Completed, Closed, or declined ==> fetch order * @param $payment */ private function retrieveIPNCapture($payment) { $this->loadVmClass('VirtueMartModelOrders', JPATH_VM_ADMINISTRATOR . DS . 'models' . DS . 'orders.php'); $orderModel = VmModel::getModel('orders'); $order = $orderModel->getOrder($payment->virtuemart_order_id); //Load the payments if (!($payments = $this->getDatasByOrderId($payment->virtuemart_order_id))) { // JError::raiseWarning(500, $db->getErrorMsg()); return null; } $captureState = $this->getCaptureState($payments, $order); if ($captureState == 'Completed' OR $captureState == 'Closed' OR $captureState == 'Declined') { // will update Billing address $client = $this->getOffAmazonPaymentsService_Client(); if ($client == NULL) { return; } $this->getAuthorization($client, NULL, $order, false); } } function plgVmOnSelfCallBE ($type, $name, &$render) { if ($name != $this->_name || $type != 'vmpayment') { return FALSE; } $action = vRequest::getCmd('action'); $virtuemart_paymentmethod_id = vRequest::getInt('virtuemart_paymentmethod_id'); //Load the method if (!($this->_currentMethod = $this->getVmPluginMethod($virtuemart_paymentmethod_id))) { return NULL; // Another method was selected, do nothing } $virtuemart_order_id = vRequest::getInt('virtuemart_order_id'); if (!($payments = $this->getDatasByOrderId($virtuemart_order_id))) { return null; } $orderModel = VmModel::getModel('orders'); $order = $orderModel->getOrder($virtuemart_order_id); $this->_order_number = $this->getUniqueReferenceId($order['details']['BT']->order_number); $this->_amount = vRequest::getFloat('amount'); switch ($action) { case 'refundPayment': if ($this->canDoRefund($payments, $order)) { $this->refundPayment($payments, $order); } break; case 'capturePayment': if ($authorizationId = $this->canDoCapture($payments, $order)) { // may be we did a new authorization in case of partial capture $this->capturePayment($payments, $order); } break; case 'newAuthorization': if ($this->canDoAuthorization($payments, $order)) { $client = $this->getOffAmazonPaymentsService_Client(); if ($client == NULL) { return; } $this->getAuthorization($client, NULL, $order, false); } break; default: vmError('VMPAYMENT_AMAZON_UPDATEPAYMENT_UNKNOWN_ACTION'); } $app = JFactory::getApplication(); $link = 'index.php?option=com_virtuemart&view=orders&task=edit&virtuemart_order_id=' . $virtuemart_order_id; $app->redirect(JRoute::_($link, FALSE)); } function plgVmOnSelfCallFE ($type, $name, &$render) { if ($name != $this->_name || $type != 'vmpayment') { return FALSE; } $action = vRequest::getCmd('action'); $virtuemart_paymentmethod_id = vRequest::getInt('virtuemart_paymentmethod_id'); //Load the method if (!($this->_currentMethod = $this->getVmPluginMethod($virtuemart_paymentmethod_id))) { return NULL; // Another method was selected, do nothing } $this->debugLog($action, 'plgVmOnSelfCallFE', 'debug'); if (!class_exists('VirtueMartCart')) { require(JPATH_VM_SITE . DS . 'helpers' . DS . 'cart.php'); } switch ($action) { case 'updateCartWithAmazonAddress': //$client = $this->getOffAmazonPaymentsService_Client(); //$this->setOrderReferenceDetails() $return = $this->updateCartWithAmazonAddress(); $json = array(); $json['reload'] = $return['error']; $json['error_msg'] = ''; if (isset($return['error_msg'])) { $json['error_msg'] = $this->rendererErrorMessage($return['error_msg']); } JResponse::setHeader('Cache-Control', 'no-cache, must-revalidate'); JResponse::setHeader('Expires', 'Mon, 6 Jul 2000 10:00:00 GMT'); // Set the MIME type for JSON output. $document = JFactory::getDocument(); $document->setMimeEncoding('application/json'); JResponse::setHeader('Content-Disposition', 'attachment;filename="amazon.json"', TRUE); JResponse::sendHeaders(); echo json_encode($json); jExit(); //JFactory::getApplication()->close(); break; case 'leaveAmazonCheckout': $this->leaveAmazonCheckout(); $json = array(); JResponse::setHeader('Cache-Control', 'no-cache, must-revalidate'); JResponse::setHeader('Expires', 'Mon, 6 Jul 2000 10:00:00 GMT'); // Set the MIME type for JSON output. $document = JFactory::getDocument(); $document->setMimeEncoding('application/json'); JResponse::setHeader('Content-Disposition', 'attachment;filename="amazon.json"', TRUE); JResponse::sendHeaders(); echo json_encode($json); jExit(); break; case 'resetAmazonReferenceId': $this->clearAmazonSession(); break; case 'onInvalidPaymentNewAuthorization': $html = $this->onInvalidPaymentNewAuthorization(); echo $html; break; default: $this->amazonError(vmText::_('VMPAYMENT_AMAZON_INVALID_NOTIFICATION_TASK')); return; } } function rendererErrorMessage($msg) { return '
Error
'; } /** * @param VirtueMartCart $cart */ public function plgVmOnCheckoutCheckDataPayment(VirtueMartCart $cart) { static $checkoutCheckDataPaymentDone = false; if (!$this->selectedThisByMethodId($cart->virtuemart_paymentmethod_id)) { /* if ($cart->layout==$this->_name) { if (!class_exists('VmConfig')) { require(JPATH_ADMINISTRATOR . DS . 'components' . DS . 'com_virtuemart' . DS . 'helpers' . DS . 'config.php'); } VmConfig::loadConfig(); $cart->layout = VmConfig::get('cartlayout', 'default'); $cart->setCartIntoSession(); } */ return NULL; // Another method was selected, do nothing } if (!($this->_currentMethod = $this->getVmPluginMethod($cart->virtuemart_paymentmethod_id))) { return NULL; // Another method was selected, do nothing } $this->_amazonOrderReferenceId = $this->getAmazonOrderReferenceIdFromSession(); if (empty($this->_amazonOrderReferenceId)) { //$message = vmText::_('VMPAYMENT_AMAZON_PAYWITHAMAZON_BUTTON'); //vmError($message, $message); return false; } if ($checkoutCheckDataPaymentDone) { return true; } $client = $this->getOffAmazonPaymentsService_Client(); if ($client == NULL) { return; } // incase the Address was not displayed if ($this->isOnlyDigitalGoods($cart)) { return true; } $physicalDestination = $this->getPhysicalDestination(); if (!$physicalDestination) { // may be we have just logged in, so there is no physical destination //$this->leaveAmazonCheckout(); return false; } $update_data = $this->getUserInfoFromAmazon($physicalDestination); if (!$this->isValidCountry($update_data['virtuemart_country_id'])) { $country = shopFunctions::getCountryByID($update_data['virtuemart_country_id']); $app = JFactory::getApplication(); $leaveAmazonCheckoutLink = $this->getLeaveAmazonCheckoutLink(); //$app->enqueueMessage(vmText::sprintf('VMPAYMENT_AMAZON_UPDATECART_DELIVERYCOUNTRYNOTALLOWED', $country, $leaveAmazonCheckoutLink)); $app->enqueueMessage(vmText::sprintf('VMPAYMENT_AMAZON_UPDATECART_DELIVERYCOUNTRYNOTALLOWED', $country)); //$this->leaveAmazonCheckout(); return false; } // setOrderReferenceDetails if (!$setOrderReferenceDetailsResponse = $this->setOrderReferenceDetails($client, $cart)) { $this->leaveAmazonCheckout(); $this->onErrorRedirectToCart(); return FALSE; } // getOrderReferenceDetails if (!$getOrderReferenceDetailsResponse = $this->getOrderReferenceDetails($client)) { $this->removeAmazonAddressFromCart($cart); $this->clearAmazonSession(); $cart->emptyCart(); $this->onErrorRedirectToCart(); return FALSE; } $orderReferenceDetails = $getOrderReferenceDetailsResponse->GetOrderReferenceDetailsResult->getOrderReferenceDetails(); if ($this->isSetConstraints($cart, $orderReferenceDetails)) { return false; } $checkoutCheckDataPaymentDone = true; return true; } private function getLeaveAmazonCheckoutLink() { $leaveAmazonCheckoutLink = '' . vmText::_('VMPAYMENT_AMAZON_LEAVE_PAY_WITH_AMAZON') . ''; return $leaveAmazonCheckoutLink; } /** * Constraints indicates if mandatory information is missing or incorrect in the Order Reference Object * @param $cart * @param $orderReferenceDetails * @return bool */ private function isSetConstraints ($cart, $orderReferenceDetails) { if ($orderReferenceDetails->isSetConstraints()) { $constraints = $orderReferenceDetails->getConstraints(); $constraintList = $constraints->getConstraint(); foreach ($constraintList as $constraint) { if ($constraint->isSetDescription()) { $this->setInConfirmOrder($cart, false); switch ($constraint->isSetConstraintID($constraint)) { case 'ShippingAddressNotSet': $this->handleShippingAddressNotSetConstraint($constraint); break; case 'PaymentPlanNotSet': $this->handlePaymentPlanNotSetConstraint($constraint); break; case 'AmountNotSet': //$this->handleAmountNotSetConstraint($constraint); // PROGRAMMING ERRROR TODO break; case 'PaymentMethodNotAllowed': $this->handlePaymentMethodNotAllowedConstraint($constraint); break; default: vmError('VMPAYMENT_AMAZON_CONSTRAINTID_UNKOWN'); $this->onErrorRedirectToCart(); return true; } return true; } } } return false; } /** * Display again the Amazon AddressBook widget to the buyer to collect shipping Information * @param $constraint */ private function handleShippingAddressNotSetConstraint ($constraint) { $this->renderAddressbookWallet(); } /** * Display again the Amazon Wallet widget to the buyer to collect payment Information * @param $constraint */ private function handlePaymentPlanNotSetConstraint ($constraint) { $this->renderAddressbookWallet(); } /** * Call again the SetOrderReferenceDetails operation with the order amount * This constraint should not happen. It is a programming error * @param $constraint */ private function handleAmountNotSetConstraint ($constraint) { $this->amazonError('handleAmountNotSetConstraint: ' . $constraint->getDescription()); } /** * Display again the Amazon Wallet widget and Request the buyer to select a different payment method * @param $constraint */ private function handlePaymentMethodNotAllowedConstraint ($constraint) { $this->debugLog("
" . var_export($constraint, true) . "
", __FUNCTION__, 'debug'); $this->renderAddressbookWallet('VMPAYMENT_AMAZON_SELECT_ANOTHER_PAYMENT'); } /** * @param $cart * @param $order * @return bool|null */ public function plgVmConfirmedOrder ($cart, $order) { if (!($this->_currentMethod = $this->getVmPluginMethod($order['details']['BT']->virtuemart_paymentmethod_id))) { return NULL; // Another method was selected, do nothing } if (!$this->selectedThisElement($this->_currentMethod->payment_element)) { return FALSE; } $this->setInConfirmOrder($cart); $this->_amazonOrderReferenceId = $this->getAmazonOrderReferenceIdFromSession(); if (!$this->_amazonOrderReferenceId) { $this->onErrorRedirectToCart(); return FALSE; } $client = $this->getOffAmazonPaymentsService_Client(); // the amount saved is in payment currency $this->_amount = $this->getTotalInPaymentCurrency($client, $order['details']['BT']->order_total, $order['details']['BT']->order_currency); $this->_is_digital = $this->isOnlyDigitalGoods($cart); $this->storeAmazonInternalData($order, NULL, NULL, NULL, $this->renderPluginName($this->_currentMethod), NULL, $this->_amazonOrderReferenceId, $this->_currentMethod); $this->_order_number = $order['details']['BT']->order_number; $html = $this->vmConfirmedOrder($cart, $order, false); vRequest::setVar('html', $html); vRequest::setVar('display_title', false); } /** * Confirmed Order also when in synchronous mode, and InvalidPaymentMethod * @param $cart * @param $order * @return bool|string */ private function vmConfirmedOrder ($cart, $order, $orderReferenceModifiable = true) { $client = $this->getOffAmazonPaymentsService_Client(); if ($client == NULL) { return; } // if $cart=NULL may be coming from plgVmRetrieveIPN if ($cart) { if (!$this->setOrderReferenceDetails($client, $cart, $order)) { $this->redirectToCart(vmText::_('VMPAYMENT_AMAZON_SELECT_ANOTHER_PAYMENT'), true); } } //confirmOrderReference if (!$this->confirmOrderReference($client, $order)) { $this->redirectToCart(vmText::_('VMPAYMENT_AMAZON_SELECT_ANOTHER_PAYMENT'), true); } // getorderdetails & address email if (!$this->updateBuyerInOrder($client, $cart, $order)) { $this->redirectToCart(vmText::_('VMPAYMENT_AMAZON_SELECT_ANOTHER_PAYMENT'), true); } /* why do i have that ? */ if ($cart) { $redirect = true; } else { $redirect = false; } $redirect = true; // at this point, since the authorization and capturing takes additional time to process // let's do that with a trigger if (!($amazonAuthorizationId = $this->getAuthorization($client, $cart, $order, $redirect))) { // getAuhtorization returns false if the the wallet needs to be displayed again $cart->_inConfirm = false; $html = $this->redisplayAddressbookWallet($client, $cart, $order['details']['BT']->order_number); return $html; } if (!class_exists('CurrencyDisplay')) { require(JPATH_VM_ADMINISTRATOR . DS . 'helpers' . DS . 'currencydisplay.php'); } VmConfig::loadJLang('com_virtuemart_orders', TRUE); $success = true; $html = $this->renderByLayout('response', array( "success" => $success, "amazonOrderId" => $this->getAmazonOrderReferenceIdFromSession(), "order" => $order, 'include_amazon_css' => $this->_currentMethod->include_amazon_css, )); $this->leaveAmazonCheckout(); if (!$cart) { $cart = VirtueMartCart::getCart(); } $cart->emptyCart(); return $html; } /** * @param $order * @param $request * @param $response * @param $notification * @param null $payment_name * @param null $amazonParams * @return array */ private function storeAmazonInternalData ($order, $request, $response, $notification = NULL, $payment_name = NULL, $amazonParams = NULL, $amazonOrderReferenceId = NULL) { $db_values['order_number'] = $order['details']['BT']->order_number; $db_values['virtuemart_order_id'] = $order['details']['BT']->virtuemart_order_id; $db_values['virtuemart_paymentmethod_id'] = $this->_currentMethod->virtuemart_paymentmethod_id; $db_values['order_is_digital'] = $this->_is_digital; $db_values['payment_order_total'] = $this->_amount; $db_values['payment_currency'] = $order['details']['BT']->user_currency_id; $db_values['amazon_request'] = $request ? serialize($request) : ""; $db_values['amazon_class_request_type'] = $request ? get_class($request) : ''; $db_values['amazon_response'] = $response ? serialize($response) : ""; $db_values['amazon_class_response_type'] = $response ? get_class($response) : ''; $db_values['amazon_notification'] = $notification ? serialize($notification) : ""; $db_values['amazon_class_notification_type'] = $notification ? get_class($notification) : ''; $db_values['amazonOrderReferenceId'] = $amazonOrderReferenceId ? $amazonOrderReferenceId : ''; //$db_values['payment_params'] = $this->_currentMethod; $db_values['payment_name'] = $payment_name; if ($amazonParams) { $amazonParamsArray = (array)($amazonParams); $db_values = array_merge($db_values, $amazonParamsArray); } //$preload=true preload the data here too preserve not updated data return $this->storePSPluginInternalData($db_values, $this->_tablepkey, 0); } /** * @return mixed */ // TODO: address line 3, district private function updateBuyerInOrder ($client, $cart, $order) { $orderModel = VmModel::getModel('orders'); $BT['virtuemart_order_id'] = $order['details']['BT']->virtuemart_order_id; $order_userinfosTable = $orderModel->getTable('order_userinfos'); $getOrderReferenceDetailsResponse = $this->getOrderReferenceDetails($client); $getOrderReferenceDetailsResult = $getOrderReferenceDetailsResponse->getGetOrderReferenceDetailsResult(); $orderReferenceDetails = $getOrderReferenceDetailsResult->getOrderReferenceDetails(); if ($orderReferenceDetails->isSetBuyer()) { $buyer = $orderReferenceDetails->getBuyer(); $BTFromAmazon = $this->getUserInfoFromAmazon($buyer, '', false, true); $BTFromAmazon['virtuemart_order_id'] = $order['details']['BT']->virtuemart_order_id; $BTFromAmazon['address_type'] = 'BT'; $this->debugLog("
" . var_export($BTFromAmazon, true) . "
", __FUNCTION__ . ' BT', 'debug'); $order_userinfosTable->emptyCache(); $order_userinfosTable->load($order['details']['BT']->virtuemart_order_id, 'virtuemart_order_id', " AND address_type='BT'"); if (!$order_userinfosTable->bindChecknStore($BTFromAmazon, true)) { vmError($order_userinfosTable->getError()); return false; } } // at this step, we should get it from amazon $onlyDigitalGoods = $this->isOnlyDigitalGoods($cart); if (!$onlyDigitalGoods) { $physicalDestination = $orderReferenceDetails->getDestination()->getPhysicalDestination(); if ($physicalDestination) { $ST = $this->getUserInfoFromAmazon($physicalDestination); $ST['virtuemart_order_id'] = $order['details']['BT']->virtuemart_order_id; $ST['address_type'] = 'ST'; $order_userinfosTable->emptyCache(); // check if ST is there $query="SELECT `#__virtuemart_order_userinfos`.* FROM `#__virtuemart_order_userinfos` WHERE `#__virtuemart_order_userinfos`.`virtuemart_order_id` = ".$order['details']['BT']->virtuemart_order_id." AND address_type='ST'"; $db = JFactory::getDBO(); $db->setQuery($query); if(!$db->loadResult()) { $order_userinfosTable=$orderModel->getTable('order_userinfos'); } $order_userinfosTable->load($order['details']['BT']->virtuemart_order_id, 'virtuemart_order_id', " AND address_type='ST'"); if (!$order_userinfosTable->bindChecknStore($ST, true)) { vmError($order_userinfosTable->getError()); return false; } $this->debugLog("
" . var_export($ST, true) . "
", __FUNCTION__ . ' ST', 'debug'); } } return true; } private function getUserInfoFromAmazon ($amazonAddress, $prefix = '', $all = true, $getEmail = false) { if ($amazonAddress->isSetName()) { $userInfoData[$prefix . 'last_name'] = $amazonAddress->getName(); $userInfoData[$prefix . 'first_name'] = ''; } if ($getEmail AND $amazonAddress->isSetEmail()) { $userInfoData['email'] = $amazonAddress->getEmail(); } if ($amazonAddress->isSetPhone()) { $userInfoData['phone_1'] = $amazonAddress->getPhone(); } if ($all) { if ($amazonAddress->isSetAddressLine1()) { $userInfoData[$prefix . 'address_1'] = $amazonAddress->getAddressLine1(); if ($amazonAddress->isSetAddressLine2()) { $userInfoData[$prefix . 'address_2'] = $amazonAddress->getAddressLine2(); } if ($amazonAddress->isSetAddressLine3()) { $userInfoData[$prefix . 'address_2'] .= ", " . $amazonAddress->getAddressLine3(); } } else { if ($amazonAddress->isSetAddressLine2()) { $userInfoData[$prefix . 'address_1'] = $amazonAddress->getAddressLine2(); } if ($amazonAddress->isSetAddressLine3()) { $userInfoData[$prefix . 'address_2'] = $amazonAddress->getAddressLine3(); } } if ($amazonAddress->isSetCity()) { $userInfoData[$prefix . 'city'] = $amazonAddress->getCity(); } if ($amazonAddress->isSetCounty()) { //$userInfoData['county'] = $amazonAddress->getCounty(); } if ($amazonAddress->isSetDistrict()) { //$userInfoData['district'] = $amazonAddress->GetDistrict(); } if ($amazonAddress->isSetStateOrRegion()) { $stateId = shopFunctions::getStateIDByName($amazonAddress->GetStateOrRegion()); if ($stateId) { $userInfoData[$prefix . 'virtuemart_state_id'] = $stateId; } else { $userInfoData[$prefix . 'virtuemart_state_id'] = 0; } } if ($amazonAddress->isSetPostalCode()) { $userInfoData[$prefix . 'zip'] = $amazonAddress->GetPostalCode(); } if ($amazonAddress->isSetCountryCode()) { $userInfoData[$prefix . 'virtuemart_country_id'] = shopFunctions::getCountryIDByName($amazonAddress->GetCountryCode()); } } return $userInfoData; } function getAmazonShipmentAddress() { $this->loadAmazonClass('OffAmazonPaymentsService_Model_GetOrderReferenceDetailsRequest'); $client = $this->getOffAmazonPaymentsService_Client(); if ($client == NULL) { return; } try { $getOrderReferenceDetailsRequest = new OffAmazonPaymentsService_Model_GetOrderReferenceDetailsRequest(); $getOrderReferenceDetailsRequest->setSellerId($this->_currentMethod->sellerId); $getOrderReferenceDetailsRequest->setAmazonOrderReferenceId($this->getAmazonOrderReferenceIdFromSession()); $referenceDetailsResultWrapper = $client->getOrderReferenceDetails($getOrderReferenceDetailsRequest); $physicalDestination = $referenceDetailsResultWrapper->GetOrderReferenceDetailsResult->getOrderReferenceDetails()->getDestination()->getPhysicalDestination(); } catch (Exception $e) { $this->amazonError(__FUNCTION__ . ' ' . $e->getMessage(), $e->getCode()); return; } return $physicalDestination; } function getAuthorizationDetails($amazonAuthorizationId, $order) { $client = $this->getOffAmazonPaymentsService_Client(); if ($client == NULL) { return; } try { $getAuthorizationDetailsRequest = new OffAmazonPaymentsService_Model_GetAuthorizationDetailsRequest(); $getAuthorizationDetailsRequest->setSellerId($this->_currentMethod->sellerId); $getAuthorizationDetailsRequest->setAmazonAuthorizationId($amazonAuthorizationId); $getAuthorizationDetailsResponse = $client->getAuthorizationDetails($getAuthorizationDetailsRequest); } catch (Exception $e) { $this->amazonError(__FUNCTION__ . ' ' . $e->getMessage(), $e->getCode()); return NULL; } $this->loadHelperClass('amazonHelperGetAuthorizationDetailsResponse'); $amazonHelperGetAuthorizationDetailsResponse = new amazonHelperGetAuthorizationDetailsResponse($getAuthorizationDetailsResponse, $this->_currentMethod); $storeInternalData = $amazonHelperGetAuthorizationDetailsResponse->getStoreInternalData(); $this->storeAmazonInternalData($order, $getAuthorizationDetailsRequest, $getAuthorizationDetailsResponse, NULL, NULL, $storeInternalData); return $getAuthorizationDetailsResponse; } private function getCaptureDetails($amazonCaptureId, $order) { $client = $this->getOffAmazonPaymentsService_Client(); if ($client == NULL) { return; } try { $getCaptureDetailsRequest = new OffAmazonPaymentsService_Model_GetCaptureDetailsRequest(); $getCaptureDetailsRequest->setSellerId($this->_currentMethod->sellerId); $getCaptureDetailsRequest->setAmazonCaptureId($amazonCaptureId); $getCaptureDetails = $client->getCaptureDetails($getCaptureDetailsRequest); } catch (Exception $e) { $this->amazonError(__FUNCTION__ . ' ' . $e->getMessage(), $e->getCode()); return; } $this->loadHelperClass('amazonHelperGetCaptureDetailsResponse'); $amazonHelperGetCaptureDetailsResponse = new amazonHelperGetCaptureDetailsResponse($getCaptureDetails, $this->_currentMethod); $storeInternalData = $amazonHelperGetCaptureDetailsResponse->getStoreInternalData(); $this->storeAmazonInternalData($order, $getCaptureDetailsRequest, $getCaptureDetails, NULL, NULL, $storeInternalData); return $getCaptureDetails; } /* private function getAmazonBillingAddress ($amazonAuthorizationId) { $getAuthorizationDetails = $this->getAuthorizationDetails($amazonAuthorizationId); $billingAddress = $getAuthorizationDetails->getGetAuthorizationDetailsResult()->getAuthorizationDetails()->getAuthorizationBillingAddress(); return $billingAddress; } */ /** * If we are going back to the cart because of InvalidPaymentMethod, then the order reference is not anylonger in a draft state * @return bool */ private function setOrderReferenceDetails($client, $cart, $order = NULL) { $this->loadAmazonClass('OffAmazonPaymentsService_Model_OrderReferenceAttributes'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_OrderTotal'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_SellerOrderAttributes'); if ($order) { $amountInCurrency = vmPSPlugin::getAmountInCurrency($order['details']['BT']->order_total, $order['details']['BT']->user_currency_id); $amount = $amountInCurrency['value']; } else { $amount = $this->getTotalInPaymentCurrency($client, $cart->pricesUnformatted['billTotal'], $cart->pricesCurrency); } //$_amazonOrderReferenceId = $this->getAmazonOrderReferenceIdFromSession(); if (empty($this->_amazonOrderReferenceId)) { $this->amazonError(__FUNCTION__ . ' setOrderReferenceDetails, No $_amazonOrderReferenceId'); return FALSE; } try { $setOrderReferenceDetailsRequest = new OffAmazonPaymentsService_Model_SetOrderReferenceDetailsRequest(); $setOrderReferenceDetailsRequest->setSellerId($this->_currentMethod->sellerId); $setOrderReferenceDetailsRequest->setAmazonOrderReferenceId($this->_amazonOrderReferenceId); $setOrderReferenceDetailsRequest->setOrderReferenceAttributes(new OffAmazonPaymentsService_Model_OrderReferenceAttributes()); $setOrderReferenceDetailsRequest->getOrderReferenceAttributes()->setOrderTotal(new OffAmazonPaymentsService_Model_OrderTotal()); $setOrderReferenceDetailsRequest->getOrderReferenceAttributes()->getOrderTotal()->setCurrencyCode($this->getCurrencyCode3($client)); $setOrderReferenceDetailsRequest->getOrderReferenceAttributes()->getOrderTotal()->setAmount($amount); $setOrderReferenceDetailsRequest->getOrderReferenceAttributes()->setSellerNote($this->getSellerNote()); $setOrderReferenceDetailsRequest->getOrderReferenceAttributes()->setSellerOrderAttributes(new OffAmazonPaymentsService_Model_SellerOrderAttributes()); if ($order) { $setOrderReferenceDetailsRequest->getOrderReferenceAttributes()->getSellerOrderAttributes()->setSellerOrderId($order['details']['BT']->order_number); } $setOrderReferenceDetailsRequest->getOrderReferenceAttributes()->getSellerOrderAttributes()->setStoreName($this->getStoreName()); //$setOrderReferenceDetailsRequest->getOrderReferenceAttributes()->getSellerOrderAttributes()->setCustomInformation($order['details']['BT']->customer_note); $setOrderReferenceDetailsRequest->getOrderReferenceAttributes()->setPlatformId($this->getPlatformId()); $setOrderReferenceDetailsResponse = $client->setOrderReferenceDetails($setOrderReferenceDetailsRequest); } catch (Exception $e) { $this->amazonError(__FUNCTION__ . ' ' . $e->getMessage(), $e->getCode()); $this->clearAmazonSession(); return FALSE; } $this->debugLog("
" . var_export($setOrderReferenceDetailsRequest, true) . "
", __FUNCTION__, 'debug'); $this->debugLog("
" . var_export($setOrderReferenceDetailsResponse, true) . "
", __FUNCTION__, 'debug'); return $setOrderReferenceDetailsResponse; } /** * @return bool */ private function getOrderReferenceDetails($client) { $this->loadAmazonClass('OffAmazonPaymentsService_Model_GetOrderReferenceDetailsRequest'); //$_amazonOrderReferenceId = $this->getAmazonOrderReferenceIdFromSession(); if (empty($this->_amazonOrderReferenceId)) { $this->amazonError(__FUNCTION__ . ', No $_amazonOrderReferenceId'); return FALSE; } try { $getOrderReferenceDetailsRequest = new OffAmazonPaymentsService_Model_GetOrderReferenceDetailsRequest(); $getOrderReferenceDetailsRequest->setSellerId($this->_currentMethod->sellerId); $getOrderReferenceDetailsRequest->setAmazonOrderReferenceId($this->_amazonOrderReferenceId); $getOrderReferenceDetailsResponse = $client->getOrderReferenceDetails($getOrderReferenceDetailsRequest); $this->debugLog("
" . var_export($getOrderReferenceDetailsRequest, true) . "
", __FUNCTION__, 'debug'); $this->debugLog("
" . var_export($getOrderReferenceDetailsResponse, true) . "
", __FUNCTION__, 'debug'); } catch (Exception $e) { $this->amazonError(__FUNCTION__ . ' ' . $e->getMessage(), $e->getCode()); $this->clearAmazonSession(); return FALSE; } return $getOrderReferenceDetailsResponse; } /** * @param $client * @param $total * @param $backToPricesCurrency * @return array */ private function getTotalInPaymentCurrency($client, $total, $backToPricesCurrency) { if (!class_exists('CurrencyDisplay')) { require(JPATH_VM_ADMINISTRATOR . '/helpers/currencydisplay.php'); } $virtuemart_currency_id = $this->getCurrencyId($client); $totalInPaymentCurrency = vmPSPlugin::getAmountValueInCurrency($total, $virtuemart_currency_id); //$this->debugLog($totalInPaymentCurrency, __FUNCTION__, 'debug'); $cd = CurrencyDisplay::getInstance($backToPricesCurrency); return $totalInPaymentCurrency; } /** * @param $client * @return int */ private function getCurrencyId($client) { $currencyCode3 = $this->getCurrencyCode3($client); $virtuemart_currency_id = shopFunctions::getCurrencyIDByName($currencyCode3); return $virtuemart_currency_id; } /** * @param $client * @return mixed */ private function getCurrencyCode3($client) { return $client->getMerchantValues()->getCurrency(); } /** * SellerNote can contain Sandbox Simulation string to test the Constraints * @return null|string */ private function getSellerNote() { return NULL; return $this->getSetOrderReferenceSandboxSimulationString(); } /** * @return string */ private function getSellerAuthorizationNote() { if ($this->_currentMethod->environment != 'sandbox' AND empty($this->_currentMethod->sandbox_error_simulation_auth)) { return NULL; } return $this->getSandboxSimulationString($this->_currentMethod->sandbox_error_simulation_auth); } /** * @return null|string */ private function getSellerRefundNote() { if ($this->_currentMethod->environment != 'sandbox' AND empty($this->_currentMethod->sandbox_error_simulation_refund)) { return NULL; } return $this->getSandboxSimulationString($this->_currentMethod->sandbox_error_simulation_refund); } /** * */ private function getSetOrderReferenceSandboxSimulationString() { return NULL; if ($this->_currentMethod->environment != 'sandbox' AND empty($this->_currentMethod->sandbox_error_simulation)) { return NULL; } $setOrderReferenceSandboxSimulation = array( 'InvalidPaymentMethod', //'PaymentMethodNotAllowed', // 'AmazonRejected', // 'TransactionTimedOut', // 'ExpiredUnused', // 'AmazonClosed', ); return $this->getSandboxSimulationString($setOrderReferenceSandboxSimulation, $this->_currentMethod->sandbox_error_simulation); } /** * * @param $authorizedSimulationReasons * @param $reason * @return null|string */ private function getSandboxSimulationString ($reason) { if ($this->_currentMethod->environment != 'sandbox' or empty($reason)) { return NULL; } $sandboxSimulationStrings = array( 'InvalidPaymentMethod' => '{"SandboxSimulation":{"State":"Declined","ReasonCode":"InvalidPaymentMethod"}}', //'PaymentMethodNotAllowed' => '{"SandboxSimulation": {"State":"Declined","ReasonCode":"InvalidPaymentMethod","PaymentMethodUpdateTimeInMins":100}}', 'AmazonRejected' => '{"SandboxSimulation":{"State":"Declined","ReasonCode":"AmazonRejected" }}', 'TransactionTimedOut' => '{"SandboxSimulation":{"State":"Declined","ReasonCode":"TransactionTimedOut"}}', 'ExpiredUnused' => '{"SandboxSimulation":{"State":"Declined","ReasonCode":"ExpiredUnused" ,"ExpirationTimeInMins":1}}', 'AmazonClosed' => '{"SandboxSimulation":{"State":"Closed", "ReasonCode":"AmazonClosed"}}', 'Pending' => '{"SandboxSimulation":{"State":"Pending"}}', ); $simulationString = $sandboxSimulationStrings[$reason]; return $simulationString; } /** * @return mixed */ private function getStoreName() { if (!class_exists('VirtueMartModelVendor')) { require(JPATH_VM_ADMINISTRATOR . DS . 'models' . DS . 'vendor.php'); } $virtuemart_vendor_id = 1; $vendorModel = VmModel::getModel('vendor'); $vendor = $vendorModel->getVendor($virtuemart_vendor_id); return $vendor->vendor_store_name; } /** * @return null|string */ private function getPlatformId () { if ($this->_currentMethod->region == "UK") { return "AA3KB5JD2CWIH"; } if ($this->_currentMethod->region == "DE") { return "A264YAJNGET7NB"; } return NULL; } private function onErrorRedirectToCart ($msg = NULL) { if (!$msg) { $msg = vmText::sprintf('VMPAYMENT_AMAZON_ERROR_TRY_AGAIN', $this->getVendorLink()); } else { } $this->redirectToCart($msg, true); } private function redirectToCart ($msg = NULL, $clearAmazonSession = false) { if ($clearAmazonSession) { $this->clearAmazonSession(); } $app = JFactory::getApplication(); $app->redirect(JRoute::_('index.php?option=com_virtuemart&view=cart&Itemid=' . vRequest::getInt('Itemid'), false), $msg); } private function getVendorLink () { return JRoute::_('index.php?option=com_virtuemart&view=vendor&layout=contact&virtuemart_vendor_id=' . $this->_currentMethod->virtuemart_vendor_id); } /** * */ private function confirmOrderReference($client, $order) { $this->loadHelperClass('amazonHelperConfirmOrderReferenceResponse'); try { $confirmOrderReferenceRequest = new OffAmazonPaymentsService_Model_ConfirmOrderReferenceRequest(); $confirmOrderReferenceRequest->setAmazonOrderReferenceId($this->_amazonOrderReferenceId); $confirmOrderReferenceRequest->setSellerId($this->_currentMethod->sellerId); $confirmOrderReferenceResponse = $client->confirmOrderReference($confirmOrderReferenceRequest); $this->debugLog("
" . var_export($confirmOrderReferenceRequest, true) . "
", __FUNCTION__, 'debug'); } catch (Exception $e) { // here we may have an error code when "Invalid Payment Method", "The OrderReferenceId xxx has constraints PaymentPlanNotSet and cannot be confirmed." $this->amazonError(__FUNCTION__ . ' ' . $e->getMessage(), $e->getCode()); return false; } $this->debugLog("
" . var_export($confirmOrderReferenceResponse, true) . "
", __FUNCTION__, 'debug'); $amazonHelperconfirmOrderReferenceResponse = new amazonHelperConfirmOrderReferenceResponse($confirmOrderReferenceResponse, $this->_currentMethod); $amazonHelperconfirmOrderReferenceResponse->onResponseUpdateOrderHistory($order); $storeInternalData = $amazonHelperconfirmOrderReferenceResponse->getStoreInternalData(); $this->storeAmazonInternalData($order, $confirmOrderReferenceRequest, $confirmOrderReferenceResponse, NULL, NULL, $storeInternalData); return true; } /** * @param $client * @param $cart * @param $order */ private function getAuthorization ($client, $cart, $order, $redirect = true) { $shouldRetry = false; $retries = 0; $this->loadAmazonClass('OffAmazonPaymentsService_Model_AuthorizeRequest'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_Price'); $this->loadHelperClass('amazonHelperAuthorizeResponse'); do { $authorizeRequest = new OffAmazonPaymentsService_Model_AuthorizeRequest(); $authorizeRequest->setAmazonOrderReferenceId($this->_amazonOrderReferenceId); $authorizeRequest->setSellerId($this->_currentMethod->sellerId); $authorizeRequest->setAuthorizationReferenceId($this->_order_number); $authorizeRequest->setSellerAuthorizationNote($this->getSellerAuthorizationNote()); $authorizeRequest->setTransactionTimeout($this->getAuthorizationTransactionTimeout()); // directly do the capture without the need to call the Capture Request if ($this->isCaptureImmediate($cart)) { $authorizeRequest->setCaptureNow(true); } else { $authorizeRequest->setCaptureNow(false); } $authorizeRequest->setAuthorizationAmount(new OffAmazonPaymentsService_Model_Price()); //$this->_amount is already on payment currency $authorizeRequest->getAuthorizationAmount()->setAmount($this->_amount); $authorizeRequest->getAuthorizationAmount()->setCurrencyCode($this->getCurrencyCode3($client)); try { $authorizeResponse = $client->authorize($authorizeRequest); $amazonAuthorizationId = $authorizeResponse->getAuthorizeResult()->getAuthorizationDetails()->getAmazonAuthorizationId(); //$this->debugLog("ERREUR
" . var_export($authorizeRequest, true) . "
", __FUNCTION__, 'debug'); //$this->debugLog("ERREUR
" . var_export($authorizeResponse, true) . "
", __FUNCTION__, 'debug'); } catch (Exception $e) { $msg = "An exception was thrown when trying to do the authorization:" . $e->getMessage() . "\n" . $e->getTraceAsString(); while ($e = $e->getPrevious()) { $msg .= ("Caused by: " . $e->getMessage() . "\n" . $e->getTraceAsString() . ""); $msg .= "\n"; } if ($redirect) { if (!$cart) { $cart = VirtueMartCart::getCart(); } $cart->setOutOfCheckout(); $this->debugLog($msg, __FUNCTION__ . " Exception", 'error'); $this->amazonError(__FUNCTION__ . ' ' . $msg); $this->redirectToCart(vmText::_('VMPAYMENT_AMAZON_SELECT_ANOTHER_PAYMENT'), true); } return false; } if ($authorizationDetails = $this->getAuthorizeDetailsFromAuthorizeResponse($authorizeResponse)) { $this->updateAuthorizeBillingAddressInOrder($authorizationDetails, $order); } $amazonHelperAuthorizeResponse = new amazonHelperAuthorizeResponse($authorizeResponse, $this->_currentMethod); $amazonState = $amazonHelperAuthorizeResponse->onResponseUpdateOrderHistory($order); $storeInternalData = $amazonHelperAuthorizeResponse->getStoreInternalData(); $this->storeAmazonInternalData($order, $authorizeRequest, $authorizeResponse, NULL, $this->renderPluginName($this->_currentMethod), $storeInternalData); $reasonCode = $authorizeResponse->getAuthorizeResult()->getAuthorizationDetails()->getAuthorizationStatus()->getReasonCode(); if ($redirect) { if ($amazonState == 'Declined' && $reasonCode == 'InvalidPaymentMethod' && $this->_currentMethod->soft_decline) { $this->incrementRetryInvalidPaymentMethodInSession(); return false; } elseif (($amazonState == 'Open' && $reasonCode == 'AmazonRejected') or ($amazonState == 'Declined' && $reasonCode == 'TransactionTimedOut')) { if ($retries < 2) { $shouldRetry = true; $retries++; } else { $cart->setOutOfCheckout(); $this->leaveAmazonCheckout(); $this->redirectToCart(vmText::_('VMPAYMENT_AMAZON_SELECT_ANOTHER_PAYMENT'), true); } } elseif ($amazonState == 'Declined') { $cart->setOutOfCheckout(); $this->leaveAmazonCheckout(); $this->redirectToCart(vmText::_('VMPAYMENT_AMAZON_SELECT_ANOTHER_PAYMENT'), true); } elseif ($amazonState == 'Closed' && $reasonCode == 'MaxCapturesProcessed') { $getAuthorizationDetails = $authorizeResponse->getAuthorizeResult()->getAuthorizationDetails(); $this->closeAuthorization($getAuthorizationDetails->getAmazonAuthorizationId(), $order); } } } while ($shouldRetry and $redirect); return $amazonAuthorizationId; } private function onInvalidPaymentNewAuthorization () { $this->loadVmClass('VirtueMartModelOrders', JPATH_VM_ADMINISTRATOR . DS . 'models' . DS . 'orders.php'); $this->loadVmClass('VirtueMartCart', JPATH_VM_SITE . DS . 'helpers' . DS . 'cart.php'); $this->_amazonOrderReferenceId = $this->getAmazonOrderReferenceIdFromSession(); if (!$this->_amazonOrderReferenceId) { $this->onErrorRedirectToCart(); return FALSE; } $retryInvalidPaymentMethod = $this->incrementRetryInvalidPaymentMethodInSession(); if ($retryInvalidPaymentMethod > 3) { //echo "TOO MANY RETRIES STOP"; $this->leaveAmazonCheckout(); $this->redirectToCart(vmText::_('VMPAYMENT_AMAZON_SELECT_ANOTHER_PAYMENT'), true); return; } if (!($order_number = vRequest::getWord('order_number'))) { $this->debugLog('no order number in submit', __FUNCTION__, 'debug'); return true; } if (!($virtuemart_order_id = VirtueMartModelOrders::getOrderIdByOrderNumber($order_number))) { $this->debugLog('no getOrderIdByOrderNumber: ' . $order_number, __FUNCTION__, 'debug'); return true; } $orderModel = VmModel::getModel('orders'); $order = $orderModel->getOrder($virtuemart_order_id); $this->_amount = $this->getTotalInPaymentCurrency($this->getOffAmazonPaymentsService_Client(), $order['details']['BT']->order_total, $order['details']['BT']->order_currency); $this->_order_number = $this->getUniqueReferenceId($order['details']['BT']->order_number); $this->loadVmClass('VirtueMartCart', JPATH_VM_SITE . DS . 'helpers' . DS . 'cart.php'); $cart = $cart = VirtueMartCart::getCart(); $html = $this->vmConfirmedOrder($cart, $order, false); return $html; } function getAuthorizeDetailsFromAuthorizeResponse ($authorizeResponse) { if ($authorizeResponse == NULL) { vmError('Amazon : programming error ' . __FUNCTION__); return false; } if (!$authorizeResponse->isSetAuthorizeResult()) { return; } $authorizeResult = $authorizeResponse->getAuthorizeResult(); if (!$authorizeResult->isSetAuthorizationDetails()) { return; } $authorizationDetails = $authorizeResult->getAuthorizationDetails(); return $authorizationDetails; } function updateAuthorizeBillingAddressInOrder ($authorizationDetails, $order) { if (!$authorizationDetails->isSetAuthorizationBillingAddress()) { return; } $authorizationBillingAddress = $authorizationDetails->getAuthorizationBillingAddress(); $BT = $this->getUserInfoFromAmazon($authorizationBillingAddress); $orderModel = VmModel::getModel('orders'); $BT['virtuemart_order_id'] = $order['details']['BT']->virtuemart_order_id; $order_userinfosTable = $orderModel->getTable('order_userinfos'); $BT['address_type'] = 'BT'; $order_userinfosTable->emptyCache(); $order_userinfosTable->load($order['details']['BT']->virtuemart_order_id, 'virtuemart_order_id', " AND address_type='BT'"); if (!$order_userinfosTable->bindChecknStore($BT, true)) { vmError($order_userinfosTable->getError()); return false; } } /** * @return int */ function getAuthorizationTransactionTimeout () { if ($this->_currentMethod->erp_mode == "erp_mode_disabled") { if ($this->_currentMethod->authorization_mode_erp_disabled == "automatic_synchronous") { return 0; } else { return self::AUTHORIZE_TRANSACTION_TIMEOUT; } } else { if ($this->_currentMethod->authorization_mode_erp_enabled == "automatic_synchronous") { return 0; } else { return self::AUTHORIZE_TRANSACTION_TIMEOUT; } } } public function plgVmOnUpdateOrderPayment (&$order, $old_order_status) { static $updateOrderPaymentNumber = 0; // we don't do anything from the front end if (JFactory::getApplication()->isSite()) { //return NULL; } //Load the method if (!($this->_currentMethod = $this->getVmPluginMethod($order->virtuemart_paymentmethod_id))) { return NULL; // Another method was selected, do nothing } if (!$this->selectedThisElement($this->_currentMethod->payment_element)) { return NULL; } if ($this->isERPModeEnabled() ) { return; } if (!$this->isValidUpdateOrderStatus($order->order_status)) { if (!JFactory::getApplication()->isSite()) { vmError(vmText::_('VMPAYMENT_AMAZON_UPDATEPAYMENT_NO_ACTION')); } return; } if ($updateOrderPaymentNumber > 10) { // todo: display message $updateOrderPaymentNumber = 0; sleep(5); } //Load the payments if (!($payments = $this->getDatasByOrderId($order->virtuemart_order_id))) { // JError::raiseWarning(500, $db->getErrorMsg()); return null; } $orderModel = VmModel::getModel('orders'); $orderModelData = $orderModel->getOrder($order->virtuemart_order_id); $this->_amount = $payments[0]->payment_order_total; // in payment currency $this->_order_number = $this->getUniqueReferenceId($orderModelData['details']['BT']->order_number); if ($order->order_status == $this->_currentMethod->status_refunded and $this->canDoRefund($payments, $orderModelData)) { return $this->refundPayment($payments, $orderModelData); } elseif ($order->order_status == $this->_currentMethod->status_capture and $this->canDoCapture($payments, $orderModelData)) { return $this->capturePayment($payments, $orderModelData); } elseif ($order->order_status == $this->_currentMethod->status_cancel and $this->canDoCancel($payments, $orderModelData)) { return $this->cancelPayment($payments, $orderModelData); } $updateOrderPaymentNumber++; return false; } /** * @param $payments * @return bool */ private function getCaptureState ($payments, $order) { $amazonCaptureId = $this->getAmazonCaptureId($payments); if (!$amazonCaptureId) { return false; } $captureDetailsResponse = $this->getCaptureDetails($amazonCaptureId, $order); $this->loadHelperClass('amazonHelperGetCaptureDetailsResponse'); $amazonHelperCaptureDetailsResponse = new amazonHelperGetCaptureDetailsResponse($captureDetailsResponse, $this->_currentMethod); $captureState = $amazonHelperCaptureDetailsResponse->getState(); $storeInternalData = $amazonHelperCaptureDetailsResponse->getStoreInternalData(); $this->storeAmazonInternalData($order, NULL, $captureDetailsResponse, NULL, $this->renderPluginName($this->_currentMethod), $storeInternalData); return $captureState; } /** * @param $payments * @return bool */ private function canDoCancel ($payments, $order) { $lastPayments = $payments[count($payments) - 1]; // return when InvalidPaymentMethod if ($lastPayments->amazon_response_state != "Suspended") { return true; } return false; } /** * @param $payments * @return bool */ private function canDoRefund ($payments, $order) { $captureState = $this->getCaptureState($payments, $order); if ($captureState === false) { vmInfo('VMPAYMENT_AMAZON_UPDATEPAYMENT_NOAMAZONCAPTUREID'); return; } if ($captureState != 'Completed') { vmInfo(vmText::sprintf('VMPAYMENT_AMAZON_UPDATEPAYMENT_CANTDOREFUND', $captureState)); return false; } return true; } private function getAuthorizationState ($payments, $order) { $amazonAuthorizationId = $this->getAmazonAuthorizationId($payments); if (!$amazonAuthorizationId) { return false; } $authorizationDetailsResponse = $this->getAuthorizationDetails($amazonAuthorizationId, $order); if (!$authorizationDetailsResponse) { return NULL; } //catch errors $this->loadHelperClass('amazonHelperGetAuthorizationDetailsResponse'); $amazonHelperAuthorizationDetailsResponse = new amazonHelperGetAuthorizationDetailsResponse($authorizationDetailsResponse, $this->_currentMethod); $authorizationState = $amazonHelperAuthorizationDetailsResponse->getState(); $storeInternalData = $amazonHelperAuthorizationDetailsResponse->getStoreInternalData(); $this->storeAmazonInternalData($order, NULL, $authorizationDetailsResponse, NULL, $this->renderPluginName($this->_currentMethod), $storeInternalData); return $authorizationState; } /** * if authorization object is in Open State, then the funds can be captured */ private function canDoCapture ($payments, $order) { $authorizationState = $this->getAuthorizationState($payments, $order); if (!$authorizationState) { return false; } if ($authorizationState != 'Open') { vmInfo(vmText::sprintf('VMPAYMENT_AMAZON_UPDATEPAYMENT_CANTDOCAPTURE', $authorizationState)); return false; } return true; } /** * if authorization object is in Open State, then the funds can be captured */ private function canDoAuthorization ($payments, $order) { $this->_amazonOrderReferenceId = $this->getAmazonOrderReferenceIdFromPayments($payments); $orderReferencestate = $this->getOrderReferenceState(); if ($orderReferencestate != 'Open') { return false; } return true; } private function configCanDoAuthorization () { if ($this->_currentMethod->erp_mode == "erp_mode_disabled" OR ($this->_currentMethod->erp_mode == "erp_mode_enabled" AND $this->_currentMethod->authorization_mode_erp_enabled != "authorization_done_by_erp")) { return true; } else { return false; } } /** * @param $payments * @param $order * if orderstate == Open, Suspended ==> closeOrderReference * of orderstate= draft, open, , and no pending, completed, closed captures CancelOrderReference */ private function cancelPayment ($payments, $order) { $cancelOrderReferenceRequest = new OffAmazonPaymentsService_Model_CancelOrderReferenceRequest(); $amazonOrderReferenceId = $this->getAmazonOrderReferenceId($payments); $cancelOrderReferenceRequest->setSellerId($this->_currentMethod->sellerId); $cancelOrderReferenceRequest->setAmazonOrderReferenceId($amazonOrderReferenceId); $client = $this->getOffAmazonPaymentsService_Client(); try { $client->cancelOrderReference($cancelOrderReferenceRequest); $this->debugLog("
" . var_export($cancelOrderReferenceRequest, true) . "
", __FUNCTION__, 'debug'); } catch (Exception $e) { $this->amazonError(__FUNCTION__ . ' ' . $e->getMessage(), $e->getCode()); return FALSE; } $this->storeAmazonInternalData($order, $cancelOrderReferenceRequest, NULL, NULL, $this->renderPluginName($this->_currentMethod), NULL, NULL, $this->_amount); } private function capturePayment ($payments, $order) { $amazonAuthorizationId = $this->getAmazonAuthorizationId($payments); $this->loadAmazonClass('OffAmazonPaymentsService_Model_CaptureRequest'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_Price'); $client = $this->getOffAmazonPaymentsService_Client(); if ($client == NULL) { return; } $captureRequest = new OffAmazonPaymentsService_Model_CaptureRequest(); $captureRequest->setSellerId($this->_currentMethod->sellerId); $captureRequest->setAmazonAuthorizationId($amazonAuthorizationId); $captureRequest->setCaptureReferenceId($this->_order_number); $captureRequest->setCaptureAmount(new OffAmazonPaymentsService_Model_Price()); $captureRequest->getCaptureAmount()->setAmount($this->_amount); $captureRequest->getCaptureAmount()->setCurrencyCode($this->getCurrencyCode3($client)); try { $captureResponse = $client->capture($captureRequest); $amazonCaptureId = $captureResponse->getCaptureResult()->getCaptureDetails()->getAmazonCaptureId(); $this->debugLog("
" . var_export($captureRequest, true) . "
", __FUNCTION__, 'debug'); $this->debugLog("
" . var_export($captureResponse, true) . "
", __FUNCTION__, 'debug'); } catch (Exception $e) { $msg = $e->getMessage(); $log = "An exception was thrown when trying to capture payment:" . $e->getMessage() . "\n" . $e->getTraceAsString(); while ($e = $e->getPrevious()) { $log .= ("Caused by: " . $e->getMessage() . "\n" . $e->getTraceAsString() . ""); $msg .= "Reason: " . $e->getMessage() . "
"; $log .= "\n"; } $this->debugLog($log, __FUNCTION__, 'debug'); $this->amazonError(__FUNCTION__ . ' ' . $msg); return false; } $this->loadHelperClass('amazonHelperCaptureResponse'); $amazonHelperCaptureResponse = new amazonHelperCaptureResponse($captureResponse, $this->_currentMethod); $amazonHelperCaptureResponse->onResponseUpdateOrderHistory($order); //$orderModel = VmModel::getModel('orders'); //$orderModel->updateStatusForOneOrder($order['details']['BT']->virtuemart_order_id, $order_history, TRUE); $storeInternalData = $amazonHelperCaptureResponse->getStoreInternalData(); $this->storeAmazonInternalData($order, $captureRequest, $captureResponse, NULL, $this->renderPluginName($this->_currentMethod), $storeInternalData, NULL, $this->_amount); $amazonState = $amazonHelperCaptureResponse->getState(); if ($amazonState == "Completed") { $amazonOrderReferenceId = $this->getAmazonOrderReferenceId($payments); if (!$amazonOrderReferenceId) { vmError('VMPAYMENT_AMAZON_UPDATEPAYMENT_NOAMAZONORDERREFERENCEID'); return false; } $this->closeOrderReference($amazonOrderReferenceId, $order); } return $amazonCaptureId; } private function refundPayment ($payments, $order) { $amazonCaptureId = $this->getAmazonCaptureId($payments); if (empty($amazonCaptureId)) { vmError(vmText::_('VMPAYMENT_AMAZON_UPDATEPAYMENT_NOAMAZONCAPTUREID')); return false; } $this->loadAmazonClass('OffAmazonPaymentsService_Model_RefundRequest'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_Price'); $client = $this->getOffAmazonPaymentsService_Client(); if ($client == NULL) { return; } $refund = new OffAmazonPaymentsService_Model_Price(); $refund->setCurrencyCode($this->getCurrencyCode3($client)); $refund->setAmount($this->_amount); $refundRequest = new OffAmazonPaymentsService_Model_RefundRequest(); $refundRequest->setSellerId($this->_currentMethod->sellerId); $refundRequest->setAmazonCaptureId($amazonCaptureId); $refundRequest->setRefundReferenceId($this->getUniqueReferenceId($order['details']['BT']->order_number)); // random string $refundRequest->setSellerRefundNote($this->getSellerRefundNote()); $refundRequest->setRefundAmount($refund); try { $refundResponse = $client->refund($refundRequest); $amazonRefundId = $refundResponse->getRefundResult()->getRefundDetails()->getAmazonRefundId(); $this->debugLog("
" . var_export($refundRequest, true) . "
", __FUNCTION__, 'debug'); $this->debugLog("
" . var_export($refundResponse, true) . "
", __FUNCTION__, 'debug'); } catch (Exception $e) { $msg = $e->getMessage(); $log = "An exception was thrown when trying to refund payment:" . $e->getMessage() . "\n" . $e->getTraceAsString(); if ($this->_currentMethod->debug) { while ($e = $e->getPrevious()) { $log .= ("Caused by: " . $e->getMessage() . "\n" . $e->getTraceAsString() . ""); $msg .= "Reason: " . $e->getMessage() . "
"; $log .= "\n"; } $this->debugLog($log, __FUNCTION__, 'debug'); } vmError(__FUNCTION__ . ' ' . $msg); return false; } $this->loadHelperClass('amazonHelperRefundResponse'); $amazonHelperRefundResponse = new amazonHelperRefundResponse($refundResponse, $this->_currentMethod); $storeInternalData = $amazonHelperRefundResponse->getStoreInternalData(); $this->storeAmazonInternalData($order, $refundRequest, $refundResponse, NULL, $this->renderPluginName($this->_currentMethod), $storeInternalData, NULL, $refund); // refund will issue a notification in all cases. The notification will inform if the refund operation has been accepted or not. // so the order status is updated but the customer is not notified. // He will be notified when the notification arrives vRequest::setVar('customer_notified', 0); $orders = vRequest::getVar('orders'); $virtuemart_order_id=$payments[0]->virtuemart_order_id; if (isset($orders[$virtuemart_order_id]) and isset($orders[$virtuemart_order_id]['customer_notified'])) vRequest::setVar($orders[$virtuemart_order_id]['customer_notified'], 0); return true; } function getOrderReferenceState () { $client = $this->getOffAmazonPaymentsService_Client(); if ($client == NULL) { return false; } $getOrderReferenceDetailsResponse = $this->getOrderReferenceDetails($client); if ($getOrderReferenceDetailsResponse) { return $getOrderReferenceDetailsResponse->getGetOrderReferenceDetailsResult()->getOrderReferenceDetails()->getOrderReferenceStatus()->getState(); } return false; } /** * Capture reference Id must always be unique * @param $order_number * @return string */ private function getUniqueReferenceId ($order_number) { return $order_number . '-' . time(); } function getAuthorizationResponse ($payments) { // we don't care, may be he has change his payment config /* if ($this->_currentMethod->capture_mode=='immediate_capture') { vmError(vmText::_('VMPAYMENT_AMAZON_UPDATEPAYMENT_CAPTUREMODE_IMMEDIATE')); return false; } */ foreach ($payments as $payment) { if ($payment->amazon_class_response_type == 'OffAmazonPaymentsService_Model_AuthorizeResponse' or $payment->amazon_class_response_type == 'OffAmazonPaymentsNotifications_Model_authorizationNotification') { return $payment; } } vmError(vmText::_('VMPAYMENT_AMAZON_UPDATEPAYMENT_NOAMAZONAUTHORIZATIONID')); return false; } /** * */ function getAmazonOrderReferenceId ($payments) { //$payments_reverse = array_reverse($payments); foreach ($payments as $payment) { if (!empty($payment->amazonOrderReferenceId) and ($payment->amazonOrderReferenceId != NULL)) { return $payment->amazonOrderReferenceId; } } return NULL; } /** * if amount = 0 then it is a full capture * otherwise it is a partial capture * in this case if a capture has already been done, a new authorization for that amount is requested */ function getAmazonAuthorizationId ($payments) { $payments_reverse = array_reverse($payments); foreach ($payments_reverse as $payment) { if (!empty($payment->amazon_response_amazonAuthorizationId)) { return $payment->amazon_response_amazonAuthorizationId; } } return NULL; } /** * @param $payments * @return null */ function getAmazonCaptureId ($payments) { $this->loadAmazonServicesClasses(); $this->loadAmazonNotificationClasses(); $payments_reverse = array_reverse($payments); foreach ($payments_reverse as $payment) { if (!empty($payment->amazon_response_amazonCaptureId)) { return $payment->amazon_response_amazonCaptureId; } } return NULL; } /** * @param $virtuemart_paymentmethod_id * @param $paymentCurrencyId * @return bool */ function plgVmgetPaymentCurrency ($virtuemart_paymentmethod_id, &$paymentCurrencyId) { if (!($method = $this->getVmPluginMethod($virtuemart_paymentmethod_id))) { return NULL; // Another method was selected, do nothing } if (!$this->selectedThisElement($method->payment_element)) { return FALSE; } $client = $this->getOffAmazonPaymentsService_Client(); if ($client == NULL) { return; } $method->payment_currency = $this->getCurrencyId($client); $paymentCurrencyId = $method->payment_currency; return TRUE; } /** * @param $html * @return bool|null */ function plgVmOnPaymentResponseReceived (&$html) { $this->loadVmClass('VirtueMartCart', JPATH_VM_SITE . DS . 'helpers' . DS . 'cart.php'); if (!class_exists('shopFunctionsF')) { require(JPATH_VM_SITE . DS . 'helpers' . DS . 'shopfunctionsf.php'); } $this->loadVmClass('VirtueMartModelOrders', JPATH_VM_ADMINISTRATOR . DS . 'models' . DS . 'orders.php'); VmConfig::loadJLang('com_virtuemart_orders', TRUE); $virtuemart_paymentmethod_id = vRequest::getInt('pm', 0); if (!($this->_currentMethod = $this->getVmPluginMethod($virtuemart_paymentmethod_id))) { return NULL; // Another method was selected, do nothing } if (!$this->selectedThisElement($this->_currentMethod->payment_element)) { return NULL; } $html = "We will send you an email confirmation with your order details shortly"; $html .= "Our order number"; $html .= "Amazon Reference"; $html .= "Go tot payments.amazon... to see your payment history and other account information."; vRequest::setVar('display_title', false); vRequest::setVar('html', $html); return true; } function plgVmOnUserPaymentCancel () { $this->loadVmClass('VirtueMartModelOrders', JPATH_VM_ADMINISTRATOR . DS . 'models' . DS . 'orders.php'); $order_number = vRequest::getUword('on'); if (!$order_number) { return FALSE; } if (!$virtuemart_order_id = VirtueMartModelOrders::getOrderIdByOrderNumber($order_number)) { return NULL; } if (!($paymentTable = $this->getDataByOrderId($virtuemart_order_id))) { return NULL; } $session = JFactory::getSession(); $return_context = $session->getId(); $field = $this->_name . '_custom'; if (strcmp($paymentTable->$field, $return_context) === 0) { $this->handlePaymentUserCancel($virtuemart_order_id); } return TRUE; } /** * Display stored payment data for an order * * @see components/com_virtuemart/helpers/vmPSPlugin::plgVmOnShowOrderBEPayment() */ function plgVmOnShowOrderBEPayment ($virtuemart_order_id, $virtuemart_paymentmethod_id) { if (!$this->selectedThisByMethodId($virtuemart_paymentmethod_id)) { return NULL; // Another method was selected, do nothing } if (!($this->_currentMethod = $this->getVmPluginMethod($virtuemart_paymentmethod_id))) { return NULL; // Another method was selected, do nothing } $payments = $this->getDatasByOrderId($virtuemart_order_id); $html = '' . "\n"; $html .= $this->getHtmlHeaderBE(); $html .= $this->showActionOrderBEPayment($virtuemart_order_id, $virtuemart_paymentmethod_id, $payments); $html .= $this->showOrderBEPayment($virtuemart_order_id, $payments); $html .= '
' . "\n"; return $html; } private function showActionOrderBEPayment ($virtuemart_order_id, $virtuemart_paymentmethod_id, $payments) { //return; $this->loadVmClass('VirtueMartModelOrders', JPATH_VM_ADMINISTRATOR . DS . 'models' . DS . 'orders.php'); $orderModel = VmModel::getModel('orders'); $order = $orderModel->getOrder($virtuemart_order_id); $options = array(); $options[] = JHTML::_('select.option', 'capturePayment', JText::_('VMPAYMENT_AMAZON_ORDER_BE_CAPTURE'), 'value', 'text'); $options[] = JHTML::_('select.option', 'refundPayment', JText::_('VMPAYMENT_AMAZON_ORDER_BE_REFUND'), 'value', 'text'); $options[] = JHTML::_('select.option', 'newAuthorization', JText::_('VMPAYMENT_AMAZON_ORDER_BE_NEW_AUTHORIZATION'), 'value', 'text'); $actionList = JHTML::_('select.genericlist', $options, 'action', '', 'value', 'text', 'capturePayment', 'action', true); //$html = '' . "\n"; $html = ''; $html .= ''; $html .= ''; $doc = JFactory::getDocument(); $doc->addScriptDeclaration(" // "); //$html .= '
'; $html .= $actionList; $html .= ' '; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= ''; $html .= '' . Jtext::_('COM_VIRTUEMART_SAVE') . ''; $html .= ''; $html .= '
' ; return $html; } private function showOrderBEPayment ($virtuemart_order_id, $payments) { $db = JFactory::getDBO(); $query = 'SHOW COLUMNS FROM `' . $this->_tablename . '` '; $db->setQuery($query); $columns = $db->loadColumn(0); $html = ''; $first = TRUE; $lang = JFactory::getLanguage(); foreach ($payments as $payment) { if ($payment->amazon_class_request_type) { $this->loadAmazonClass($payment->amazon_class_request_type); } if ($payment->amazon_class_response_type) { $this->loadAmazonClass($payment->amazon_class_response_type); } if ($payment->amazon_class_notification_type) { $this->loadAmazonClass($payment->amazon_class_notification_type); } $html .= '' . vmText::_('VMPAYMENT_AMAZON_DATE') . '' . $payment->created_on . ''; // Now only the first entry has this data when creating the order if ($first) { $html .= $this->getHtmlRowBE('AMAZON_PAYMENT_NAME', $payment->payment_name); // keep that test to have it backwards compatible. Old version was deleting that column when receiving an IPN notification if ($payment->payment_order_total and $payment->payment_order_total != 0.00) { $html .= $this->getHtmlRowBE('COM_VIRTUEMART_TOTAL', ($payment->payment_order_total) . " " . shopFunctions::getCurrencyByID($payment->payment_currency, 'currency_code_3')); } if ($payment->email_currency and $payment->email_currency != 0) { //$html .= $this->getHtmlRowBE($this->_name.'_PAYMENT_EMAIL_CURRENCY', shopFunctions::getCurrencyByID($payment->email_currency, 'currency_code_3')); } $first = FALSE; } else { $amazon_classes = array(); /* if (!empty($payment->amazon_request)) { $amazon_data = unserialize($payment->amazon_request); $amazon_classes[get_class($amazon_data)] = $payment->amazon_request; } */ $this->loadAmazonServicesClasses(); $this->loadAmazonNotificationClasses(); if (!empty($payment->amazon_request)) { $amazon_classes[$payment->amazon_class_request_type] = $payment->amazon_request; $vmClass = $this->getVmClass($payment->amazon_class_request_type); $html .= $this->getHtmlRowBE(vmText::_('VMPAYMENT_AMAZON_REQUEST_TYPE'), vmText::_('VMPAYMENT_AMAZON_REQUEST_TYPE_' . $vmClass)); $transactionLogContent = $this->getTransactionLogContent($payment->amazon_class_request_type, $payment->amazon_request, $payment); if (empty($transactionLogContent)) { vmError("getTransactionLogContent" . $payment->amazon_class_request_type . ' '); vmError("getTransactionLogContent" . $payment->amazon_request . ' '); } $html .= $transactionLogContent; } if (!empty($payment->amazon_response)) { $vmClass = $this->getVmClass($payment->amazon_class_response_type); $amazon_classes[$payment->amazon_class_response_type] = $payment->amazon_response; $html .= $this->getHtmlRowBE(vmText::_('VMPAYMENT_AMAZON_RESPONSE_TYPE'), vmText::_('VMPAYMENT_AMAZON_RESPONSE_TYPE_' . $vmClass)); $html .= $this->getResponseData($payment); $html .= $this->getTransactionLogContent($payment->amazon_class_response_type, $payment->amazon_response, $payment); } elseif (!empty($payment->amazon_notification)) { $amazon_classes[$payment->amazon_class_notification_type] = $payment->amazon_notification; $vmClass = $this->getVmClass($payment->amazon_class_notification_type); $html .= $this->getHtmlRowBE(vmText::_('VMPAYMENT_AMAZON_NOTIFICATION_TYPE'), vmText::_('VMPAYMENT_AMAZON_NOTIFICATION_TYPE_' . $vmClass)); $html .= $this->getResponseData($payment); $html .= $this->getTransactionLogContent($payment->amazon_class_notification_type, $payment->amazon_notification, $payment); } } } $doc = JFactory::getDocument(); $js = " jQuery().ready(function($) { $('.amazonLogOpener').click(function() { var logId = $(this).attr('rel'); $('#amazonLog_'+logId).toggle(); return false; }); $('.amazonDetailsOpener').click(function() { var detailsId = $(this).attr('rel'); $('#amazonDetails_'+detailsId).toggle(); return false; }); });"; $doc->addScriptDeclaration($js); return $html; } function getResponseData ($payment) { $html = ''; $code = 'amazon_response_'; foreach ($payment as $key => $value) { // only displays if there is a value or the value is different from 0.00 and the value if ($value) { if (substr($key, 0, strlen($code)) == $code) { $html .= $this->getHtmlRowBE($key, $value); } } } return $html; } function getTransactionLogContent ($amazon_class, $amazon_data_serialized, $payment) { $html = ''; $this->loadAmazonClass($amazon_class); $vmClass = $this->getVmClass($amazon_class); $vmClassName = 'amazonHelper' . $vmClass; $amazon_data = unserialize($amazon_data_serialized); $this->loadHelperClass($vmClassName); $html .= ''; if (!class_exists($vmClassName)) { vmError(__FUNCTION__ . ' Programming error: class name does not exist:' . $vmClassName); return NULL; } elseif (empty($vmClass)) { vmError(__FUNCTION__ . ' Programming error: class does not exist:' . $vmClass); return NULL; } else { $obj = new $vmClassName($amazon_data, $this->_currentMethod); $contents = $obj->getContents(); if (!empty($contents)) { $html .= ''; //$html .= ''; $html .= '  '; $html .= vmText::_('VMPAYMENT_AMAZON_VIEW_TRANSACTION_DETAILS'); $html .= ' '; $html .= ''; } } $html .= ' '; $html .= ' '; if ($this->_currentMethod->debug) { //$html .= '' . $amazon_class . ' $html .= '' . '  '; $html .= vmText::_('VMPAYMENT_AMAZON_VIEW_TRANSACTION_LOG'); $html .= ' '; } $html .= ' '; //} return $html; } function getVmClass ($amazonClass) { $pos = strrpos($amazonClass, '_'); $vmClass = substr($amazonClass, $pos + 1); return $vmClass; } /** * Create the table for this plugin if it does not yet exist. * This functions checks if the called plugin is active one. * When yes it is calling the standard method to create the tables * * @author Valérie Isaksen * */ public function plgVmOnStoreInstallPaymentPluginTable ($jplugin_id) { if ($res = $this->selectedThisByJPluginId($jplugin_id)) { $virtuemart_paymentmethod_id = vRequest::getInt('virtuemart_paymentmethod_id'); $method = $this->getPluginMethod($virtuemart_paymentmethod_id); vmdebug('plgVmOnStoreInstallPaymentPluginTable', $method, $virtuemart_paymentmethod_id); if (!extension_loaded('curl')) { vmError(vmText::sprintf('VMPAYMENT_AMAZON_CONF_MANDATORY_PHP_EXTENSION', 'curl')); } if (!extension_loaded('openssl')) { vmError(vmText::sprintf('VMPAYMENT_AMAZON_CONF_MANDATORY_PHP_EXTENSION', 'openssl')); } } return $this->onStoreInstallPluginTable($jplugin_id); } /** * This event is fired after the payment method has been selected. It can be used to store * additional payment info in the cart. * * @author Valérie isaksen * * @param VirtueMartCart $cart : the actual cart * @return null if the payment was not selected, true if the data is valid, error message if the data is not vlaid * */ public function plgVmOnSelectCheckPayment (VirtueMartCart $cart, &$msg) { if (!$this->selectedThisByMethodId($cart->virtuemart_paymentmethod_id)) { return NULL; } if (!($this->_currentMethod = $this->getVmPluginMethod($cart->virtuemart_paymentmethod_id))) { $this->clearAmazonSession(); return NULL; } $_amazonOrderReferenceId = $this->getAmazonOrderReferenceIdFromSession(); if (!$_amazonOrderReferenceId) { //$msg = vmText::_('VMPAYMENT_AMAZON_PAYWITHAMAZON_BUTTON'); return false; } return TRUE; // this method was selected , and the data is valid by default } function removeAmazonAddressFromCart ($cart) { $data = $this->getDataFromSession(); if (isset($data['BT'])) { $data['BT']['address_type'] = 'BT'; $cart->saveAddressInCart($data['BT'], $data['BT']['address_type'], TRUE); } if (isset($data['ST'])) { $data['ST']['address_type'] = 'ST'; $cart->saveAddressInCart($data['ST'], $data['ST']['address_type'], TRUE); } return; } /** * plgVmDisplayListFEPayment * This event is fired to display the pluginmethods in the cart (edit shipment/payment) for exampel * * @param object $cart Cart object * @param integer $selected ID of the method selected * @return boolean True on success, false on failures, null when this plugin was not selected. * On errors, JError::raiseWarning (or JError::raiseError) must be used to set a message. * * @author Valerie Isaksen */ public function plgVmDisplayListFEPayment (VirtueMartCart $cart, $selected = 0, &$htmlIn) { return $this->displayListFE($cart, $selected, $htmlIn); } /** * Used when the vmOPC is set to OFF * @param $cart * @param $payment_advertise * @return null * In case OPC is off: the login widget is displayed on the cart, and on the payment list */ function plgVmOnCheckoutAdvertise ($cart, &$payment_advertise) { if (vmConfig::get('oncheckout_opc') == 0) { $html = NULL; $this->displayListFE($cart, $cart->virtuemart_paymentmethod_id, $html); } } /** * @param $plugin * @param $selectedPlugin * @param $pluginSalesPrice * @return string */ protected function getPluginHtml ($method, $selectedPlugin, $pluginSalesPrice) { if ($selectedPlugin == $method->virtuemart_paymentmethod_id) { $checked = 'checked="checked"'; //return NULL; } else { $checked = ''; } $html = ''; if (!class_exists('CurrencyDisplay')) { require(JPATH_VM_ADMINISTRATOR . DS . 'helpers' . DS . 'currencydisplay.php'); } $currency = CurrencyDisplay::getInstance(); $costDisplay = ""; if ($pluginSalesPrice) { $costDisplay = $currency->priceDisplay($pluginSalesPrice); $costDisplay = ' (' . JText::_('COM_VIRTUEMART_PLUGIN_COST_DISPLAY') . $costDisplay . ")"; } //$html = '\n". '\n"; // IF NOT SELECTED Then display the Pay With amazon Button $this->loadVmClass('VirtueMartCart', JPATH_VM_SITE . DS . 'helpers' . DS . 'cart.php'); //$this->debug('', 'updateCartWithAmazonAddress', 'debug'); $cart = VirtueMartCart::getCart(); $cartLayout = $cart->layout; if (empty($cart->products) and $cartLayout == $this->_name) { //$this->unsetCartLayoutAndPaymentMethod($cart); $this->leaveAmazonCheckout(); } $amazonOrderReferenceIdWeight = $this->getAmazonOrderReferenceIdWeightFromSession(); if ($amazonOrderReferenceIdWeight) { if (isset($amazonOrderReferenceIdWeight['_amazonOrderReferenceId'])) { $this->_amazonOrderReferenceId = $amazonOrderReferenceIdWeight['_amazonOrderReferenceId']; } $referenceIdIsOnlyDigitalGoods = false; if (isset($amazonOrderReferenceIdWeight['isOnlyDigitalGoods'])) { $referenceIdIsOnlyDigitalGoods = $amazonOrderReferenceIdWeight['isOnlyDigitalGoods']; } } if (!$this->_amazonOrderReferenceId OR $this->shouldLoginAgain($referenceIdIsOnlyDigitalGoods, $this->isOnlyDigitalGoods($cart))) { $html .= $this->renderSignInButton($cart); } // amazon is not listed in the payment list. JS displays the signin button return $html; } private function unsetCartLayoutAndPaymentMethod ($cart) { if (!class_exists('VmConfig')) { require(JPATH_ADMINISTRATOR . DS . 'components' . DS . 'com_virtuemart' . DS . 'helpers' . DS . 'config.php'); } VmConfig::loadConfig(); $cart->layout = VmConfig::get('cartlayout', 'default'); $cart->virtuemart_paymentmethod_id = 0; // $cart->prepareAddressDataInCart(); // VM2 function $cart->prepareAddressFieldsInCart(); // empty BT ? $cart->setCartIntoSession(); return; } /** * reset the cart layout, unset the paymentmethod, put back the storeAddress */ private function leaveAmazonCheckout ($msg = NULL) { if (!class_exists('VmConfig')) { require(JPATH_ADMINISTRATOR . DS . 'components' . DS . 'com_virtuemart' . DS . 'helpers' . DS . 'config.php'); } $cart = VirtueMartCart::getCart(); $cart->layout = VmConfig::get('cartlayout', 'default'); $cart->layoutPath = ''; $cart->virtuemart_paymentmethod_id = 0; $previousAddress = $this->getBTandSTFromSession(); $cart->BT = $previousAddress['BT']; $cart->ST = $previousAddress['ST']; $cart->prepareAddressDataInCart('BT', true); // empty BT ? $cart->prepareAddressDataInCart('ST', true); // empty ST ? $cart->setCartIntoSession(); $cart->setOutOfCheckout(); $this->clearAmazonSession(); if ($msg) { $app = JFactory::getApplication(); $app->enqueueMessage($msg); } return; } private function setCartLayout($cart, $intoSession = true) { if (!class_exists('VmConfig')) { require(JPATH_ADMINISTRATOR . DS . 'components' . DS . 'com_virtuemart' . DS . 'helpers' . DS . 'config.php'); } VmConfig::loadConfig(); $cart->layoutPath = vmPlugin::getTemplatePath($this->_name, 'payment', 'cart'); $cart->layout = 'cart'; if ($intoSession) { $cart->setCartIntoSession(); } } /** * plgVmonSelectedCalculatePricePayment * Calculate the price (value, tax_id) of the selected method * It is called by the calculator * This function does NOT to be reimplemented. If not reimplemented, then the default values from this function are taken. * @cart: VirtueMartCart the current cart * @cart_prices: array the new cart prices * @return null if the method was not selected, false if the shipping rate is not valid any more, true otherwise * * */ private static $cartPriceUpdatedDone = false; public function plgVmonSelectedCalculatePricePayment (VirtueMartCart $cart, array &$cart_prices, &$cart_prices_name) { if (!($this->selectedThisByMethodId($cart->virtuemart_paymentmethod_id))) { return NULL; // Another method was selected, do nothing } if (!($this->_currentMethod = $this->getVmPluginMethod($cart->virtuemart_paymentmethod_id))) { $this->clearAmazonSession(); return NULL; } $amazonOrderReferenceIdWeight = $this->getAmazonOrderReferenceIdWeightFromSession(); $this->_amazonOrderReferenceId = $amazonOrderReferenceIdWeight['_amazonOrderReferenceId']; $referenceIdIsOnlyDigitalGoods = $amazonOrderReferenceIdWeight['isOnlyDigitalGoods']; $cart_prices_name = ''; $cart_prices['cost'] = 0; if (!$this->checkConditions($cart, $this->_currentMethod, $cart_prices)) { //vmInfo('VMPAYMENT_AMAZON_PAYMENT_NOT_AVAILABLE'); //$this->unsetCartLayoutAndPaymentMethod($cart); $this->leaveAmazonCheckout(vmText::_('VMPAYMENT_AMAZON_PAYMENT_NOT_AVAILABLE')); return FALSE; } $layout = $cart->layout; if ($this->shouldLoginAgain($referenceIdIsOnlyDigitalGoods, $this->isOnlyDigitalGoods($cart))) { } else { $check = self::$cartPriceUpdatedDone; if (!self::$cartPriceUpdatedDone) { $cartPriceUpdated = ($this->getAmazonSalesPriceFromSession() == $cart_prices['salesPrice']) ? false : true; if ($cartPriceUpdated) { $cart->_dataValidated = false; $cart->setCartIntoSession(); } } $this->renderAddressbookWallet($cart->_dataValidated); } $cart_prices_name = $this->renderPluginName($this->_currentMethod); $this->setCartPrices($cart, $cart_prices, $this->_currentMethod); if (!self::$cartPriceUpdatedDone) { $this->setSalesPriceInSession($cart_prices['salesPrice']); } self::$cartPriceUpdatedDone = true; return TRUE; } private function shouldLoginAgain ($referenceIdIsOnlyDigitalGoods, $isOnlyDigitalGoods) { if (($isOnlyDigitalGoods and $referenceIdIsOnlyDigitalGoods) OR (!$isOnlyDigitalGoods and !$referenceIdIsOnlyDigitalGoods)) { return false; } static $enqueueMessageDone = false; if (!$enqueueMessageDone) { JFactory::getApplication()->enqueueMessage(vmText::_('VMPAYMENT_AMAZON_CLICK_SHOULD_LOGIN_AGAIN')); $enqueueMessageDone = true; } return true; } private function getPixelValue ($value) { $value = str_replace("px", "", $value); $value = $value . 'px'; return trim($value); } /** * plgVmOnCheckAutomaticSelectedPayment * Checks how many plugins are available. If only one, the user will not have the choice. Enter edit_xxx page * The plugin must check first if it is the correct type * * @author Valerie Isaksen * @param VirtueMartCart cart: the cart object * @return null if no plugin was found, 0 if more then one plugin was found, virtuemart_xxx_id if only one plugin is found * */ public function plgVmOnCheckAutomaticSelectedPayment (VirtueMartCart $cart, array $cart_prices = array()) { return $this->onCheckAutomaticSelected($cart, $cart_prices); } /** * This method is fired when showing the order details in the frontend. * It displays the method-specific data. * * @param integer $order_id The order ID * @return mixed Null for methods that aren't active, text (HTML) otherwise * @author Valerie Isaksen */ public function plgVmOnShowOrderFEPayment ($virtuemart_order_id, $virtuemart_paymentmethod_id, &$payment_name) { $this->onShowOrderFE($virtuemart_order_id, $virtuemart_paymentmethod_id, $payment_name); } /** * This method is fired when showing when priting an Order * It displays the the payment method-specific data. * * @param integer $_virtuemart_order_id The order ID * @param integer $method_id method used for this order * @return mixed Null when for payment methods that were not selected, text (HTML) otherwise * @author Valerie Isaksen */ public function plgVmonShowOrderPrintPayment ($order_number, $method_id) { return $this->onShowOrderPrint($order_number, $method_id); } /** * Save updated order data to the method specific table * * @param array $_formData Form data * @return mixed, True on success, false on failures (the rest of the save-process will be * skipped!), or null when this method is not actived. * * public function plgVmOnUpdateOrderPayment( $_formData) { * return null; * } */ /** * Save updated orderline data to the method specific table * * @param array $_formData Form data * @return mixed, True on success, false on failures (the rest of the save-process will be * skipped!), or null when this method is not actived. * * public function plgVmOnUpdateOrderLine( $_formData) { * return null; * } */ /** * plgVmOnEditOrderLineBE * This method is fired when editing the order line details in the backend. * It can be used to add line specific package codes * * @param integer $_orderId The order ID * @param integer $_lineId * @return mixed Null for method that aren't active, text (HTML) otherwise * * public function plgVmOnEditOrderLineBE( $_orderId, $_lineId) { * return null; * } */ /** * This method is fired when showing the order details in the frontend, for every orderline. * It can be used to display line specific package codes, e.g. with a link to external tracking and * tracing systems * * @param integer $_orderId The order ID * @param integer $_lineId * @return mixed Null for method that aren't active, text (HTML) otherwise * * public function plgVmOnShowOrderLineFE( $_orderId, $_lineId) { * return null; * } */ public function plgVmDeclarePluginParamsPayment ($name, $id, &$data) { return $this->declarePluginParams('payment', $name, $id, $data); } public function plgVmSetOnTablePluginParamsPayment ($name, $id, &$table) { return $this->setOnTablePluginParams($name, $id, $table); } function getEmailCurrency (&$method) { return $method->payment_currency; // either the vendor currency, either same currency as payment } private function saveAmazonOrderReferenceId ($cart) { $this->_amazonOrderReferenceId = vRequest::getString('session', ''); $this->setAmazonOrderReferenceIdInSession($this->_amazonOrderReferenceId, $this->isOnlyDigitalGoods($cart)); $cart->virtuemart_paymentmethod_id = vRequest::getInt('pm'); } /*********************/ /* Private functions */ /*********************/ /** * get the partial shipping address (city, state, postal code, and country) by calling the GetOrderReferenceDetails operation * to compute taxes and shipping costs or possible applicable shipping speed, and options. * @param $client * @param $cart */ function updateCartWithAmazonAddress () { $this->loadVmClass('VirtueMartCart', JPATH_VM_SITE . DS . 'helpers' . DS . 'cart.php'); $return = array(); //$this->debug('', 'updateCartWithAmazonAddress', 'debug'); $cart = VirtueMartCart::getCart(); $physicalDestination = $this->getPhysicalDestination(); if (!$physicalDestination) { $return['error'] = 'NoPhysicalDestination'; $return['error_msg'] = vmText::_('VMPAYMENT_AMAZON_UPDATECART_ERROR'); return $return; } $update_data = $this->getUserInfoFromAmazon($physicalDestination); if (!$this->isValidCountry($update_data['virtuemart_country_id'])) { $this->updateCartWithDefaultAmazonAddress($cart, $this->isOnlyDigitalGoods($cart)); $country = shopFunctions::getCountryByID($update_data['virtuemart_country_id']); $cart->_dataValidated = false; $cart->BT['virtuemart_country_id'] = 0; $cart->setCartIntoSession(); $return['error'] = 'deliveryCountryNotAllowed'; $return['error_msg'] = vmText::sprintf('VMPAYMENT_AMAZON_UPDATECART_DELIVERYCOUNTRYNOTALLOWED', $country); return $return; } if ($this->isSameAddress($update_data, $cart)) { $return['error'] = 'sameAddress'; return $return; } $update_data ['address_type'] = 'BT'; $cart->saveAddressInCart($update_data, $update_data['address_type'], TRUE); // update BT and ST with Amazon Partial Address $prefix = 'shipto_'; $update_data = $this->getUserInfoFromAmazon($physicalDestination, $prefix); $update_data ['address_type'] = 'ST'; $cart->saveAddressInCart($update_data, $update_data['address_type'], TRUE, $prefix); $cart->STsameAsBT = false; $cart->setCartIntoSession(); $return['error'] = 'addressUpdated'; return $return; } function getPhysicalDestination () { $this->_amazonOrderReferenceId = $this->getAmazonOrderReferenceIdFromSession(); if (empty($this->_amazonOrderReferenceId)) { //vmError('VMPAYMENT_AMAZON_LOGIN'); return FALSE; } $orderReferenceDetails = $this->getOrderReferenceDetailsResponse(); if (!$orderReferenceDetails) { return false; } $destination = $orderReferenceDetails->GetOrderReferenceDetailsResult->getOrderReferenceDetails()->getDestination(); if (empty($destination)) { // plgVmonSelectedCalculatePricePayment is also called in the module //$this->debug('Destination is empty, noot saving', 'saveAmazonPartialShipmentAddressIncart', 'debug'); return false; } $physicalDestination = $destination->getPhysicalDestination(); return $physicalDestination; } function updateCartWithDefaultAmazonAddress ($cart, $STsameAsBT = true) { $this->loadVmClass('VirtueMartCart', JPATH_VM_SITE . DS . 'helpers' . DS . 'cart.php'); $this->_amazonOrderReferenceId = $this->getAmazonOrderReferenceIdFromSession(); if (empty($this->_amazonOrderReferenceId)) { //vmError('VMPAYMENT_AMAZON_LOGIN'); return FALSE; } $virtuemart_vendor_id = 1; $vendorModel = VmModel::getModel('vendor'); $vendorModel->setId($virtuemart_vendor_id); $vendorFields = $vendorModel->getVendorAddressFields($virtuemart_vendor_id); $skips = array('name', 'username', 'agreed'); // TODO if asynchronous authorization: we set some default fields to the vendor fields $update_dataBT = array(); //$update_dataST = array(); $prefix = 'shipto_'; foreach ($vendorFields['fields'] as $field) { if (!$field['required']) { continue; } if ($field['name'] == 'virtuemart_country_id') { $update_dataBT[$field['name']] = $field[$field['name']]; $update_dataST[$prefix . $field['name']] = $field[$field['name']]; } elseif ($field['name'] == 'virtuemart_state_id') { $update_dataBT[$field['name']] = $field[$field['name']]; $update_dataST[$prefix . $field['name']] = $field['value']; } elseif ($field['name'] == 'email') { $update_dataBT[$field['name']] = $field['value']; $update_dataST[$prefix . $field['name']] = $field['value']; } else { $update_dataBT[$field['name']] = '-'; $update_dataST[$prefix . $field['name']] = '-'; } } $update_dataBT ['address_type'] = 'BT'; $cart->saveAddressInCart($update_dataBT, $update_dataBT['address_type'], TRUE); if (!$STsameAsBT) { $update_dataST ['address_type'] = 'ST'; $cart->STsameAsBT = false; unset($update_dataST['shipto_company']); $cart->saveAddressInCart($update_dataST, $update_dataST['address_type'], TRUE, $prefix); } else { $cart->STsameAsBT = true; } $cart->setCartIntoSession(); return true; } private function isSameAddress ($update_data, $cart) { if ($cart->BT['city'] == $update_data['city'] and $cart->BT['virtuemart_country_id'] == $update_data['virtuemart_country_id'] AND $cart->BT['zip'] == $update_data['zip']) { return true; } return false; } /** * IPN_Handler * * This trigger is invoked whenever a new notification needs to be processed, * and will call the IPN API * * */ private function ipn () { // ERP mode turns off all automated authorization and capture functionality // as well as IPN reception and / or polling, and disables any admin UI functionality that may trigger //If the authorization is done by ERP then the IPN URL set in amazon should not be this one. // we keep it anyway, for testing purposes if ($this->isERPModeEnabled() and $this->isAuthorizationDoneByErp()) { return; } // Fetch all HTTP request headers $headers = $this->getallheaders(); $body = file_get_contents('php://input'); $this->loadAmazonClass('OffAmazonPaymentsNotifications_Client'); $this->loadVmClass('VirtueMartModelOrders', JPATH_VM_ADMINISTRATOR . DS . 'models' . DS . 'orders.php'); try { $client = new OffAmazonPaymentsNotifications_Client(); $notification = $client->parseRawMessage($headers, $body); } catch (OffAmazonPaymentsNotifications_InvalidMessageException $e) { $this->debugLog($e->getMessage() . ' ' . __FUNCTION__ . ' $body', 'error'); header("HTTP/1.1 503 Service Unavailable"); exit(0); } $notificationType = $notification->getNotificationType(); $this->debugLog($notificationType, 'ipn', 'debug'); if (!$this->isValidNotificationtype($notificationType)) { $this->debugLog($notificationType, 'ipn NOT isValidNotificationtype', 'error'); return; } $notificationClass = 'amazonHelper' . $notificationType; $notificationFile = JPATH_SITE . DS . 'plugins' . DS . 'vmpayment' . DS . 'amazon' . DS . 'helpers' . DS . strtolower($notificationType . '.php'); if (!file_exists($notificationFile)) { $this->debugLog("Unknown notification Type: " . $notificationType, __FUNCTION__, 'error'); return false; } if (!class_exists($notificationClass)) { require(JPATH_SITE . DS . 'plugins' . DS . 'vmpayment' . DS . 'amazon' . DS . 'helpers' . DS . 'helper.php'); require($notificationFile); } $this->debugLog($notificationType, 'ipn', 'debug'); $notificationResponse = new $notificationClass($notification, $this->_currentMethod); $this->debugLog("
" . var_export($notificationResponse->amazonData, true) . "
", __FUNCTION__, 'debug'); if (!($order_number = $notificationResponse->getReferenceId())) { /* // it is not really an error, orderReferenceNotification do not send a ReferenceId if ($amazonReferenceId=$notificationResponse->getAmazonReferenceId()) { $payments=$this->getDatasByAmazonReferenceId($amazonReferenceId); if (!$payments) { $this->debugLog('no ReferenceId IPN received', $notificationClass, 'error'); } $orderModel = VmModel::getModel('orders'); $order = $orderModel->getOrder($payments[0]->virtuemart_order_id); $this->storeAmazonInternalData($order, NULL, NULL, $notification, NULL, $notificationResponse->getStoreInternalData()); } */ $this->debugLog('no ReferenceId IPN received', $notificationClass, 'error'); return true; } if (!($virtuemart_order_id = VirtueMartModelOrders::getOrderIdByOrderNumber($order_number))) { $this->debugLog('Received a ' . $notificationClass . ' with order number ' . $order_number . ' but no order in DB with that number', $notificationClass, 'error'); return true; } $orderModel = VmModel::getModel('orders'); $order = $orderModel->getOrder($virtuemart_order_id); if (!($payments = $this->getDatasByOrderId($virtuemart_order_id))) { // we ignore it because we receive also notification when refund/capture is done in the Amazon BE, and there is no valid reference //$this->debugLog('Received a ' . $newClass . ' with order number ' . $order_number . 'but no order in DB with that number in AMAZON payment table', $newClass, 'error'); return true; } $amazonState = $notificationResponse->onNotificationUpdateOrderHistory($order, $payments); $this->storeAmazonInternalData($order, NULL, NULL, $notification, NULL, $notificationResponse->getStoreInternalData()); $nextOperation = $notificationResponse->onNotificationNextOperation($order, $payments, $amazonState); if ($nextOperation === false) { return; } if (!function_exists($nextOperation)) { //$this->debugLog('Trying to call ' . $nextOperation . ' but the function does not exists: Programming error', $notificationClass, 'error'); } $this->$nextOperation($payments, $order); } private function onNotificationGetAuthorization ($payments, $order) { $client = $this->getOffAmazonPaymentsService_Client(); if ($client == NULL) { return; } $this->getAuthorization($client, NULL, $order, false); } private function onNotificationGetAuthorizationDetails ($payments, $order) { $amazonAuthorizationId = $this->getAmazonAuthorizationId($payments); if (!$amazonAuthorizationId) { return false; } $authorizationDetailsResponse = $this->getAuthorizationDetails($amazonAuthorizationId, $order); if (!$authorizationDetailsResponse->isSetGetAuthorizationDetailsResult()) { return; } $getAuthorizationDetailsResult = $authorizationDetailsResponse->getGetAuthorizationDetailsResult(); if (!$getAuthorizationDetailsResult->isSetAuthorizationDetails()) { return; } $getAuthorizationDetails = $getAuthorizationDetailsResult->getAuthorizationDetails(); $this->updateAuthorizeBillingAddressInOrder($getAuthorizationDetails, $order); if ($getAuthorizationDetails->isSetAuthorizationStatus()) { $authorizationStatus = $getAuthorizationDetails->getAuthorizationStatus(); if ($authorizationStatus->isSetState()) { $amazonState = $authorizationStatus->getState(); } if ($authorizationStatus->isSetReasonCode()) { $reasonCode = $authorizationStatus->getReasonCode(); } if ($amazonState == 'Closed') { $this->closeAuthorization($getAuthorizationDetails->getAmazonAuthorizationId(), $order); } } $this->loadHelperClass('amazonHelperGetAuthorizationDetailsResponse'); $amazonHelperGetAuthorizationDetailsResponse = new amazonHelperGetAuthorizationDetailsResponse($authorizationDetailsResponse, $this->_currentMethod); $amazonHelperGetAuthorizationDetailsResponse->onResponseUpdateOrderHistory($order); return; } /** * @param $amazonOrderReferenceId * @param $order */ function closeOrderReference ($amazonOrderReferenceId, $order, $closeReason = 'VMPAYMENT_AMAZON_CLOSE_REASON_ORDER_COMPLETE') { $this->loadAmazonClass('OffAmazonPaymentsService_Model_CloseOrderReferenceRequest'); $client = $this->getOffAmazonPaymentsService_Client(); if ($client == NULL) { return; } try { $closeOrderReferenceRequest = new OffAmazonPaymentsService_Model_CloseOrderReferenceRequest(); $closeOrderReferenceRequest->setSellerId($this->_currentMethod->sellerId); $closeOrderReferenceRequest->setAmazonOrderReferenceId($amazonOrderReferenceId); $closeOrderReferenceRequest->setClosureReason(vmText::_($closeReason)); $closeOrderReferenceResponse = $client->closeOrderReference($closeOrderReferenceRequest); } catch (Exception $e) { $this->amazonError(__FUNCTION__ . ' ' . $e->getMessage(), $e->getCode()); return; } $this->loadHelperClass('amazonHelpercloseOrderReferenceResponse'); $amazonHelperCloseOrderReferenceResponse = new amazonHelpercloseOrderReferenceResponse($closeOrderReferenceResponse, $this->_currentMethod); $storeInternalData = $amazonHelperCloseOrderReferenceResponse->getStoreInternalData(); $this->storeAmazonInternalData($order, $closeOrderReferenceRequest, $closeOrderReferenceResponse, NULL, NULL, $storeInternalData); return; } /** * To close an authorization after the total amount of the authorization has been captured * @return mixed */ function closeAuthorization ($amazonAuthorizationId, $order, $closeReason = 'VMPAYMENT_AMAZON_CLOSE_REASON_ORDER_COMPLETE') { $this->loadAmazonClass('OffAmazonPaymentsService_Model_CloseAuthorizationRequest'); $client = $this->getOffAmazonPaymentsService_Client(); if ($client == NULL) { return; } try { $closeAuthorizationRequest = new OffAmazonPaymentsService_Model_CloseAuthorizationRequest(); $closeAuthorizationRequest->setSellerId($this->_currentMethod->sellerId); $closeAuthorizationRequest->setAmazonAuthorizationId($amazonAuthorizationId); $closeAuthorizationRequest->setClosureReason(vmText::_($closeReason)); $closeAuthorizationResponse = $client->closeAuthorization($closeAuthorizationRequest); } catch (Exception $e) { $this->amazonError(__FUNCTION__ . ' ' . $e->getMessage(), $e->getCode()); return; } $this->loadHelperClass('amazonHelperCloseAuthorizationResponse'); $amazonHelperCloseAutorizationResponse = new amazonHelperCloseAuthorizationResponse($closeAuthorizationResponse, $this->_currentMethod); $storeInternalData = $amazonHelperCloseAutorizationResponse->getStoreInternalData(); $this->storeAmazonInternalData($order, $closeAuthorizationRequest, $closeAuthorizationResponse, NULL, NULL, $storeInternalData); return; } private function isValidNotificationType ($notificationType) { $validNotificationType = array( "OrderReferenceNotification", //"BillingAgreementNotification", "AuthorizationNotification", "CaptureNotification", "RefundNotification", ); if (in_array($notificationType, $validNotificationType)) { $this->debugLog("received notificationType: " . $notificationType, __FUNCTION__, 'debug'); return true; } return false; } private function getWidgetURL () { $region = $this->_currentMethod->region; $region_europe = array('UK', 'DE'); $url = ''; if (in_array($region, $region_europe)) { if ($this->_currentMethod->shop_mode == 'sandbox') { $url = 'https://static-eu.payments-amazon.com/OffAmazonPayments/' . strtolower($region) . '/sandbox/js/Widgets.js'; } else { $url = 'https://static-eu.payments-amazon.com/OffAmazonPayments/' . strtolower($region) . '/js/Widgets.js'; } $url .= '?sellerId=' . $this->_currentMethod->sellerId; } else { if ($this->_currentMethod->environment == 'sandbox') { $url = $this->_currentMethod->sandbox_signin; } else { $url = $this->_currentMethod->production_signin; } } return $url; } private function getAmazonOrderReferenceIdFromPayments ($payments) { foreach ($payments as $payment) { if ($payment->amazon_class_request_type == 'OffAmazonPaymentsService_Model_ConfirmOrderReferenceRequest') { $amazon_request = unserialize($payment->amazon_request); return $amazon_request->AmazonOrderReferenceId; } } } private function incrementRetryInvalidPaymentMethodInSession () { $session = JFactory::getSession(); $sessionAmazon = $session->get('amazon', 0, 'vm'); $sessionAmazonData = json_decode($sessionAmazon, true); if (isset($sessionAmazonData['RetryInvalidPaymentMethod'])) { $sessionAmazonData['RetryInvalidPaymentMethod']++; } else { $sessionAmazonData['RetryInvalidPaymentMethod'] = 0; } $session->set('amazon', json_encode($sessionAmazonData), 'vm'); return $sessionAmazonData['RetryInvalidPaymentMethod']; } private function getRetryInvalidPaymentMethodFromSession () { $session = JFactory::getSession(); $sessionAmazon = $session->get('amazon', 0, 'vm'); $sessionAmazonData = json_decode($sessionAmazon, true); if (isset($sessionAmazonData['RetryInvalidPaymentMethod'])) { return $sessionAmazonData['RetryInvalidPaymentMethod']; } else { return 0; } } /** * save the BT and ST in case the shopper has already given one * @param $cart */ private function saveBTandSTInSession ($cart) { $session = JFactory::getSession(); $sessionAmazon = $session->get('amazon', 0, 'vm'); $sessionAmazonData = json_decode($sessionAmazon, true); // check if it is already saved or not if (!isset($sessionAmazonData['BT'])) { $sessionAmazonData['BT'] = $cart->BT; $sessionAmazonData['ST'] = $cart->ST; $session->set('amazon', json_encode($sessionAmazonData), 'vm'); } } private function getBTandSTFromSession () { $session = JFactory::getSession(); $sessionAmazon = $session->get('amazon', 0, 'vm'); $address['BT'] = NULL; $address['ST'] = NULL; if ($sessionAmazon) { $sessionAmazonData = json_decode($sessionAmazon, true); if (isset($sessionAmazonData['BT']) OR isset($sessionAmazonData['ST'])) { $address['BT'] = $sessionAmazonData['BT']; $address['ST'] = $sessionAmazonData['ST']; } } return $address; } /** * @return null */ private function getAmazonOrderReferenceIdWeightFromSession () { $session = JFactory::getSession(); $sessionAmazon = $session->get('amazon', 0, 'vm'); if ($sessionAmazon) { $sessionAmazonData = json_decode($sessionAmazon, true); if (isset($sessionAmazonData[$this->_currentMethod->virtuemart_paymentmethod_id])) { return $sessionAmazonData[$this->_currentMethod->virtuemart_paymentmethod_id]; } } return NULL; } /** * @return null */ private function clearAmazonSession () { $session = JFactory::getSession(); $session->clear('amazon', 'vm'); return NULL; } /** * @return null */ private function getAmazonSalesPriceFromSession () { $session = JFactory::getSession(); $sessionAmazon = $session->get('amazon', 0, 'vm'); if ($sessionAmazon) { $sessionAmazonData = json_decode($sessionAmazon, true); if (isset($sessionAmazonData[$this->_currentMethod->virtuemart_paymentmethod_id]) and isset($sessionAmazonData[$this->_currentMethod->virtuemart_paymentmethod_id]['_salesPrices']) ) { return $sessionAmazonData[$this->_currentMethod->virtuemart_paymentmethod_id]['_salesPrices']; } } return NULL; } /** * @param $salesPrices */ private function setSalesPriceInSession ($salesPrices) { $session = JFactory::getSession(); $sessionAmazon = $session->get('amazon', 0, 'vm'); if ($sessionAmazon) { $sessionAmazonData = json_decode($sessionAmazon, true); } else { $sessionAmazonData = array(); } $sessionAmazonData['virtuemart_paymentmethod_id'] = $this->_currentMethod->virtuemart_paymentmethod_id; $sessionAmazonData[$this->_currentMethod->virtuemart_paymentmethod_id]['_salesPrices'] = $salesPrices; $session->set('amazon', json_encode($sessionAmazonData), 'vm'); } /** * @return null */ private function getAmazonOrderReferenceIdFromSession () { $session = JFactory::getSession(); $sessionAmazon = $session->get('amazon', 0, 'vm'); if ($sessionAmazon) { $sessionAmazonData = json_decode($sessionAmazon, true); if (isset($sessionAmazonData[$this->_currentMethod->virtuemart_paymentmethod_id])) { return $sessionAmazonData[$this->_currentMethod->virtuemart_paymentmethod_id]['_amazonOrderReferenceId']; } } return NULL; } /** * @return null */ private function getisOnlyDigitalGoodsFromSession () { $session = JFactory::getSession(); $sessionAmazon = $session->get('amazon', 0, 'vm'); if ($sessionAmazon) { $sessionAmazonData = json_decode($sessionAmazon, true); if (isset($sessionAmazonData[$this->_currentMethod->virtuemart_paymentmethod_id])) { return $sessionAmazonData[$this->_currentMethod->virtuemart_paymentmethod_id]['isOnlyDigitalGoods']; } } return NULL; } /** * @param $amazonOrderReferenceId * @param $isOnlyDigitalGoods */ private function setAmazonOrderReferenceIdInSession ($amazonOrderReferenceId, $isOnlyDigitalGoods) { $session = JFactory::getSession(); $sessionAmazon = $session->get('amazon', 0, 'vm'); if ($sessionAmazon) { $sessionAmazonData = json_decode($sessionAmazon, true); } else { $sessionAmazonData = array(); } $sessionAmazonData['virtuemart_paymentmethod_id'] = $this->_currentMethod->virtuemart_paymentmethod_id; $sessionAmazonData[$this->_currentMethod->virtuemart_paymentmethod_id]['_amazonOrderReferenceId'] = $amazonOrderReferenceId; $sessionAmazonData[$this->_currentMethod->virtuemart_paymentmethod_id]['isOnlyDigitalGoods'] = $isOnlyDigitalGoods; $session->set('amazon', json_encode($sessionAmazonData), 'vm'); } /** * Use the order reference object to query the order information, including * the current physical delivery address as selected by the buyer * * @return OffAmazonPaymentsService_Model_GetOrderReferenceDetailsResponse service response */ private function getOrderReferenceDetailsResponse ($addressConsentToken = null) { $this->loadAmazonClass('OffAmazonPaymentsService_Model_GetOrderReferenceDetailsRequest'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_GetOrderReferenceDetailsResponse'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_OrderReferenceDetails'); //$_amazonOrderReferenceId = $this->getAmazonOrderReferenceId(); if (empty($this->_amazonOrderReferenceId)) { vmError('VMPAYMENT_AMAZON_LOGIN'); return FALSE; } $client = $this->getOffAmazonPaymentsService_Client(); if ($client == NULL) { return NULL; } try { $getOrderReferenceDetailsRequest = new OffAmazonPaymentsService_Model_GetOrderReferenceDetailsRequest(); $getOrderReferenceDetailsRequest->setSellerId($this->_currentMethod->sellerId); $getOrderReferenceDetailsRequest->setAmazonOrderReferenceId($this->_amazonOrderReferenceId); if (is_null($addressConsentToken) == FALSE) { $decodedToken = urldecode($addressConsentToken); $getOrderReferenceDetailsRequest->setAddressConsentToken($decodedToken); } $orderReferenceDetailsResponse = $client->getOrderReferenceDetails($getOrderReferenceDetailsRequest); } catch (Exception $e) { $this->amazonError(__FUNCTION__ . ' ' . $e->getMessage(), $e->getCode()); return FALSE; } $this->debugLog($orderReferenceDetailsResponse, 'getOrderReferenceDetailsResponse', 'debug'); return $orderReferenceDetailsResponse; } private function isValidUpdateOrderStatus ($orderStatus) { $validOrderStatus = array( $this->_currentMethod->status_capture, $this->_currentMethod->status_refunded, $this->_currentMethod->status_cancel, ); if (!in_array($orderStatus, $validOrderStatus)) { return false; } return true; } /** * @return bool */ private function isCaptureImmediate ($cart) { if ($cart) { return ($this->_currentMethod->capture_mode == "capture_immediate" OR $this->isSomeDigitalGoods($cart)); } else { return false; } } private function isERPModeEnabled () { if ($this->_currentMethod->erp_mode == "erp_mode_enabled") { return true; } else { return false; } } private function isAuthorizationDoneByErp () { if ($this->_currentMethod->authorization_mode_erp_enabled == "authorization_done_by_erp") { return true; } else { return false; } } /** * in case of only Digital Goods, the Address Wallet is not displayed * @param $cart * @return bool */ private function isOnlyDigitalGoods ($cart) { if (!$this->_currentMethod->digital_goods) { return false; } if ($cart) { $weight = $this->getOrderWeight($cart, 'GR'); } else { $weight = $this->getisOnlyDigitalGoodsFromSession(); } if ($weight == 0) { return true; } else { return false; } } /** * In case of some Digital goods, the capture is immediate * @param $cart * @return bool */ private function isSomeDigitalGoods ($cart) { if (!$this->_currentMethod->digital_goods) { return false; } foreach ($cart->products as $product) { if ($product->product_weight == 0) { return true; } } return false; } /** * in VM, the payment is not showed if the buyer browse in another language * @return bool */ private function isValidLanguage () { if (!$this->_currentMethod->language_restriction) { return true; } $lang = JFactory::getLanguage(); $tag = strtolower(substr($lang->get('tag'), 0, 2)); if (array_key_exists($tag, $this->languages_region) AND $this->languages_region[$tag] == $this->_currentMethod->region) { return true; } return false; } /** * @return bool */ private function isValidAmount ($amount) { $this->_currentMethod->min_amount = (float)str_replace(',', '.', $this->_currentMethod->min_amount); $this->_currentMethod->max_amount = (float)str_replace(',', '.', $this->_currentMethod->max_amount); $amount_cond = ($amount > 0 AND $amount >= $this->_currentMethod->min_amount AND $amount <= $this->_currentMethod->max_amount OR ($this->_currentMethod->min_amount <= $amount AND ($this->_currentMethod->max_amount == 0))); if ($amount == 0 or !$amount_cond) { vmdebug('AMAZON checkConditions $amount_cond false'); return false; } return true; } /** * Exclusion of unsupported items: product categories as “not available via Amazon Payments”. * @param $cart * @return bool */ private function isValidProductCategories ($cart) { if (!is_array($this->_currentMethod->exclude_categories)) { $exclude_categories[0] = $this->_currentMethod->exclude_categories; } else { $exclude_categories = $this->_currentMethod->exclude_categories; } foreach ($cart->products as $product) { if (array_intersect($exclude_categories, $product->categories)) { return false; } } return true; } // // Session functions // private function getDataFromSession () { $session = JFactory::getSession(); $sessionAmazon = $session->get('amazon', 0, 'vm'); if ($sessionAmazon) { $sessionAmazonData = json_decode($sessionAmazon, true); return $sessionAmazonData; } return false; } // // DEBUG AND LOG FUNCTIONS // /** * @param string $message * @param string $title * @param string $type * @param bool $echo * @param bool $doVmDebug */ function debugLog ($message, $title = '', $type = 'message', $echo = false, $doVmDebug = false) { if ($this->_currentMethod->debug) { $this->debug($message, $title, true); } if ($echo) { echo $message . '
'; } parent::debugLog($message, $title, $type, $doVmDebug); } private function debug ($subject, $title = '', $echo = true) { $debug = '
'; $debug .= ($title) ? '
' . $title . ':
' : ''; //$debug .= '
';
		if (is_array($subject)) {
			$debug .= str_replace("=>", "⇒", str_replace("Array", "Array", nl2br(str_replace(" ", "   ", print_r($subject, true)))));
		} else {
			//$debug .= str_replace("=>", "⇒", str_replace("Array", "Array", (str_replace(" ", "   ", print_r($subject, true)))));
			$debug .= str_replace("=>", "⇒", str_replace("Array", "Array", print_r($subject, true)));

		}

		//$debug .= '
'; $debug .= '
'; if ($echo) { echo $debug; } else { return $debug; } } // // Load classes / files if not exists // function loadAmazonServicesClasses () { $this->loadAmazonClass('OffAmazonPaymentsService_Client'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_SetOrderReferenceDetailsResponse'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_Price'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_OrderTotal'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_SellerOrderAttributes'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_ResponseHeaderMetadata'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_ResponseMetadata'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_AuthorizeResult'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_AuthorizationDetails'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_AuthorizeResponse'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_Address'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_IdList'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_Status'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_CaptureDetails'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_CaptureResult'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_GetCaptureDetailsResponse'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_GetCaptureDetailsResult'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_RefundResult'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_RefundDetails'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_RefundResponse'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_CloseOrderReferenceRequest'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_GetAuthorizationDetailsResult'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_GetRefundDetailsResult'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_CloseAuthorizationRequest'); $this->loadAmazonClass('OffAmazonPaymentsService_Model_CloseAuthorizationResult'); } function loadAmazonNotificationClasses () { $this->loadAmazonClass('OffAmazonPaymentsNotifications_Client'); $this->loadAmazonClass('OffAmazonPaymentsNotifications_Model_AuthorizationNotification'); $this->loadAmazonClass('OffAmazonPaymentsNotifications_Model_AuthorizationDetails'); $this->loadAmazonClass('OffAmazonPaymentsNotifications_Model_Price'); $this->loadAmazonClass('OffAmazonPaymentsNotifications_Model_IdList'); $this->loadAmazonClass('OffAmazonPaymentsNotifications_Model_Status'); $this->loadAmazonClass('OffAmazonPaymentsNotifications_Model_OrderItemCategories'); $this->loadAmazonClass('OffAmazonPaymentsNotifications_Model_RefundNotification'); $this->loadAmazonClass('OffAmazonPaymentsNotifications_Model_RefundDetails'); $this->loadAmazonClass('OffAmazonPaymentsNotifications_Model_CaptureNotification'); $this->loadAmazonClass('OffAmazonPaymentsNotifications_Model_CaptureDetails'); $this->loadAmazonClass('OffAmazonPaymentsNotifications_Model_IPNNotificationMetadata'); $this->loadAmazonClass('OffAmazonPaymentsNotifications_NotificationImpl'); $this->loadAmazonClass('OffAmazonPaymentsNotifications_Model_SnsNotificationMetadata'); $this->loadAmazonClass('OffAmazonPaymentsNotifications_Model_OrderTotal'); } function loadAmazonClass ($className) { if (!class_exists($className)) { $filePath = JPATH_SITE . DS . 'plugins' . DS . 'vmpayment' . DS . 'amazon' . DS . 'library' . DS . str_replace('_', DS, $className) . '.php'; if (file_exists($filePath)) { require $filePath; return; } else { vmError('Programming error: trying to load:' . $filePath); } } } function loadHelperClass ($className) { if (!class_exists('amazonHelper')) { require(JPATH_SITE . DS . 'plugins' . DS . 'vmpayment' . DS . 'amazon' . DS . 'helpers' . DS . 'helper.php'); } if (!class_exists($className)) { $fileName = strtolower(str_replace('amazonHelper', '', $className)) . '.php'; $fileNameAbsPath = JPATH_SITE . DS . 'plugins' . DS . 'vmpayment' . DS . 'amazon' . DS . 'helpers' . DS . $fileName; if (file_exists($fileNameAbsPath)) { require($fileNameAbsPath); } else { vmError('Programming error: ' . __FUNCTION__ . ' trying to load:' . $fileNameAbsPath); } } } function loadVmClass ($className, $fileName) { if (!class_exists($className)) { if (file_exists($fileName)) { require($fileName); } else { vmError('Programming error:' . __FUNCTION__ . ' trying to load:' . $fileName); } } } function getallheaders () { if (!function_exists('getallheaders')) { //$this->debugLog("getallheaders PHP function does not exists" . "
" . var_export($_SERVER, true) . "
", __FUNCTION__, 'debug'); $headers = ''; foreach ($_SERVER as $name => $value) { if (substr($name, 0, 5) == 'HTTP_') { $headers[str_replace(' ', '-', strtolower(str_replace('_', ' ', substr($name, 5))))] = $value; } } //$this->debugLog("getallheaders Local function returns" . "
" . var_export($headers, true) . "
", __FUNCTION__, 'debug'); return $headers; } else { return getallheaders(); } } } // No closing tag