diff --git a/src/catalog/controller/checkout/pingback.php b/src/catalog/controller/checkout/pingback.php index 363f2a3..ab7b5e3 100644 --- a/src/catalog/controller/checkout/pingback.php +++ b/src/catalog/controller/checkout/pingback.php @@ -5,7 +5,14 @@ class ControllerCheckoutPingback extends Controller protected $paymentModel; const DEFAULT_PINGBACK_RESPONSE_SUCCESS = "OK"; - + const TRANSACTION_CREATED = 0; + const TRANSACTION_COMPLETED = 1; + const TRANSACTION_CANCELED = 5; + const TRANSACTION_SKIPPED = 3; + const RECURRING_PEDING = 6; + const RECURRING_ACTIVE = 2; + const RECURRING_CANCELED = 4; + public function index() { $this->load->model('setting/setting'); @@ -31,37 +38,77 @@ public function index() } if ($pingback->validate()) { + $referenceId = $pingback->getReferenceId(); + $transactionStatus = self::TRANSACTION_CREATED; + $recurringStatus = self::RECURRING_PEDING; if ($pingback->isDeliverable()) { - $this->getPaymentModel()->callDeliveryApi($order, $pingback->getReferenceId()); - - if ($order['order_status_id'] != $this->config->get($order['payment_code'] . '_complete_status')) { - $this->getCheckoutOrderModel()->update( - $orderId, - $this->config->get($order['payment_code'] . '_complete_status'), - 'Order approved!, Transaction Id: #' . $pingback->getReferenceId(), - true - ); - } + $transactionStatus = self::TRANSACTION_COMPLETED; + $recurringStatus = self::RECURRING_ACTIVE; + + $this->getPaymentModel()->callDeliveryApi($order, $referenceId); + + $this->getCheckoutOrderModel()->update( + $orderId, + $this->config->get($order['payment_code'] . '_complete_status'), + 'Order approved!, Transaction Id: #' . $referenceId, + true + ); } elseif ($pingback->isCancelable()) { - if ($order['order_status_id'] != $this->config->get($order['payment_code'] . '_cancel_status')) { - $this->getCheckoutOrderModel() - ->update($orderId, $this->config->get($order['payment_code'] .'_cancel_status'), 'Order canceled!', true); - } + $transactionStatus = self::TRANSACTION_CANCELED; + $recurringStatus = self::RECURRING_CANCELED; + + $this->getCheckoutOrderModel() + ->update($orderId, $this->config->get($order['payment_code'] .'_cancel_status'), 'Order canceled!', true); } elseif ($pingback->isUnderReview()) { - if ($order['order_status_id'] != $this->config->get($order['payment_code'] . '_under_review_status')) { - $this->getCheckoutOrderModel() - ->update($orderId, $this->config->get($order['payment_code'] .'_under_review_status'), 'The order is under review!', false); - } + $this->getCheckoutOrderModel() + ->update($orderId, $this->config->get($order['payment_code'] .'_under_review_status'), 'The order is under review!', true); } + $this->updateRecurringOrder($order, $referenceId, $transactionStatus, $recurringStatus); + echo self::DEFAULT_PINGBACK_RESPONSE_SUCCESS; } else { echo $pingback->getErrorSummary(); } } + public function updateRecurringOrder($orderInfo, $ref, $transactionStatus, $recurringStatus) + { + try { + $orderRecurring = $this->db->query("SELECT * FROM `" . DB_PREFIX . "order_recurring` WHERE `order_id` = {$orderInfo['order_id']} ORDER BY order_recurring_id DESC LIMIT 1")->row; + if (!empty($orderRecurring)) { + $this->load->model('checkout/recurring'); + $orderRecurringId = $orderRecurring['order_recurring_id']; + if (!empty($orderRecurring['profile_reference'])) { + $orderRecurring['name'] = $orderRecurring['product_name']; + $orderRecurring['quantity'] = $orderRecurring['product_quantity']; + $orderRecurring['description'] = $orderRecurring['profile_description']; + $orderRecurring['recurring_trial'] = $orderRecurring['trial']; + $orderRecurring['recurring_trial_cycle'] = $orderRecurring['trial_cycle']; + $orderRecurring['recurring_trial_duration'] = $orderRecurring['trial_duration']; + $orderRecurring['recurring_trial_price'] = $orderRecurring['trial_price']; + + $orderRecurringId = $this->model_checkout_recurring->create($orderRecurring, $orderInfo['order_id'], ''); + } + $this->model_checkout_recurring->addReference($orderRecurringId, $ref); + + $amount = $orderInfo['currency_value'] > 0 + ? ($orderInfo['total'] * $orderInfo['currency_value']) + : $orderInfo['total']; + $this->updateRecurringTransaction($orderRecurringId, $amount, $transactionStatus, $recurringStatus); + } + } catch (Exception $ex) {} + } + + protected function updateRecurringTransaction($order_recurring_id, $amount, $transactionStatus, $recurringStatus) { + try { + $this->db->query("INSERT INTO `" . DB_PREFIX . "order_recurring_transaction` SET `order_recurring_id` = {$order_recurring_id}, `created` = NOW(), `amount` = {$amount}, `type` = {$transactionStatus}"); + $this->db->query("UPDATE `" . DB_PREFIX . "order_recurring` SET `status` = {$recurringStatus} WHERE `order_recurring_id` = {$order_recurring_id} LIMIT 1"); + } catch (Exception $ex) {} + } + /** * @return ModelPaymentBrick | ModelPaymentPaymentwall */ diff --git a/src/catalog/controller/payment/paymentwall.php b/src/catalog/controller/payment/paymentwall.php index cf0ae22..90715c5 100644 --- a/src/catalog/controller/payment/paymentwall.php +++ b/src/catalog/controller/payment/paymentwall.php @@ -26,6 +26,7 @@ public function widget() $orderId = @$this->session->data['order_id']; $orderInfo = $this->getCheckoutOrderModel()->getOrder($orderId); + $products = $this->cart->getProducts(); if (!empty($orderInfo)) { $this->cart->clear(); @@ -35,6 +36,14 @@ public function widget() $this->redirect($this->url->link('checkout/cart', '', 'SSL')); } + $cartProducts = reset($products); + + if (!empty($cartProducts['recurring'])) { + $this->load->model('checkout/recurring'); + $profileDesciption = $this->getProfileDescription($cartProducts); + $this->model_checkout_recurring->create($cartProducts, $orderInfo['order_id'], $profileDesciption); + } + $this->document->setTitle($this->language->get('widget_title')); $this->data['breadcrumbs'] = array(); @@ -55,7 +64,8 @@ public function widget() $this->data['iframe'] = $this->getPaymentModel()->generateWidget( $orderInfo, $this->customer, - $this->url->link('checkout/success', '', 'SSL') + $this->url->link('checkout/success', '', 'SSL'), + $cartProducts ); if (file_exists(DIR_TEMPLATE . $this->config->get('config_template') . '/template/payment/paymentwall_widget.tpl')) { @@ -76,10 +86,43 @@ public function widget() $this->response->setOutput($this->render()); } + /** + * @return Profile description + */ + protected function getProfileDescription($product) + { + $this->language->load('checkout/cart'); + $profile_description = ''; + + $frequencies = array( + 'day' => $this->language->get('text_day'), + 'week' => $this->language->get('text_week'), + 'semi_month' => $this->language->get('text_semi_month'), + 'month' => $this->language->get('text_month'), + 'year' => $this->language->get('text_year'), + ); + + if ($product['recurring_trial']) { + $recurring_price = $this->currency->format($this->tax->calculate($product['recurring_trial_price'] * $product['quantity'], $product['tax_class_id'], $this->config->get('config_tax'))); + $profile_description = sprintf($this->language->get('text_trial_description'), $recurring_price, $product['recurring_trial_cycle'], $frequencies[$product['recurring_trial_frequency']], $product['recurring_trial_duration']) . ' '; + } + + $recurring_price = $this->currency->format($this->tax->calculate($product['recurring_price'] * $product['quantity'], $product['tax_class_id'], $this->config->get('config_tax'))); + + if ($product['recurring_duration']) { + $profile_description .= sprintf($this->language->get('text_payment_description'), $recurring_price, $product['recurring_cycle'], $frequencies[$product['recurring_frequency']], $product['recurring_duration']); + } else { + $profile_description .= sprintf($this->language->get('text_payment_until_canceled_description'), $recurring_price, $product['recurring_cycle'], $frequencies[$product['recurring_frequency']], $product['recurring_duration']); + } + + return $profile_description; + } + /** * @return ModelPaymentPaymentwall */ - protected function getPaymentModel(){ + protected function getPaymentModel() + { if(!$this->model_payment_paymentwall){ $this->load->model('payment/paymentwall'); } diff --git a/src/catalog/model/payment/paymentwall.php b/src/catalog/model/payment/paymentwall.php index fb06a47..759509b 100644 --- a/src/catalog/model/payment/paymentwall.php +++ b/src/catalog/model/payment/paymentwall.php @@ -85,31 +85,27 @@ protected function prepareDeliveryData($order, $ref) * @param $successUrl * @return string */ - public function generateWidget($orderInfo, $customer, $successUrl) + public function generateWidget($orderInfo, $customer, $successUrl, $cartProducts) { $successUrl = $this->config->get('paymentwall_success_url') ? $this->config->get('paymentwall_success_url') : $successUrl; + $this->load->model('catalog/product'); + $widget = new Paymentwall_Widget( $customer->getId() ? $customer->getId() : $orderInfo['email'], $this->config->get('paymentwall_widget'), array( - new Paymentwall_Product( - $orderInfo['order_id'], - $orderInfo['currency_value'] > 0 - ? ($orderInfo['total'] * $orderInfo['currency_value']) - : $orderInfo['total'], // when currency_value <= 0 changes to 1 - $orderInfo['currency_code'], - 'Order #' . $orderInfo['order_id'] - ) + $this->getProduct($orderInfo, $cartProducts, $hasTrial) ), array_merge( array( 'success_url' => $successUrl, 'email' => $orderInfo['email'], 'integration_module' => 'opencart', - 'test_mode' => $this->config->get('paymentwall_test') + 'test_mode' => $this->config->get('paymentwall_test'), + 'hide_post_trial_good' => $hasTrial ? 1 : 0, ), $this->getUserProfileData($orderInfo) )); @@ -121,6 +117,83 @@ public function generateWidget($orderInfo, $customer, $successUrl) )); } + public function getProduct($orderInfo, $cartProducts, &$hasTrial) + { + $price = $orderInfo['currency_value'] > 0 + ? ($orderInfo['total'] * $orderInfo['currency_value']) + : $orderInfo['total']; + $periodType = null; + $recurringDuration = null; + $trialProduct = null; + $typeProduct = Paymentwall_Product::TYPE_SUBSCRIPTION; + $hasTrial = false; + + if (count($cartProducts['quantity']) > 1) { + $typeProduct = Paymentwall_Product::TYPE_FIXED; + } + + if ($typeProduct == Paymentwall_Product::TYPE_SUBSCRIPTION) { + $subScriptionProduct = $cartProducts; + $recurringDuration = $subScriptionProduct['recurring_duration']; + $periodType = $this->getPeriodType($subScriptionProduct['recurring_frequency'], $recurringDuration); + + if ($subScriptionProduct['recurring_trial']) { + $hasTrial = true; + $recurringTrialDuration = $subScriptionProduct['recurring_trial_duration']; + $periodTrialType = $this->getPeriodType($subScriptionProduct['recurring_trial_frequency'], $recurringTrialDuration); + + $trialProduct = new Paymentwall_Product( + $orderInfo['order_id'], + $price, + $orderInfo['currency_code'], + $subScriptionProduct['name'], + $typeProduct, + $recurringTrialDuration, + $periodTrialType, + true + ); + } + } + + return new Paymentwall_Product( + $orderInfo['order_id'], + $price, + $orderInfo['currency_code'], + 'Order #' . $orderInfo['order_id'], + $typeProduct, + $recurringDuration, + $periodType, + ($typeProduct == Paymentwall_Product::TYPE_SUBSCRIPTION) ? true : false, + $trialProduct + ); + } + + protected function getPeriodType($recurringFrequency, &$recurringDuration) + { + switch ($recurringFrequency) { + case 'day': + $periodType = Paymentwall_Product::PERIOD_TYPE_DAY; + break; + case 'week': + $periodType = Paymentwall_Product::PERIOD_TYPE_WEEK; + break; + case 'semi_month': + $periodType = Paymentwall_Product::PERIOD_TYPE_WEEK; + $recurringDuration = $recurringDuration * 2; //2 weeks + break; + case 'month': + $periodType = Paymentwall_Product::PERIOD_TYPE_MONTH; + break; + case 'year': + $periodType = Paymentwall_Product::PERIOD_TYPE_YEAR; + break; + default: + break; + } + + return $periodType; + } + /** * @param $orderInfo * @return array @@ -139,4 +212,13 @@ protected function getUserProfileData($orderInfo) 'email' => $orderInfo['email'], ); } + + public function recurringPayments() + { + /* + * Used by the checkout to state the module + * supports recurring profiles. + */ + return true; + } } diff --git a/src/catalog/view/theme/default/image/loading.gif b/src/catalog/view/theme/default/image/loading.gif new file mode 100644 index 0000000..0241bdd Binary files /dev/null and b/src/catalog/view/theme/default/image/loading.gif differ