From 8f17fb61e7615a505256b15409fa9c303c590f6b Mon Sep 17 00:00:00 2001 From: Novalnet-Technic Date: Wed, 10 Nov 2021 18:09:23 +0530 Subject: [PATCH] first commit --- admin/novalnet.php | 769 +++++++ callback_novalnet2oscommerce.php | 719 +++++++ includes/classes/novalnet/class.Novalnet.php | 805 ++++++++ .../novalnet/class.NovalnetInstaller.php | 117 ++ .../novalnet/class.NovalnetInterface.php | 1779 +++++++++++++++++ .../novalnet/class.NovalnetPaymentKeys.php | 1032 ++++++++++ .../novalnet/class.NovalnetTranslator.php | 96 + .../novalnet/class.NovalnetValidation.php | 349 ++++ includes/classes/novalnet/css/loader.css | 9 + includes/classes/novalnet/db.sql | 120 ++ includes/classes/novalnet/db_version11.sql | 13 + includes/classes/novalnet/img/amex.png | Bin 0 -> 2506 bytes includes/classes/novalnet/img/cartasi.png | Bin 0 -> 20381 bytes .../classes/novalnet/img/creditcard_cvc.png | Bin 0 -> 24905 bytes includes/classes/novalnet/img/cvc_hint.png | Bin 0 -> 651 bytes includes/classes/novalnet/img/eps.png | Bin 0 -> 2888 bytes includes/classes/novalnet/img/ideal.png | Bin 0 -> 2840 bytes includes/classes/novalnet/img/invoice.png | Bin 0 -> 865 bytes includes/classes/novalnet/img/loader.gif | Bin 0 -> 7356 bytes includes/classes/novalnet/img/logo.png | Bin 0 -> 5470 bytes includes/classes/novalnet/img/maestro.png | Bin 0 -> 16438 bytes includes/classes/novalnet/img/paypal.png | Bin 0 -> 2565 bytes includes/classes/novalnet/img/prepayment.png | Bin 0 -> 1264 bytes includes/classes/novalnet/img/sepa.png | Bin 0 -> 4755 bytes includes/classes/novalnet/img/sofortbank.png | Bin 0 -> 2903 bytes .../classes/novalnet/img/visa_mastercard.png | Bin 0 -> 3134 bytes includes/classes/novalnet/js/jquery.js | 4 + includes/classes/novalnet/js/novalnet_api.js | 104 + includes/classes/novalnet/js/novalnet_cc.js | 231 +++ .../classes/novalnet/js/novalnet_cc_iframe.js | 101 + includes/classes/novalnet/js/novalnet_sepa.js | 332 +++ .../novalnet/js/novalnet_sepa_iframe.js | 95 + .../classes/novalnet/languages/english.php | 344 ++++ .../classes/novalnet/languages/german.php | 344 ++++ includes/classes/novalnet/orders/novalnet.php | 93 + includes/classes/novalnet/version.php | 25 + .../english/modules/payment/novalnet_cc.php | 19 + .../modules/payment/novalnet_config.php | 19 + .../english/modules/payment/novalnet_eps.php | 19 + .../modules/payment/novalnet_ideal.php | 19 + .../modules/payment/novalnet_invoice.php | 19 + .../modules/payment/novalnet_paypal.php | 19 + .../modules/payment/novalnet_prepayment.php | 19 + .../english/modules/payment/novalnet_sepa.php | 19 + .../modules/payment/novalnet_sofortbank.php | 19 + .../german/modules/payment/novalnet_cc.php | 19 + .../modules/payment/novalnet_config.php | 19 + .../german/modules/payment/novalnet_eps.php | 19 + .../german/modules/payment/novalnet_ideal.php | 19 + .../modules/payment/novalnet_invoice.php | 19 + .../modules/payment/novalnet_paypal.php | 19 + .../modules/payment/novalnet_prepayment.php | 19 + .../german/modules/payment/novalnet_sepa.php | 19 + .../modules/payment/novalnet_sofortbank.php | 19 + includes/modules/payment/novalnet_cc.php | 319 +++ includes/modules/payment/novalnet_config.php | 50 + includes/modules/payment/novalnet_eps.php | 129 ++ includes/modules/payment/novalnet_ideal.php | 125 ++ includes/modules/payment/novalnet_invoice.php | 160 ++ includes/modules/payment/novalnet_paypal.php | 128 ++ .../modules/payment/novalnet_prepayment.php | 123 ++ includes/modules/payment/novalnet_sepa.php | 292 +++ .../modules/payment/novalnet_sofortbank.php | 128 ++ novalnet_css_link.php | 22 + novalnet_form.php | 51 + novalnet_subscription_stop.php | 72 + 66 files changed, 9422 insertions(+) create mode 100644 admin/novalnet.php create mode 100644 callback_novalnet2oscommerce.php create mode 100644 includes/classes/novalnet/class.Novalnet.php create mode 100644 includes/classes/novalnet/class.NovalnetInstaller.php create mode 100644 includes/classes/novalnet/class.NovalnetInterface.php create mode 100644 includes/classes/novalnet/class.NovalnetPaymentKeys.php create mode 100644 includes/classes/novalnet/class.NovalnetTranslator.php create mode 100644 includes/classes/novalnet/class.NovalnetValidation.php create mode 100644 includes/classes/novalnet/css/loader.css create mode 100644 includes/classes/novalnet/db.sql create mode 100644 includes/classes/novalnet/db_version11.sql create mode 100644 includes/classes/novalnet/img/amex.png create mode 100644 includes/classes/novalnet/img/cartasi.png create mode 100644 includes/classes/novalnet/img/creditcard_cvc.png create mode 100644 includes/classes/novalnet/img/cvc_hint.png create mode 100644 includes/classes/novalnet/img/eps.png create mode 100644 includes/classes/novalnet/img/ideal.png create mode 100644 includes/classes/novalnet/img/invoice.png create mode 100644 includes/classes/novalnet/img/loader.gif create mode 100644 includes/classes/novalnet/img/logo.png create mode 100644 includes/classes/novalnet/img/maestro.png create mode 100644 includes/classes/novalnet/img/paypal.png create mode 100644 includes/classes/novalnet/img/prepayment.png create mode 100644 includes/classes/novalnet/img/sepa.png create mode 100644 includes/classes/novalnet/img/sofortbank.png create mode 100644 includes/classes/novalnet/img/visa_mastercard.png create mode 100644 includes/classes/novalnet/js/jquery.js create mode 100644 includes/classes/novalnet/js/novalnet_api.js create mode 100644 includes/classes/novalnet/js/novalnet_cc.js create mode 100644 includes/classes/novalnet/js/novalnet_cc_iframe.js create mode 100644 includes/classes/novalnet/js/novalnet_sepa.js create mode 100644 includes/classes/novalnet/js/novalnet_sepa_iframe.js create mode 100644 includes/classes/novalnet/languages/english.php create mode 100644 includes/classes/novalnet/languages/german.php create mode 100644 includes/classes/novalnet/orders/novalnet.php create mode 100644 includes/classes/novalnet/version.php create mode 100644 includes/languages/english/modules/payment/novalnet_cc.php create mode 100644 includes/languages/english/modules/payment/novalnet_config.php create mode 100644 includes/languages/english/modules/payment/novalnet_eps.php create mode 100644 includes/languages/english/modules/payment/novalnet_ideal.php create mode 100644 includes/languages/english/modules/payment/novalnet_invoice.php create mode 100644 includes/languages/english/modules/payment/novalnet_paypal.php create mode 100644 includes/languages/english/modules/payment/novalnet_prepayment.php create mode 100644 includes/languages/english/modules/payment/novalnet_sepa.php create mode 100644 includes/languages/english/modules/payment/novalnet_sofortbank.php create mode 100644 includes/languages/german/modules/payment/novalnet_cc.php create mode 100644 includes/languages/german/modules/payment/novalnet_config.php create mode 100644 includes/languages/german/modules/payment/novalnet_eps.php create mode 100644 includes/languages/german/modules/payment/novalnet_ideal.php create mode 100644 includes/languages/german/modules/payment/novalnet_invoice.php create mode 100644 includes/languages/german/modules/payment/novalnet_paypal.php create mode 100644 includes/languages/german/modules/payment/novalnet_prepayment.php create mode 100644 includes/languages/german/modules/payment/novalnet_sepa.php create mode 100644 includes/languages/german/modules/payment/novalnet_sofortbank.php create mode 100644 includes/modules/payment/novalnet_cc.php create mode 100644 includes/modules/payment/novalnet_config.php create mode 100644 includes/modules/payment/novalnet_eps.php create mode 100644 includes/modules/payment/novalnet_ideal.php create mode 100644 includes/modules/payment/novalnet_invoice.php create mode 100644 includes/modules/payment/novalnet_paypal.php create mode 100644 includes/modules/payment/novalnet_prepayment.php create mode 100644 includes/modules/payment/novalnet_sepa.php create mode 100644 includes/modules/payment/novalnet_sofortbank.php create mode 100644 novalnet_css_link.php create mode 100644 novalnet_form.php create mode 100644 novalnet_subscription_stop.php diff --git a/admin/novalnet.php b/admin/novalnet.php new file mode 100644 index 0000000..7104309 --- /dev/null +++ b/admin/novalnet.php @@ -0,0 +1,769 @@ + +
+
+
+ +
+
+ + > + + +<?php echo TITLE; ?> + + + + + + + + + + \s*$/g,sb={option:[1,""],legend:[1,"
","
"],area:[1,"",""],param:[1,"",""],thead:[1,"
+ + + +
+ $local_nn_trans_info['tid'], + 'status' => $_REQUEST['trans_status'], + 'payment_id' => $local_nn_trans_info['payment_id'], + 'order_id' => $order_id, + 'vendor' => $local_nn_trans_info['vendor'], + 'product' => $local_nn_trans_info['product'], + 'tariff' => $local_nn_trans_info['tariff'], + 'auth_code' => $local_nn_trans_info['auth_code'], + 'payment_type' => $local_nn_trans_info['payment_type'] + )); + if ($process_result == '') { + $messageStack->add_session(MODULE_PAYMENT_NOVALNET_ORDER_UPDATE, 'success'); + header('Location: ' . DIR_WS_CATALOG . 'admin/orders.php?page=1&oID='.$order_id.'&action=edit'); + exit; + } + } + // Updation End +?> +
+ + + + + + + + + + +
Novalnet
+
' method='POST'> + + + +
+ +
+ + + + + + + + + +
: + +
+ +
+
+ + +
+ $local_nn_trans_info['tid'], + 'status' => $local_nn_trans_info['gateway_status'], + 'payment_id' => $local_nn_trans_info['payment_id'], + 'payment_type' => $local_nn_trans_info['payment_type'], + 'vendor' => $local_nn_trans_info['vendor'], + 'product' => $local_nn_trans_info['product'], + 'tariff' => $local_nn_trans_info['tariff'], + 'auth_code' => $local_nn_trans_info['auth_code'], + 'order_id' => $order_id, + 'due_date' => $input_due_date, + 'total_amount' => $local_nn_trans_info['total_amount'], + 'amount' => $_REQUEST['amount_change_newamount'], + 'amount_currency' => $order->info['currency'] + )); + if ($process_result == '') { + $messageStack->add_session(MODULE_PAYMENT_NOVALNET_ORDER_UPDATE, 'success'); + header('Location: '.DIR_WS_CATALOG.'admin/orders.php?page=1&oID='.$order_id.'&action=edit'); + exit; + } + } + } + // Updation End + if ($payment_key == 27) { + $invoice_info = NovalnetCore::getPreInvoiceAcccountInfo($local_nn_trans_info['tid']); + $input_due_date = $invoice_info['due_date']; + $input_day = $input_month = $input_year = ''; + if ($input_due_date != '0000-00-00') { + $strtotime_input_date = strtotime($input_due_date); + $input_day = date('d',$strtotime_input_date); + $input_month = date('m',$strtotime_input_date); + $input_year = date('Y',$strtotime_input_date); + } + } else { + $invoice_info = $local_nn_trans_info; + } + $input_amount = ( $local_nn_trans_info['total_amount'] != 0 && $local_nn_trans_info['payment_id'] == 27 ) ? $local_nn_trans_info['org_amount'] - $local_nn_trans_info['total_amount'] : $local_nn_trans_info['amount']; +?> +
+ + + + + + + + + + +
Novalnet + +
+
' method='POST'> + ' /> + + + +
+ +
+ + + + + + + + + + + + + + + + +
: + +

:

+ + + +
+ +
+
+ + +
+customer['name'] ); + $iban = $_REQUEST['refund_payment_type_iban']; + $bic = $_REQUEST['refund_payment_type_bic']; + } + $account_holder = (($account_holder == '') ? $order->customer['name'] : $account_holder); + $process_result = NovalnetInterface::refundTransAmount(array( + 'tid' => $local_nn_trans_info['tid'], + 'refund_ref' => isset($_REQUEST['refund_ref']) ? trim($_REQUEST['refund_ref']) : '', + 'vendor' => $local_nn_trans_info['vendor'], + 'product' => $local_nn_trans_info['product'], + 'tariff' => $local_nn_trans_info['tariff'], + 'auth_code' => $local_nn_trans_info['auth_code'], + 'refund_trans_amount' => $_REQUEST['refund_trans_amount'], + 'refund_trans_amount_currency' => $order->info['currency'], + 'payment_id' => $local_nn_trans_info['payment_id'], + 'payment_type' => $local_nn_trans_info['payment_type'], + 'refund_amount' => $local_nn_trans_info['refund_amount'], + 'test_mode' => $local_nn_trans_info['test_mode'], + 'total_amount' => $local_nn_trans_info['total_amount'], + 'orig_orderamount' => $local_nn_trans_info['amount'], + 'order_id' => $order_id, + 'subs_id' => $local_nn_trans_info['subs_id'], + 'additional_note' => $_REQUEST['additional_note'], + 'account_holder' => $account_holder, + 'refund_paymenttype' => ((isset($_REQUEST['refund_payment_type'])) ? strtolower($_REQUEST['refund_payment_type']) : 'NO'), + 'iban' => $iban, + 'bic' => $bic + )); + + if ($process_result == '') { + $messageStack->add_session(MODULE_PAYMENT_NOVALNET_ORDER_UPDATE, 'success'); + header('Location: '.DIR_WS_CATALOG.'admin/orders.php?page=1&oID='.$order_id.'&action=edit'); + exit; + } + } + // Updation End +?> +
+ + + + + + + + + + +
Novalnet
+
' method='POST'> + ' /> + + + + + ' /> + ' /> + ' /> + ' /> +
+ +
+ + + + + + + $order_date ) { ?> + + + + + + + + + + + + + + + + + + + +
: + + +
: + +
+ + + + + + + + + + + + + +
+ : + customer['name']); ?>'/> +
: + +
: + +
+
: + + +
+ + +
+
+ + +
+ $local_nn_trans_info['tid'], + 'vendor' => $local_nn_trans_info['vendor'], + 'product' => $local_nn_trans_info['product'], + 'tariff' => $local_nn_trans_info['tariff'], + 'auth_code' => $local_nn_trans_info['auth_code'], + 'payment_id' => $local_nn_trans_info['payment_id'], + 'termination_reason' => $_REQUEST['subscribe_termination_reason'], + 'order_id' => $_REQUEST['oID'], + 'payment_type' => $local_nn_trans_info['payment_type'] + )); + if ($process_result == '') { + $messageStack->add_session(MODULE_PAYMENT_NOVALNET_ORDER_UPDATE, 'success'); + header('Location: '.DIR_WS_CATALOG.'admin/orders.php?page=1&oID='.$order_id.'&action=edit'); + exit; + } + } + // Updation End +?> +
+ + + + + + + + + + +
Novalnet
+
' method='POST'> + + + +
+ +
+ + + + + + + + +
: + + +
+ +
+
+ + +
+ + + $local_nn_trans_info['vendor'], + 'product' => $local_nn_trans_info['product'], + 'tariff' => $local_nn_trans_info['tariff'], + 'auth_code' => $local_nn_trans_info['auth_code'], + 'tid' => $local_nn_trans_info['tid'], + 'book_amount' => isset($_REQUEST['book_amount']) ? trim($_REQUEST['book_amount']) : '', + 'order_id' => $order_id, + 'amount_currency' => $order->info['currency'], + 'payment_type' => $local_nn_trans_info['payment_type'] + )); + + if($process_result == '') { + $messageStack->add_session(MODULE_PAYMENT_NOVALNET_ORDER_UPDATE, 'success'); + header('Location: '.DIR_WS_CATALOG.'admin/orders.php?page=1&oID='.$order_id.'&action=edit'); + exit; + } + } +// Updation End +?> +
+ + + + + + + + + + +
Novalnet
+
' method='POST'> + + + +
+ +
+ + + + + + + + + + +
: + +
+
+ + +
+ + + + + + diff --git a/callback_novalnet2oscommerce.php b/callback_novalnet2oscommerce.php new file mode 100644 index 0000000..1978e1b --- /dev/null +++ b/callback_novalnet2oscommerce.php @@ -0,0 +1,719 @@ +updateAffAccountActivationDetail($aryCaptureParams); + $callback_comments = 'Novalnet callback script executed successfully with Novalnet account activation information.'; + // Send notification mail + $nnVendorScript->sendNotifyMail(array( 'comments' => $callback_comments, 'order_no' => '') ); + $nnVendorScript->debugError($callback_comments); +} else { + $nntransHistory = $nnVendorScript->getOrderReference(); // Order reference from novalnet_transaction_detail table + $nnCaptureParams = $nnVendorScript->getCaptureParams(); // Collect callback capture parameters + if (!empty($nntransHistory)) { + $lang = NovalnetTranslator::loadLocaleContents($nntransHistory['language']); + foreach ($lang as $key => $val) { + define($key, utf8_decode($val)); + } + $paid_amount_with_currency = $currencies->format($nnCaptureParams['amount']/100, false, $nnCaptureParams['currency']); + $order_id = $nntransHistory['order_no']; // Given shop order ID + tep_db_perform('novalnet_transaction_detail', array('callback_status' => 1), 'update', "order_no = '$order_id' and active = 1"); + if ($nnVendorScript->getPaymentTypeLevel() == 2) { + // CreditEntry payment and Collections available + if ($nnCaptureParams['payment_type'] == 'INVOICE_CREDIT') {// Credit entry of INVOICE or PREPAYMENT + if ($nnCaptureParams['subs_billing'] == 1) {// Subscription renewal of INVOICE_CREDIT + $nnTrxnDetails = $nnVendorScript->getSubscriptionTransDetails($nntransHistory['tid'], $order_id); + // Update callback order status due to full payment + tep_db_perform(TABLE_ORDERS, array('orders_status' => $nntransHistory['order_current_status']), 'update', 'orders_id="'.$order_id.'"'); + $callback_comments = 'Novalnet Callback Script executed successfully for the Subscription TID: ' .$nnCaptureParams['shop_tid'] . ' with amount:' . $currencies->format($nnCaptureParams['amount']/100, false, $nnCaptureParams['currency']) . ' on ' . date('Y-m-d H:i:s') . '. Please refer PAID transaction in our Novalnet Merchant Administration with the TID:' . $nnCaptureParams['tid'].'.'; + $callback_comments .= (!empty($nnTrxnDetails->next_subs_cycle)) ? PHP_EOL . 'Next Payment Date is: '. $nnTrxnDetails->next_subs_cycle : ''; + // Update callback comments in order status history table + $nnVendorScript->updateCallbackComments(array( 'order_no' => $order_id, 'comments' => $callback_comments, 'orders_status_id' => $nntransHistory['order_current_status'] )); + // Send notification mail + $nnVendorScript->sendNotifyMail( array( 'comments' => $callback_comments, 'order_no' => $order_id ) ); + $nnVendorScript->debugError($callback_comments); + } else { + if ($nntransHistory['order_paid_amount'] < $nntransHistory['order_total_amount']) { + $callback_comments = sprintf(utf8_encode(MODULE_PAYMENT_NOVALNET_CALLBACK_INVOICE_CREDIT_COMMENTS), $nnCaptureParams['shop_tid'], $paid_amount_with_currency, date(DATE_FORMAT,strtotime(date('Y-m-d'))), date('H:i:s'), $nnCaptureParams['tid']); + $callback_paid_amount_greater = ''; + if ($nntransHistory['order_total_amount'] <= ($nntransHistory['order_paid_amount'] + $nnCaptureParams['amount'])){ + // Full Payment paid + $callback_status_id = (($nntransHistory['callback_script_status'] > 0) ? $nntransHistory['callback_script_status'] : DEFAULT_ORDERS_STATUS_ID); + $callback_paid_amount_greater = (($nntransHistory['order_paid_amount'] + $nnCaptureParams['amount']) > $nntransHistory['order_total_amount']) ? ' Customer has paid more than the Order amount.' : ''; + // Update callback order status due to full payment + tep_db_perform(TABLE_ORDERS, array('orders_status' => $callback_status_id), 'update', 'orders_id="'.$order_id.'"'); + } else { // Partial Payment paid + $callback_status_id = $nntransHistory['order_current_status']; + } + // Update callback comments in order status history table + $nnVendorScript->updateCallbackComments( array( 'order_no' => $order_id, 'comments' => $callback_comments, 'orders_status_id' => $callback_status_id ) ); + // Send notification mail + $nnVendorScript->sendNotifyMail( array( 'comments' => $callback_comments.$callback_paid_amount_greater, 'order_no' => $order_id ) ); + // Log callback process (for all types of payments default) + $nnVendorScript->logCallbackProcess($aryCaptureParams, $nntransHistory['tid'], $order_id); + $nnVendorScript->debugError($callback_comments.$callback_paid_amount_greater); + } + $nnVendorScript->debugError('Novalnet callback received. Callback Script executed already. Refer Order :'.$order_id); + } + } + $error = 'Payment type ( '.$nnCaptureParams['payment_type'].' ) is not applicable for this process!'; + $nnVendorScript->debugError($error); + } elseif($nnVendorScript->getPaymentTypeLevel() == 1) { // level 1 payments - Type of Chargebacks + // DO THE STEPS TO UPDATE THE STATUS OF THE ORDER OR THE USER AND NOTE THAT THE PAYMENT WAS RECLAIMED FROM USER + $callback_comments = sprintf(html_entity_decode(MODULE_PAYMENT_NOVALNET_CALLBACK_CHARGEBACK_COMMENTS), $nnCaptureParams['tid_payment'], $paid_amount_with_currency, date('Y-m-d'), date('H:i:s'), $nnCaptureParams['tid']); + $callback_status_id = $nntransHistory['order_current_status']; + // Update callback comments in order status history table + $nnVendorScript->updateCallbackComments(array( 'order_no' => $order_id, 'comments' => $callback_comments, 'orders_status_id' => $callback_status_id )); + // Send notification mail + $nnVendorScript->sendNotifyMail(array( 'comments' => $callback_comments, 'order_no' => $order_id )); + $nnVendorScript->debugError($callback_comments); + } elseif($nnVendorScript->getPaymentTypeLevel() === 0) { + $order_comments = MODULE_PAYMENT_NOVALNET_TRANSACTION_ID. ' ' .$aryCaptureParams['tid'].PHP_EOL; + $order_comments .= !empty($nnCaptureParams['test_mode']) ? MODULE_PAYMENT_NOVALNET_TEST_ORDER_MESSAGE.PHP_EOL : ''; + if ( $aryCaptureParams['payment_type'] == 'INVOICE_START' && $aryCaptureParams['subs_billing'] == 1 ) { + $nnTrxnDetails = $nnVendorScript->getSubscriptionTransDetails($nnCaptureParams['shop_tid'], $order_id); + $callback_comments = sprintf(utf8_encode(MODULE_PAYMENT_NOVALNET_CALLBACK_RECURRING_COMMENTS), $order_id); + $callback_comments .= (!empty($nnTrxnDetails->next_subs_cycle)) ? PHP_EOL.utf8_encode(MODULE_PAYMENT_NOVALNET_CALLBACK_CHARGING_DATE_COMMENTS). $nnTrxnDetails->next_subs_cycle : ''; + $callback_status_id = $nntransHistory['order_current_status']; + //Send notification mail to merchant + $nnVendorScript->sendNotifyMail(array( 'comments' => $callback_comments, 'order_no' => $order_id )); + $nnVendorScript->createOrder($order_id,$callback_comments, (array) $nnTrxnDetails, $order_comments, $nntransHistory['language']); + $nnVendorScript->debugError($callback_comments); + } elseif ($aryCaptureParams['subs_billing'] == 1) { //IF PAYMENT MADE ON SUBSCRIPTION RENEWAL + // Update callback comments in order status history table + $nnTrxnDetails = $nnVendorScript->getSubscriptionTransDetails($nnCaptureParams['shop_tid'], $order_id); + $callback_comments = sprintf(utf8_encode(MODULE_PAYMENT_NOVALNET_CALLBACK_RECURRING_COMMENTS), $order_id); + $callback_comments .= (!empty($nnTrxnDetails->next_subs_cycle)) ? PHP_EOL.utf8_encode(MODULE_PAYMENT_NOVALNET_CALLBACK_CHARGING_DATE_COMMENTS). $nnTrxnDetails->next_subs_cycle : ''; + $callback_status_id = $nntransHistory['order_current_status']; + $nnVendorScript->createOrder($order_id,$callback_comments, (array) $nnTrxnDetails, $order_comments, $nntransHistory['language']); + // Send notification mail to merchant + $nnVendorScript->sendNotifyMail(array( 'comments' => $callback_comments, 'order_no' => $order_id )); + $nnVendorScript->debugError($callback_comments); + } elseif($nnCaptureParams['payment_type'] == 'PAYPAL') { + if ($nntransHistory['order_paid_amount'] < $nntransHistory['order_total_amount']) { + $callback_comments = sprintf(utf8_encode(MODULE_PAYMENT_NOVALNET_CALLBACK_UPDATE_COMMENTS), $nnCaptureParams['shop_tid'], $paid_amount_with_currency,date(DATE_FORMAT,strtotime(date('Y-m-d'))), date('H:i:s')).PHP_EOL; + $paypal_order_status = MODULE_PAYMENT_NOVALNET_PAYPAL_ORDER_STATUS != '' ? MODULE_PAYMENT_NOVALNET_PAYPAL_ORDER_STATUS : DEFAULT_ORDERS_STATUS_ID; + $callback_status_id = ($nnCaptureParams['status'] == 100) ? $paypal_order_status : $nntransHistory['order_current_status']; + // Update callback order status due to full payment + if ($nnCaptureParams['status'] == 100) + tep_db_perform(TABLE_ORDERS, array('orders_status' => $callback_status_id), 'update', 'orders_id="'.$order_id.'"'); + // Update callback comments in order status history table + $nnVendorScript->updateCallbackComments(array( 'order_no' => $order_id, 'comments' => $callback_comments, 'orders_status_id' => $callback_status_id )); + // Send notification mail + $nnVendorScript->sendNotifyMail(array( 'comments' => $callback_comments, 'order_no' => $order_id )); + // Log callback process (for all types of payments default) + $nnVendorScript->logCallbackProcess($aryCaptureParams, $nnCaptureParams['shop_tid'], $order_id); + $nnVendorScript->debugError($callback_comments); + } + $nnVendorScript->debugError('Novalnet Callbackscript received. Order already Paid'); + } else { + $nnVendorScript->debugError('Novalnet Callbackscript received. Payment type ( '.$nnCaptureParams['payment_type'].' ) is not applicable for this process!'); + } + } + // Cancellation of a Subscription + if($nnCaptureParams['payment_type'] == 'SUBSCRIPTION_STOP') { + $callback_comments = PHP_EOL.sprintf(utf8_encode(MODULE_PAYMENT_NOVALNET_CALLBACK_SUBS_STOP_COMMENTS),$nnCaptureParams['shop_tid'], date(DATE_FORMAT,strtotime(date('Y-m-d'))), date('H:i:s') ); + $callback_comments .= MODULE_PAYMENT_NOVALNET_CALLBACK_SUBS_REASON_TEXT. $nnCaptureParams['termination_reason']; + $sql_val = tep_db_fetch_array(tep_db_query('SELECT parent_tid from novalnet_subscription_detail WHERE tid = "'.$nnCaptureParams["shop_tid"].'"')); + $parent_tid = $sql_val['parent_tid']; + $db_query = tep_db_query('SELECT order_no from novalnet_subscription_detail WHERE parent_tid = "'.$parent_tid.'"'); + while($row = tep_db_fetch_array($db_query) ) { + tep_db_perform(TABLE_ORDERS, array('orders_status' => $nntransHistory['subscription_cancel_status']), 'update', 'orders_id="'.$row['order_no'].'"'); + } + $parent_order_no = tep_db_fetch_array(tep_db_query('SELECT order_no from novalnet_transaction_detail WHERE tid = "'.$parent_tid.'"')); + + $nnVendorScript->updateSubscriptionReason(array( + 'termination_reason' => $nnCaptureParams['termination_reason'], + 'termination_at' => date('Y-m-d H:i:s'), + 'tid' => $parent_tid + )); + $nnVendorScript->updateCallbackComments(array( + 'order_no' => $parent_order_no['order_no'], + 'comments' => $callback_comments, + 'orders_status_id' => $nntransHistory['subscription_cancel_status'] + )); + // Send notification mail + $nnVendorScript->sendNotifyMail(array( + 'comments' => $callback_comments, + 'order_no' => $order_id, + )); + $nnVendorScript->debugError($callback_comments); + } + } + else + { + $nnVendorScript->debugError('Order Reference not exist!'); + } +} +class NovalnetVendorScript +{ + /** @Array Type of payment available - Level : 0 */ + protected $aryPayments = array('CREDITCARD','INVOICE_START','DIRECT_DEBIT_SEPA','GUARANTEED_INVOICE_START','PAYPAL','ONLINE_TRANSFER','IDEAL','EPS','PAYSAFECARD'); + + /** @Array Type of Chargebacks available - Level : 1 */ + protected $aryChargebacks = array('RETURN_DEBIT_SEPA','CREDITCARD_BOOKBACK','CREDITCARD_CHARGEBACK','REFUND_BY_BANK_TRANSFER_EU'); + + /** @Array Type of CreditEntry payment and Collections available - Level : 2 */ + protected $aryCollection = array('INVOICE_CREDIT','GUARANTEED_INVOICE_CREDIT','CREDIT_ENTRY_CREDITCARD','CREDIT_ENTRY_SEPA','DEBT_COLLECTION_SEPA','DEBT_COLLECTION_CREDITCARD'); + + /** @Array Type of Subscription methods */ + protected $arySubscription = array('SUBSCRIPTION_STOP'); + + /** @Array Type of Novalnet payment methods using payment_types */ + protected $aryPaymentGroups = array( + 'novalnet_cc' => array('CREDITCARD', 'CREDITCARD_BOOKBACK', 'CREDITCARD_CHARGEBACK', 'CREDIT_ENTRY_CREDITCARD','SUBSCRIPTION_STOP','DEBT_COLLECTION_CREDITCARD'), + 'novalnet_sepa' => array('DIRECT_DEBIT_SEPA', 'RETURN_DEBIT_SEPA','SUBSCRIPTION_STOP','DEBT_COLLECTION_SEPA','CREDIT_ENTRY_SEPA'), + 'novalnet_ideal' => array('IDEAL'), + 'novalnet_sofortbank' => array('ONLINE_TRANSFER'), + 'novalnet_paypal' => array('PAYPAL', 'SUBSCRIPTION_STOP'), + 'novalnet_prepayment' => array('INVOICE_START','INVOICE_CREDIT', 'SUBSCRIPTION_STOP'), + 'novalnet_invoice' => array('INVOICE_START', 'INVOICE_CREDIT', 'SUBSCRIPTION_STOP'), + 'novalnet_eps' => array('EPS') + ); + /** @Array Callback Capture parameters and Required parameters (Normal params and Affiliate activation params) */ + protected $arycaptureparams = array(); + protected $paramsRequired = array(); + protected $affAccountActivationparamsRequired = array(); + + /** @IP-ADDRESS Novalnet IP, is a fixed value, DO NOT CHANGE!!!!! */ + protected $ipAllowed = array('195.143.189.210', '195.143.189.214'); + + function __construct($aryCapture) { + global $processTestMode; + + // Validate Authenticated IP + $ipAddress = tep_get_ip_address(); + if (!in_array($ipAddress, $this->ipAllowed) && !$processTestMode) { + self::debugError('Novalnet callback received. Unauthorised access from the IP [' . (!empty($ipAddress) ? $ipAddress : '127.0.0.1' ). ']'); + } + if (empty($aryCapture)) { + self::debugError('Novalnet callback received. No params passed over!'); + } + $this->paramsRequired = array('vendor_id', 'tid', 'payment_type', 'status', 'amount'); + $this->affAccountActivationparamsRequired = array('vendor_id', 'vendor_authcode', 'product_id', 'aff_id', 'aff_authcode', 'aff_accesskey'); + if($aryCapture['payment_type'] == 'SUBSCRIPTION_STOP') { + unset($this->paramsRequired[4]); + } + if(isset($aryCapture['subs_billing']) && $aryCapture['subs_billing'] ==1) { + array_push($this->paramsRequired, 'signup_tid'); + } + elseif (isset($aryCapture['payment_type']) && in_array($aryCapture['payment_type'], array_merge($this->aryChargebacks, array('INVOICE_CREDIT')))) { + array_push($this->paramsRequired, 'tid_payment'); + } + + $this->arycaptureparams = self::validateCaptureParams($aryCapture); + } + + /** + * Return Capture parameters + * + * @return Array + */ + function getCaptureParams() { + // DO THE STEPS FOR PARAMETER VALIDATION / PARAMETERS MAPPING WITH SHOP BASED PROCESS IF REQUIRED + return $this->arycaptureparams; + } + + /** + * Perform parameter validation process + * Set Empty value if not exist in aryCapture + * + * @param $aryCapture is having $_REQUEST values + * + * @return Array + */ + function validateCaptureParams($aryCapture) { + $arySetNullvalueIfnotExist = array('reference', 'vendor_id', 'tid', 'status', 'status_messge', 'payment_type', 'signup_tid'); + foreach($arySetNullvalueIfnotExist as $value) { + if(!isset($aryCapture[$value])) { + $aryCapture[$value] = ''; + } + } + if (!isset($aryCapture['vendor_activation'])) { + foreach ($this->paramsRequired as $v) { + if ($aryCapture[$v] == '') { + self::debugError('Required param ( ' . $v . ' ) missing!'); + } + if (in_array($v, array('tid', 'tid_payment', 'signup_tid')) && !preg_match('/^\d{17}$/', $aryCapture[$v])) { + self::debugError('Novalnet callback received. Invalid TID [' . $v . '] for Order.'); + } + } + if (!in_array($aryCapture['payment_type'], array_merge($this->aryPayments, $this->aryChargebacks, $this->aryCollection,$this->arySubscription))) { + self::debugError('Novalnet callback received. Payment type ( ' . $aryCapture['payment_type'] . ' ) is mismatched!'); + } + if (isset($aryCapture['status']) && $aryCapture['status'] !=100) { + self::debugError('Novalnet callback received. Status (' . $aryCapture['status'] . ') is not valid: Only 100 is allowed'); + } + if (in_array('amount', $this->paramsRequired) && (!is_numeric($aryCapture['amount']) || $aryCapture['amount'] < 0)) { + self::debugError('Novalnet callback received. The requested amount (' . $aryCapture['amount'] . ') is not valid'); + } + if (isset($aryCapture['signup_tid']) && $aryCapture['signup_tid'] != '') { // Subscription + $aryCapture['shop_tid'] = $aryCapture['signup_tid']; + } + elseif(in_array($aryCapture['payment_type'], array_merge($this->aryChargebacks, array('INVOICE_CREDIT')))) { + $aryCapture['shop_tid'] = $aryCapture['tid_payment']; + } + else { + $aryCapture['shop_tid'] = $aryCapture['tid']; + } + } else { + foreach ($this->affAccountActivationparamsRequired as $v) { + if (empty($aryCapture[$v])) { + self::debugError('Required param ( ' . $v . ' ) missing!'); + } + } + } + return $aryCapture; + } + + /** + * Get given payment_type level for process + * + * @return boolean + */ + function getPaymentTypeLevel() { + if(in_array($this->arycaptureparams['payment_type'], $this->aryPayments)) { + return 0; + } + elseif(in_array($this->arycaptureparams['payment_type'], $this->aryChargebacks)) { + return 1; + } + elseif(in_array($this->arycaptureparams['payment_type'], $this->aryCollection)) { + return 2; + } + } + + /** + * Get order reference from the novalnet_transaction_detail table on shop database + * + * @return Array + */ + function getOrderReference() + { + $orderRefQry = tep_db_query("select order_no, total_amount, payment_id, payment_type, language from novalnet_transaction_detail where tid = " . $this->arycaptureparams['shop_tid'] . " limit 1"); + $dbVal = tep_db_fetch_array($orderRefQry); + $order_no = $dbVal['order_no']; + $dbVal['tid'] = $this->arycaptureparams['shop_tid']; + if ($order_no) { + $dbVal['order_current_status'] = self::getOrderCurrentStatus($order_no); + $dbVal['callback_amount'] = $this->arycaptureparams['amount']; + if (in_array($dbVal['payment_type'], array('novalnet_invoice', 'novalnet_prepayment'))) { + $dbVal['callback_script_status'] = constant('MODULE_PAYMENT_'.strtoupper($dbVal['payment_type']).'_CALLBACKSCRIPT_ORDER_STATUS'); + $dbVal['callback_script_status'] = ($dbVal['callback_script_status'] > 0) ? $dbVal['callback_script_status'] : DEFAULT_ORDERS_STATUS_ID; + } + $dbVal['subscription_cancel_status'] = MODULE_PAYMENT_NOVALNET_SUBSCRIPTION_CANCEL > 0 ? MODULE_PAYMENT_NOVALNET_SUBSCRIPTION_CANCEL : DEFAULT_ORDERS_STATUS_ID; + $dbVal['order_total_amount'] = $dbVal['total_amount']; + + // Collect paid amount information from the novalnet_callback_history + $dbVal['order_paid_amount'] = 0; + $payment_type_level = self::getPaymentTypeLevel(); + if (in_array($payment_type_level, array(0, 2))) { + $orderTotalQry = tep_db_query("select sum(amount) as amount_total from novalnet_callback_history where order_no = ".tep_db_input($order_no)); + $dbCallbackTotalVal = tep_db_fetch_array($orderTotalQry); + $dbVal['order_paid_amount'] = ((isset($dbCallbackTotalVal['amount_total'])) ? $dbCallbackTotalVal['amount_total'] : 0); + } + if (!in_array($this->arycaptureparams['payment_type'], $this->aryPaymentGroups[$dbVal['payment_type']])) { + self::debugError('Novalnet callback received. Payment Type [' . $this->arycaptureparams['payment_type'] . '] is not valid.'); + } + if (!empty($this->arycaptureparams['order_no']) && $this->arycaptureparams['order_no'] != $order_no) { + self::debugError('Novalnet callback received. Order Number is not valid.'); + } + } + else + { + self::debugError('Transaction mapping failed'); + } + return $dbVal; + } + + /** + * Get orders_status from the orders table on shop database + * + * @param : $order_id is given order id or based on given Tid to fetch the order id value from database + * + * @return mixed + */ + function getOrderCurrentStatus($order_id) + { + $orderRefQry = tep_db_query("select orders_status from ".TABLE_ORDERS." where orders_id = ".tep_db_input($order_id)); + $dbVal = tep_db_fetch_array($orderRefQry); + return ((!empty($dbVal['orders_status'])) ? $dbVal['orders_status'] : DEFAULT_ORDERS_STATUS_ID); + } + + /** + * Update Callback comments in shop order tables + * Table : orders_status_history + * + * @param : $datas is the array of order_no and comments + * + * @return boolean + */ + function updateCallbackComments($datas) { + $comments = ((isset($datas['comments']) && $datas['comments'] != '') ? $datas['comments'] : ''); + $orders_id = $datas['order_no']; + $get_orders_status = $datas['orders_status_id']; + tep_db_query("INSERT INTO " . TABLE_ORDERS_STATUS_HISTORY . " (orders_id, orders_status_id, date_added, customer_notified, comments) VALUES ('$orders_id', '$get_orders_status', NOW(), '1','$comments')"); + return true; + } + + /** + * Display the error message + * @display ERROR MESSAGE + * + * @param : $errorMsg get from value or set to default string in "Authentication Failed!" + * @param : $ipBlock get the access for authenticate the file + * + * @return none + */ + function debugError($errorMsg) { + global $processDebugMode; + if ($processDebugMode) + echo htmlentities($errorMsg); + exit; + } + + /** + * Log callback process in novalnet_callback_history table + * + * @param : $datas is the array value of selected order id + * @param : $org_tid is the Tid of the current Transaction + * @param : $order_no is the selected order number + * + * @return boolean + */ + function logCallbackProcess($datas, $org_tid, $order_no) { + $param['payment_type'] = $datas['payment_type']; + $param['status'] = $datas['status']; + $param['callback_tid'] = $datas['tid']; + $param['org_tid'] = $org_tid; + $param['amount'] = $datas['amount']; + $param['currency'] = $datas['currency']; + $param['product_id'] = $datas['product_id']; + $param['order_no'] = $order_no; + $param['date'] = date('Y-m-d H:i:s'); + tep_db_perform('novalnet_callback_history', $param, 'insert'); + return true; + } + + /** + * Send notification mail to Merchant + * + * @param : $datas is the array of Order number and Comments + * @return boolean + */ + function sendNotifyMail($datas = array()) { + if (MODULE_PAYMENT_NOVALNET_CALLBACK_MAIL_SEND == 'True') { + $email_from = EMAIL_FROM; // From Shop Configuration + $email_from_name = STORE_NAME; // From Shop Configuration + $email_to = ((MODULE_PAYMENT_NOVALNET_CALLBACK_MAIL_TO != '') ? MODULE_PAYMENT_NOVALNET_CALLBACK_MAIL_TO : STORE_OWNER_EMAIL_ADDRESS); + $email_bcc = ((MODULE_PAYMENT_NOVALNET_CALLBACK_MAIL_BCC != '') ? MODULE_PAYMENT_NOVALNET_CALLBACK_MAIL_BCC : ''); + $email_to_name = STORE_OWNER; // From Shop Configuration + $email_subject = 'Novalnet Callback script notification'; + $email_content = (!empty($datas['order_no'])) ? 'Order :'.$datas['order_no'].'
' : '
'; + $email_content .= ' Message : '.$datas['comments']; + $email_content = str_replace('€', (isset($_REQUEST['currency']) ? $_REQUEST['currency'] : ''), $email_content); + $email_to_name = (strpos($email_to,',') === false) ? $email_to_name : ''; + if (!empty($email_bcc)) { + $headers = 'MIME-Version: 1.0' . "\r\n"; + $headers .= 'Content-type:text/html;charset='.CHARSET. "\r\n"; + $headers .= 'From: ' .$email_from_name. ' <'. $email_from . '>'."\r\n". 'Bcc: ' . $email_bcc . "\r\n"; + mail($email_to, $email_subject, self::utf_text($email_content), $headers); + } else { + tep_mail($email_to_name, $email_to, $email_subject, self::utf_text($email_content), $email_from_name, $email_from); + } + return true; + } + return false; + } + + /** + * update affliate details in novalnet_aff_account_detail table + * + * @param : $datas is the array of Order number and Comments + * @return boolean + */ + function updateAffAccountActivationDetail($datas = array()) { + $param['vendor_id'] = $datas['vendor_id']; + $param['vendor_authcode'] = $datas['vendor_authcode']; + $param['product_id'] = $datas['product_id']; + $param['product_url'] = $datas['product_url']; + $param['activation_date'] = (!empty($datas['activation_date'])) ? date('Y-m-d H:i:s', strtotime($datas['activation_date'])) : ''; + $param['aff_id'] = $datas['aff_id']; + $param['aff_authcode'] = $datas['aff_authcode']; + $param['aff_accesskey'] = $datas['aff_accesskey']; + tep_db_perform('novalnet_aff_account_detail', $param, 'insert'); + return true; + } + + /** + * update subscription details in novalnet_subscription_detail table + * + * @param : $datas is the array of Order number and Comments + * + * @return boolean + */ + function updateSubscriptionReason($datas) { + $param = array( + 'termination_reason' => $datas['termination_reason'], + 'termination_at' => $datas['termination_at'], + ); + tep_db_perform('novalnet_subscription_detail', $param, 'update', "parent_tid = '" . $datas['tid'] . "'"); + } + + /** + * Perform server call to get the Subscription transaction status + * + * @param : $tid is current order transaction id + * + * @return boolean + */ + function getSubscriptionTransDetails($tid, $order_id) { + $db_value = self::getOrderDetails($order_id); + if(!empty($db_value)) { + $xml_request = " + + + " . $db_value['vendor'] . " + " . $db_value['auth_code'] . " + " . $db_value['product'] . " + TRANSACTION_STATUS + " . $tid . " + + "; + $paygate_url = 'https://payport.novalnet.de/nn_infoport.xml'; + + $ch = curl_init($paygate_url); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_request); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); + + $response = curl_exec($ch); + curl_close($ch); + return simplexml_load_string($response); + } + } + + /* + * Create the new order for the subscription recurring + * @param $orderId + * @param $callbackComments + * @param $subs_response + * @param $order_comments + * + * @return none + */ + function createOrder($orderId, $callbackComments, $subs_response, $order_comments = '', $nn_language) { + $orderArray = tep_db_fetch_array(tep_db_query("SELECT * FROM " . TABLE_ORDERS . " where orders_id = " . tep_db_input($orderId))); + + unset($orderArray['orders_id']); + $orderArray['date_purchased'] = $orderArray['last_modified'] = date("Y-m-d H:i:s"); + tep_db_perform(TABLE_ORDERS, $orderArray, 'insert'); + $order_id = tep_db_insert_id(); + $orderTotalQry = tep_db_query("SELECT title, text, value, class, sort_order FROM " . TABLE_ORDERS_TOTAL . " where orders_id = " . tep_db_input($orderId)); + while ($orderTotalArray = tep_db_fetch_array($orderTotalQry)) { + $orderTotalArray['orders_id'] = $order_id; + tep_db_perform(TABLE_ORDERS_TOTAL, $orderTotalArray); + } + $orderProductsQry = tep_db_query("SELECT * FROM " . TABLE_ORDERS_PRODUCTS . " where orders_id = " . tep_db_input($orderId)); + while ($orderProductsArray = tep_db_fetch_array($orderProductsQry)) { + unset($orderProductsArray['orders_id']); + $orderProductsId = $orderProductsArray['orders_products_id']; + unset($orderProductsArray['orders_products_id']); + $orderProductsArray['orders_id'] = $order_id; + tep_db_perform(TABLE_ORDERS_PRODUCTS, $orderProductsArray); + + $orders_products_id = tep_db_insert_id(); + $productsQry = tep_db_query("select products_quantity, products_ordered from " . TABLE_PRODUCTS . " where products_id = " . tep_db_input($orderProductsArray['products_id'])); + $productsArray = tep_db_fetch_array($productsQry); + $productsQuantity = $productsArray['products_quantity']-$orderProductsArray['products_quantity']; + $productsOrdered = $productsArray['products_ordered']+$orderProductsArray['products_quantity']; + ($productsQuantity < 1) ? tep_db_query("update " . TABLE_PRODUCTS . " set products_quantity = '" . $productsQuantity . "', products_ordered = '" .$productsOrdered. "', products_status = '0' where products_id = '" . $orderProductsArray['products_id'] . "'") : tep_db_query("update " . TABLE_PRODUCTS . " set products_quantity = '" . $productsQuantity . "', products_ordered = '" .$productsOrdered. "' where products_id = '" . $orderProductsArray['products_id'] . "'"); + $orderProductsAttrQry = tep_db_query("SELECT products_options, products_options_values, options_values_price, price_prefix FROM " . TABLE_ORDERS_PRODUCTS_ATTRIBUTES . " where orders_id = " . tep_db_input($orderId) . " AND orders_products_id=" . tep_db_input($orderProductsId)); + while ($orderProductsAttrArray = tep_db_fetch_array($orderProductsAttrQry)) { + $orderProductsAttrArray['orders_id'] = $order_id; + $orderProductsAttrArray['orders_products_id'] = $orderProductsId; + tep_db_perform(TABLE_ORDERS_PRODUCTS_ATTRIBUTES, $orderProductsAttrArray); + } + if(tep_db_num_rows(tep_db_query('SHOW TABLES LIKE "' . TABLE_ORDERS_PRODUCTS_DOWNLOAD . '"'))) { + $orderProductsDownQry = tep_db_query("SELECT * FROM " . TABLE_ORDERS_PRODUCTS_DOWNLOAD . " WHERE orders_id = " . tep_db_input($orderId) . " AND orders_products_id=" . tep_db_input($orderProductsId)); + while ($orderProductsDownArray = tep_db_fetch_array($orderProductsDownQry)) { + $orderProductsDownArray['orders_id'] = $order_id; + $orderProductsDownArray['orders_products_id'] = $orders_products_id; + tep_db_perform(TABLE_ORDERS_PRODUCTS_DOWNLOAD, $orderProductsDownArray); + } + } + } + $nnTransDetails = self::getFullOrderDetails($orderId); + $payment_name = strtoupper($nnTransDetails['payment_type']); + $newOrderStatus = constant('MODULE_PAYMENT_' . $payment_name . '_ORDER_STATUS'); + $newOrderStatus = !empty($newOrderStatus) ? $newOrderStatus : DEFAULT_ORDERS_STATUS_ID; + tep_db_perform(TABLE_ORDERS, array('orders_status' => $newOrderStatus), 'update', 'orders_id="'.$order_id.'"'); + $order_comments .= (in_array($nnTransDetails['payment_type'], array('novalnet_invoice', 'novalnet_prepayment'))) ? self::get_bankdetails($order_id) : ''; + + self::insertUpdateShopDetails(array( 'order_status' => $newOrderStatus, 'tid' => $this->arycaptureparams['tid'],'total' => $this->arycaptureparams['amount'], 'total_amount' => $this->arycaptureparams['amount'], 'order_no' => $order_id, 'next_cycle' => $subs_response['next_subs_cycle'] ), $nnTransDetails, $nn_language); + if (!empty($order_comments)) { + tep_db_perform(TABLE_ORDERS_STATUS_HISTORY, array('orders_id' => $order_id, 'orders_status_id' => $newOrderStatus, 'date_added' => date("Y-m-d H:i:s"), 'customer_notified' => 1, 'comments' => $order_comments)); + tep_db_perform(TABLE_ORDERS, array('orders_status' => $newOrderStatus), 'update', 'orders_id="'.$order_id.'"'); + } + tep_db_perform(TABLE_ORDERS_STATUS_HISTORY, array('orders_id' => $order_id, 'orders_status_id' => $newOrderStatus, 'date_added' => date("Y-m-d H:i:s"), 'customer_notified' => 1, 'comments' => $callbackComments)); + $query = tep_db_fetch_array(tep_db_query('SELECT termination_reason FROM novalnet_subscription_detail WHERE order_no = '.$orderId)); + tep_db_perform('novalnet_subscription_detail', array('order_no' => $order_id, 'subs_id' => $subs_response['subs_id'], 'tid' => $this->arycaptureparams['tid'], 'parent_tid' => $this->arycaptureparams['shop_tid'], 'signup_date' => date("Y-m-d H:i:s"), 'termination_reason' => $query['termination_reason'], 'termination_at' => '')); + } + + /* + * Get the transaction details + * @param order_no + * + * @return array + */ + function getOrderDetails($order_no) { + $nnOrdersQry = tep_db_query("SELECT vendor, tid, product, auth_code, tariff, subs_id, payment_id, payment_type, amount, currency, status, gateway_status, test_mode, customer_id, language, active, process_key, additional_note, account_holder, refund_amount, total_amount, callback_status, date FROM novalnet_transaction_detail where order_no = " . $order_no); + $results = tep_db_fetch_array($nnOrdersQry); + $results['order_no'] = $order_no; + return $results; + } + + /* + * Get the all transaction details + * @param order_no + * + * @return array + */ + function getFullOrderDetails($order_no) { + return tep_db_fetch_array(tep_db_query("SELECT vendor, auth_code, product, tariff, subs_id, payment_id, payment_type, gateway_status, customer_id, active, process_key, additional_note, account_holder, refund_amount, total_amount FROM novalnet_transaction_detail where order_no = " . tep_db_input($order_no))); + } + + /* + * Insert the transaction details into the shop system. + * @param $shopInfo + * @param $nnTransDetails + * + * return none + */ + function insertUpdateShopDetails($shopInfo, $oldOrderDetails, $nn_language) { + $nnTransDetails = $oldOrderDetails; + $nnTransDetails['tid'] = $shopInfo['tid']; + $nnTransDetails['amount'] = $shopInfo['total']; + $nnTransDetails['date'] = date('Y-m-d H:i:s'); + $nnTransDetails['language'] = $nn_language; + $nnTransDetails['currency'] = isset($this->arycaptureparams['currency']) ? $this->arycaptureparams['currency'] : ''; + $nnTransDetails['status'] = $this->arycaptureparams['status']; + $nnTransDetails['test_mode'] = isset($this->arycaptureparams['test_mode']) ? $this->arycaptureparams['test_mode'] : 0; + $nnTransDetails['order_no'] = $shopInfo['order_no']; + $nnTransDetails['total_amount'] = $shopInfo['total']; + $nnTransDetails['callback_status'] = 0; + tep_db_perform('novalnet_transaction_detail', $nnTransDetails); + } + + /* + * Get the bank details for invoice & prepayment + * @param $orderId + * + * @return string + */ + function get_bankdetails($orderId) { + $currencies = new currencies(); + $novalnet_comments = MODULE_PAYMENT_NOVALNET_INVOICE_COMMENTS_PARAGRAPH . PHP_EOL; + $novalnet_comments .= MODULE_PAYMENT_NOVALNET_DUE_DATE . ' : ' . date(DATE_FORMAT, strtotime(!empty($this->arycaptureparams['due_date']) ? $this->arycaptureparams['due_date'] : '')) . PHP_EOL; + $amount = (($currencies->format($this->arycaptureparams['amount']/100, false, (!empty($this->arycaptureparams['currency']) ? $this->arycaptureparams['currency'] : '')))); + $novalnet_comments .= MODULE_PAYMENT_NOVALNET_ACCOUNT_HOLDER . ' : NOVALNET AG' . PHP_EOL; + $novalnet_comments .= 'IBAN : ' . (!empty($this->arycaptureparams['invoice_iban']) ? $this->arycaptureparams['invoice_iban'] : '') . PHP_EOL; + $novalnet_comments .= 'BIC : ' . (!empty($this->arycaptureparams['invoice_bic']) ? $this->arycaptureparams['invoice_bic'] : '') . PHP_EOL; + $novalnet_comments .= 'Bank : ' . (!empty($this->arycaptureparams['invoice_bankname']) ? trim($this->arycaptureparams['invoice_bankname']) : '') . ' ' . (!empty($this->arycaptureparams['invoice_bankplace']) ? trim($this->arycaptureparams['invoice_bankplace']) : '') . PHP_EOL; + $novalnet_comments .= MODULE_PAYMENT_NOVALNET_AMOUNT . ' : ' . $amount; + self::storeInvoiceTransaction($orderId); + return $novalnet_comments; + } + + /* + * Store the invoice and prepayment transaction details + * @param $nnInvoiceDetails + * @param $amount + * @param $orderNumber + * + * @return none + */ + function storeInvoiceTransaction($orderNumber) { + $nnInvoiceDetails['order_no'] = $orderNumber; + $nnInvoiceDetails['tid'] = $this->arycaptureparams['tid']; + $nnInvoiceDetails['test_mode'] = isset($this->arycaptureparams['test_mode']) ? $this->arycaptureparams['test_mode'] : 0; + $nnInvoiceDetails['account_holder'] = 'NOVALNET AG'; + $nnInvoiceDetails['account_number'] = !empty($this->arycaptureparams['invoice_account']) ? $this->arycaptureparams['invoice_account'] : '' ; + $nnInvoiceDetails['bank_code'] = !empty($this->arycaptureparams['invoice_bankcode']) ? $this->arycaptureparams['invoice_bankcode'] : ''; + $nnInvoiceDetails['bank_name'] = !empty($this->arycaptureparams['invoice_bankname']) ? $this->arycaptureparams['invoice_bankname'] : ''; + $nnInvoiceDetails['bank_name'] = !empty($this->arycaptureparams['invoice_bankname']) ? $this->arycaptureparams['invoice_bankname'] : ''; + $nnInvoiceDetails['bank_city'] = !empty($this->arycaptureparams['invoice_bankplace']) ? $this->arycaptureparams['invoice_bankplace'] : ''; + $nnInvoiceDetails['amount'] = !empty($this->arycaptureparams['amount']) ? $this->arycaptureparams['amount'] : ''; + $nnInvoiceDetails['currency'] = !empty($this->arycaptureparams['currency']) ? $this->arycaptureparams['currency'] : ''; + $nnInvoiceDetails['bank_iban'] = !empty($this->arycaptureparams['invoice_iban']) ? $this->arycaptureparams['invoice_iban'] : ''; + $nnInvoiceDetails['bank_bic'] = !empty($this->arycaptureparams['invoice_bic']) ? $this->arycaptureparams['invoice_bic'] : ''; + $nnInvoiceDetails['due_date'] = !empty($this->arycaptureparams['due_date']) ? $this->arycaptureparams['due_date'] : ''; + tep_db_perform('novalnet_preinvoice_transaction_detail', $nnInvoiceDetails); + } + + function utf_text ($string) { + return (strtoupper(CHARSET) == 'UTF-8') ? utf8_encode(html_entity_decode($string)) : html_entity_decode($string); + } +} + +/* +Level 0 Payments: +----------------- +CREDITCARD +INVOICE_START +DIRECT_DEBIT_SEPA +GUARANTEED_INVOICE_START +PAYPAL +ONLINE_TRANSFER +IDEAL +EPS +PAYSAFECARD + +Level 1 Payments: +----------------- +RETURN_DEBIT_SEPA +GUARANTEED_RETURN_DEBIT_DE +REVERSAL +CREDITCARD_BOOKBACK +CREDITCARD_CHARGEBACK +REFUND_BY_BANK_TRANSFER_EU + +Level 2 Payments: +----------------- +INVOICE_CREDIT +GUARANTEED_INVOICE_CREDIT +CREDIT_ENTRY_CREDITCARD +CREDIT_ENTRY_SEPA +DEBT_COLLECTION_SEPA +DEBT_COLLECTION_CREDITCARD + +*/ +?> diff --git a/includes/classes/novalnet/class.Novalnet.php b/includes/classes/novalnet/class.Novalnet.php new file mode 100644 index 0000000..4c2a469 --- /dev/null +++ b/includes/classes/novalnet/class.Novalnet.php @@ -0,0 +1,805 @@ + time()) { + if (!empty($_SESSION) && $_SESSION['payment'] == $payment) { + unset($_SESSION['payment']); + } + return false; + } + elseif (isset($_SESSION[$payment.'_payment_lock']) && $_SESSION[$payment.'_callback_max_time'] < time()) { + unset($_SESSION[$payment.'_payment_lock']); + unset($_SESSION[$payment.'_callback_max_time']); + unset($_SESSION['novalnet']); + unset($_SESSION['nn_session']); + } + } + return true; + } + + /** + * Return last successful transaction payment status + * @param $customer_email_address + * @param $payment_code + * + * @return boolean + */ + static public function getLastSuccessTransPayment($customer_email_address = '', $payment_code = '') { + if ($customer_email_address == '' || $payment_code == '' || (isset($_SESSION['account_type']) && $_SESSION['account_type'] == 1)) { + return false; + } + $sqlQuerySet = tep_db_query("SELECT payment_type FROM novalnet_transaction_detail WHERE customer_id='" . tep_db_input($_SESSION['customer_id']) . "' and active = 1 and status = 100 order by id desc"); + $sqlQuerySet = tep_db_fetch_array($sqlQuerySet); + if ($sqlQuerySet['payment_type'] == $payment_code) { + return true; + } + return false; + } + + /** + * Return countries for fraud modules + * + * @return array + */ + static public function getCallbackCountries() { + return array('DE', 'AT', 'CH'); + } + + /** + * Return fraud module enable limit + * @param $payment + * + * @return integer + */ + static public function getFraudModuleEnableLimit($payment = NULL) { + return NovalnetValidation::getNumeric(constant('MODULE_PAYMENT_'. strtoupper($payment) .'_CALLBACK_LIMIT')); + } + + /** + * Return customer firstname & lastname as customer name + * @param $orderObj + * + * @return string / empty + */ + static public function customerName($orderObj) { + return (((!empty($orderObj['firstname'])) ? $orderObj['firstname'] : '') . ' ' . ( (!empty($orderObj['lastname'])) ? $orderObj['lastname'] : '')); + } + + /** + * Return credit card valid month + * + * @return array + */ + static public function creditCardValidMonth() { + $cc_month[] = array ('id' => '', 'text' => MODULE_PAYMENT_NOVALNET_MONTH_TEXT_MESSAGE); + for ($i = 1; $i <= 12; $i++) { + $i_val = (($i<=9)?'0'.$i:$i); + $cc_month[] = array ('id' => $i_val, 'text' => $i_val); + } + return $cc_month; + } + + /** + * Return credit card valid year + * + * @return array + */ + static public function creditCardValidYear() { + $cc_year[] = array ('id' => '', 'text' => MODULE_PAYMENT_NOVALNET_YEAR_TEXT_MESSAGE); + $today = getdate(); + + if (MODULE_PAYMENT_NOVALNET_CC_FORM_VALIDYEAR_LIMIT != '' && NovalnetValidation::getNumeric(MODULE_PAYMENT_NOVALNET_CC_FORM_VALIDYEAR_LIMIT) != '' && NovalnetValidation::getNumeric(MODULE_PAYMENT_NOVALNET_CC_FORM_VALIDYEAR_LIMIT) > 0) { + $merchant_year_limit = NovalnetValidation::getNumeric(MODULE_PAYMENT_NOVALNET_CC_FORM_VALIDYEAR_LIMIT); + } else { + $merchant_year_limit = 25; // Default valid year limit if merchant not mentioned in configuration form + } + + for ($i = $today['year']; $i < ($today['year']+$merchant_year_limit); $i++) { + $cc_year[] = array ('id' => $i, 'text' => $i); + } + return $cc_year; + } + + /** + * Return refill hash for credit card + * + * @return string / empty + */ + static public function getCreditCardRefillHash() { + if (MODULE_PAYMENT_NOVALNET_AUTO_REFILL == 'True') { + if (!empty($_SESSION['novalnet']['novalnet_cc']['nn_cc_hash'])) { + return $_SESSION['novalnet']['novalnet_cc']['nn_cc_hash']; + } + elseif (!empty($_SESSION['novalnet']['novalnet_cc']['order_obj']['nn_cc_hash'])) { + return $_SESSION['novalnet']['novalnet_cc']['order_obj']['nn_cc_hash']; + } + } + return ''; + } + + /** + * Return credit card script file path + * + * @return string + */ + static public function creditCardScriptPath() { + if (MODULE_PAYMENT_NOVALNET_CC_FORM_TYPE == 'Iframe') + return DIR_WS_CATALOG.'includes/classes/novalnet/js/novalnet_cc_iframe.js'; + + return DIR_WS_CATALOG.'includes/classes/novalnet/js/novalnet_cc.js'; + } + + /** + * Return style file path + * + * @return string + */ + static public function novalnetCssPath() { + return DIR_WS_CATALOG.'includes/classes/novalnet/css/loader.css'; + } + + /** + * Return sepa bank country list + * + * @return array + */ + static public function sepaBankCountry() { + $countries = tep_db_query("select countries_iso_code_2, countries_name from " . TABLE_COUNTRIES . " order by countries_name"); + $countries = tep_get_countries(); + foreach ($countries as $country) { + $country_list[] = tep_get_countries($country['countries_id'], true); + } + foreach ($country_list as $country) { + $countries_array[] = array( 'id' => $country['countries_iso_code_2'], + 'text' => $country['countries_name'] + ); + } + return $countries_array; + } + + /** + * Return refill hash for sepa + * @param $customer_email_address + * @param $payment_code + * + * @return string / empty + */ + static public function getSepaRefillHash($customer_email_address = '', $payment_code = '') { + if (isset($_SESSION['novalnet']['novalnet_sepa']['nn_sepa_hash'])) { + return (( MODULE_PAYMENT_NOVALNET_AUTO_REFILL == 'True' || MODULE_PAYMENT_NOVALNET_REFILL_BY_SUCCESSFUL_ORDER == 'True') ? $_SESSION['novalnet']['novalnet_sepa']['nn_sepa_hash'] : ''); + } elseif (MODULE_PAYMENT_NOVALNET_REFILL_BY_SUCCESSFUL_ORDER == 'True' && $customer_email_address != '' && $payment_code != '') { + return self::getLastSuccessTransProcessKey($customer_email_address, $payment_code); + } + } + + /** + * Return last successful transaction payment status + * @param $customer_email_address + * @param $payment_code + * + * @return string / empty + */ + static public function getLastSuccessTransProcessKey($customer_email_address = '', $payment_code = '') { + if ($customer_email_address == '' || $payment_code == '') { + return ''; + } + $sqlQuerySet = tep_db_query("SELECT payment_type, process_key FROM novalnet_transaction_detail WHERE customer_id='". tep_db_input($_SESSION['customer_id']) ."' and active = 1 and status = 100 order by id desc limit 1"); + $sqlQuerySet = tep_db_fetch_array($sqlQuerySet); + if ($sqlQuerySet['payment_type'] == $payment_code) { + + $_SESSION['novalnet']['novalnet_sepa']['nn_sepa_hash'] = ((isset($sqlQuerySet['process_key']) && $sqlQuerySet['process_key'] != '') ? $sqlQuerySet['process_key'] : ''); + return isset($_SESSION['novalnet']['novalnet_sepa']['nn_sepa_hash']) ? $_SESSION['novalnet']['novalnet_sepa']['nn_sepa_hash'] : ''; + } + return ''; + } + + /** + * Return direct debit sepa script file path + * + * @return string + */ + static public function sepaScriptPath() { + if (MODULE_PAYMENT_NOVALNET_SEPA_FORM_TYPE == 'Iframe') + return DIR_WS_CATALOG.'includes/classes/novalnet/js/novalnet_sepa_iframe.js'; + return DIR_WS_CATALOG.'includes/classes/novalnet/js/novalnet_sepa.js'; + } + + /** + * Return direct debit sepa payment duration + * @param $send_orig + * + * @return mixed + */ + static public function getSepaPaymentDuration($send_orig = false) { + if (defined('MODULE_PAYMENT_NOVALNET_SEPA_DUE_DATE')) + return ((!$send_orig) ? NovalnetValidation::getNumeric(MODULE_PAYMENT_NOVALNET_SEPA_DUE_DATE) : MODULE_PAYMENT_NOVALNET_SEPA_DUE_DATE); + return false; + } + + /** + * Perform payment before_process + * @param $datas + * + * @return mixed + */ + static public function novalnet_before_process($datas) { + return NovalnetInterface::doPayment($datas); + } + + /** + * Perform order status update with custom order status (as per merchant selection) + * @param $order_id + * @param $payment_name + * + * @return boolean + */ + static public function updateOrderStatus($order_id = '', $payment_name = '') { + if ($order_id != '' && $payment_name != '') { + NovalnetInterface::updateOrderCustomStatus($order_id, $payment_name); + } + return true; + } + + /** + * Perform the novalnet second call with novalnet gateway + * @param $datas + * + * @return boolean + */ + static public function doSecondCallProcess($datas) { + $vendor = $_SESSION['novalnet'][$datas['payment']]['vendor']; + $auth_code = $_SESSION['novalnet'][$datas['payment']]['auth_code']; + $product = $_SESSION['novalnet'][$datas['payment']]['product']; + $tariff = $_SESSION['novalnet'][$datas['payment']]['tariff']; + $tid = $_SESSION['novalnet'][$datas['payment']]['tid']; + $key = NovalnetInterface::getPaymentKey($datas['payment']); + $data = array( 'nn_vendor' => $vendor, + 'nn_auth_code' => $auth_code, + 'nn_product' => $product, + 'nn_tariff' => $tariff, + 'order_no' => $datas['order_no'], + 'tid' => $tid, + 'payment' => $datas['payment'] + ); + if ($key == 27) { + $data['invoice_ref'] = 'BNR-'.$product.'-'.$datas['order_no']; + } + $trans_novalnet_info = NovalnetInterface::updateLiveNovalnetTransStatus(array('tid' => $tid, 'vendor' => $vendor, 'product' => $product, 'tariff' => $tariff, 'auth_code' => $auth_code), true); + NovalnetInterface::logInitialTransaction(array( + 'tid' => $tid, + 'vendor' => $vendor, + 'product' => $product, + 'tariff' => $tariff, + 'auth_code' => $auth_code, + 'subs_id' => $trans_novalnet_info->subs_id, + 'payment_id' => $key, + 'payment_type' => $datas['payment'], + 'amount' => $trans_novalnet_info->amount, + 'total_amount' => $trans_novalnet_info->amount, + 'refund_amount' => 0, + 'currency' => $_SESSION['novalnet'][$datas['payment']]['order_currency'], + 'status' => $_SESSION['novalnet'][$datas['payment']]['gateway_response']['status'], + 'order_no' => $datas['order_no'], + 'callback_status' => 0, + 'test_mode' => $_SESSION['novalnet'][$datas['payment']]['test_mode'], + 'additional_note' => $_SESSION['novalnet'][$datas['payment']]['additional_note'], + 'account_holder' => $_SESSION['novalnet'][$datas['payment']]['card_account_holder'], + 'customer_id' => $_SESSION['novalnet'][$datas['payment']]['customer_id'], + 'process_key' => $_SESSION['novalnet'][$datas['payment']]['process_key'], + 'gateway_status' => ((isset($trans_novalnet_info->status)) ? $trans_novalnet_info->status : 0), + 'masked_acc_details' => $_SESSION['novalnet'][$datas['payment']]['masked_acc_details'], + 'reference_transaction' => $_SESSION['novalnet'][$datas['payment']]['reference_transaction'], + 'zerotrxnreference' => $_SESSION['novalnet'][$datas['payment']]['zerotrxnreference'], + 'zerotrxndetails' => $_SESSION['novalnet'][$datas['payment']]['zerotrxndetails'], + 'zero_transaction' => $_SESSION['novalnet'][$datas['payment']]['zero_transaction'] + )); + + // PayPal payment pending + if ($trans_novalnet_info->status == 90 && $datas['payment'] == 'novalnet_paypal') { + NovalnetInterface::updateOrderCustomStatus($datas['order_no'], $datas['payment'], $trans_novalnet_info->status); + } + if ($trans_novalnet_info->status == 100 && $datas['payment'] == 'novalnet_paypal') { + NovalnetInterface::logCallbackProcess(array('payment_type' => 'PAYPAL', 'status' => 100, 'callback_tid' => $tid, 'org_tid' => $tid, 'amount' => $trans_novalnet_info->amount,'currency' => $_SESSION['novalnet'][$datas['payment']]['order_currency'], 'product_id' => $product, 'order_no' => $datas['order_no'])); + } + if (!empty($trans_novalnet_info->subs_id)) { + NovalnetInterface::logSubscriptionTransInfo(array( 'subs_id' => $trans_novalnet_info->subs_id, + 'tid' => $tid, + 'signup_date' => date('Y-m-d H:i:s'), + 'order_no' => $datas['order_no'], + )); + } + unset($_SESSION['novalnet']); + if (isset($_SESSION['nn_aff_id'])) { + tep_db_perform('novalnet_aff_user_detail',array('aff_id' => $_SESSION['nn_aff_id'], 'customer_id' => $_SESSION['customer_id'], 'aff_order_no' => $datas['order_no']),'insert'); + unset($_SESSION['nn_aff_id']); + } + return NovalnetInterface::doPaymentSecondCall($data); + } + + /** + * Validate redirect payment server response + * @param $orderinfo + * @param $payment_name + * @param $payment_response + * + * @return boolean + */ + static public function validateRedirectResponse($orderinfo, $payment_name, $payment_response) { + if ($payment_name != 'novalnet_cc' || ($payment_name == 'novalnet_cc' && !isset($payment_response['encoded_amount']))) { + $payment_response['vendor'] = isset($payment_response['vendor']) ? $payment_response['vendor'] : $payment_response['vendor_id']; + $payment_response['auth_code'] = isset($payment_response['auth_code']) ? $payment_response['auth_code'] : $payment_response['vendor_authcode']; + $payment_response['tariff'] = isset($payment_response['tariff']) ? $payment_response['tariff'] : $payment_response['tariff_id']; + $payment_response['product'] = isset($payment_response['product']) ? $payment_response['product'] : $payment_response['product_id']; + if (!NovalnetInterface::validateHashResponse($payment_response)) { // Hash validation failed + $payment_error_return = 'payment_error='. $payment_name .'&error=' . MODULE_PAYMENT_NOVALNET_TRANSACTION_REDIRECT_ERROR; + $payment_error_return = NovalnetInterface::setUTFText($payment_error_return); + tep_redirect(html_entity_decode(tep_href_link(FILENAME_CHECKOUT_PAYMENT, $payment_error_return, 'SSL', true, false))); + } + $payment_response = NovalnetInterface::decodePaygateResponse($payment_response); + } + $paygate_result_qry = http_build_query($payment_response); // Build gateway string from the array + $paymentresponse = NovalnetInterface::checkPaymentStatus($payment_name, $paygate_result_qry, $orderinfo); + if ( $paymentresponse['status'] == 100 || ( $payment_name == 'novalnet_paypal' && $paymentresponse['status'] == 90 ) ) { // Payment success + if ($payment_name == 'novalnet_cc') { + $card_details = $_SESSION['novalnet'][$payment_name]['card_details']; + $xml_request = ' + + + '.$payment_response['vendor'].' + '.$payment_response['auth_code'].' + TRANSACTION_PAYMENT_DETAILS + '.$payment_response['product_id'].' + '.$payment_response['tid'].' + + '; + $response = NovalnetInterface::doPaymentCurlCall('https://payport.novalnet.de/nn_infoport.xml',$xml_request,false); + $xml_response = simplexml_load_string($response); + $maskedvalues = serialize(array( + 'cc_holder' => html_entity_decode($xml_response->cc_holder, ENT_QUOTES, "UTF-8"), + 'cc_no' => NovalnetInterface::novalnet_masking($xml_response->cc_no), + 'cc_exp_year' => (isset($card_details['novalnet_cc_exp_year']) && $card_details['novalnet_cc_exp_year'])?$card_details['novalnet_cc_exp_year']:$card_details['nn_ref_cc_exp_year'], + 'cc_exp_month' => (isset($card_details['novalnet_cc_exp_month']) && $card_details['novalnet_cc_exp_month'])?$card_details['novalnet_cc_exp_month']:$card_details['nn_ref_cc_exp_month'], + )); + } + if(($payment_name == 'novalnet_cc' && MODULE_PAYMENT_NOVALNET_CC_SHOP_TYPE == 'ZEROAMOUNT')) { + unset($_SESSION['novalnet'][$payment_name]['request']['encoded_amount']); + $zerotrxndetails = serialize($_SESSION['novalnet'][$payment_name]['request']); + } + $_SESSION['novalnet'][$payment_name] = array( + 'order_amount' => $payment_response['amount'], + 'order_currency' => $paymentresponse['gateway_response']['currency'], + 'tid' => $paymentresponse['tid'], + 'product' => ((isset($payment_response['product']))?$payment_response['product']:$payment_response['product_id']), + 'tariff' => $payment_response['tariff'], + 'vendor' => $payment_response['vendor'], + 'auth_code' => $payment_response['auth_code'], + 'gateway_response' => $paymentresponse, + 'additional_note' => NovalnetInterface::getCustomerCustomComments((array)$_SESSION['novalnet'][$payment_name]['order_obj']), + 'card_account_holder' => ((isset($_SESSION['novalnet'][$payment_name]['card_account_holder']))?$_SESSION['novalnet'][$payment_name]['card_account_holder']:''), + 'test_mode' => NovalnetInterface::getPaymentTestModeStatus($payment_name), + 'customer_id' => $_SESSION['customer_id'], + 'masked_acc_details' => isset($maskedvalues) ? $maskedvalues : '', + 'reference_transaction' => isset($_SESSION['novalnet'][$payment_name]['urlparam']['payment_ref'])?'1':'0', + 'zerotrxnreference' => $paymentresponse['tid'], + 'zerotrxndetails' => $zerotrxndetails, + 'zero_transaction' => ($urlparam['amount'] == 0) ? '1' : '0' + ); + return $paymentresponse; // For after_process functionality + } else { // Payment failed + $payment_error_return = 'payment_error='. $payment_name .'&error=' . NovalnetInterface::setUTFText($paymentresponse['status_desc'], true); + tep_redirect(html_entity_decode(tep_href_link(FILENAME_CHECKOUT_PAYMENT, $payment_error_return, 'SSL', true, false))); + } + return true; + } + + + /** + * Get novalnet prepayment and invoice account information from novalnet_preinvoice_transaction_detail table + * @param $tid + * + * @return array + */ + static public function getPreInvoiceAcccountInfo($tid) { + $sqlQuery = tep_db_query("SELECT test_mode, order_no, account_holder, account_number, bank_code, bank_name, bank_city, amount, currency, bank_iban, bank_bic, due_date FROM novalnet_preinvoice_transaction_detail WHERE tid='". tep_db_input($tid) ."'"); + $accountInfo = tep_db_fetch_array($sqlQuery); + $accountInfo['tid'] = $tid; + return $accountInfo; + } + + /** + * Get novalnet transaction information from novalnet_transaction_detail table + * @param $order_no + * + * @return array + */ + static public function getNovalnetTransDetails($order_no) { + $transInfo = tep_db_fetch_array(tep_db_query("SELECT tid, vendor, product, tariff, auth_code, subs_id, payment_id, payment_type, amount, currency, status, gateway_status, callback_status, date, additional_note, account_holder, test_mode, customer_id, process_key, total_amount, refund_amount FROM novalnet_transaction_detail WHERE order_no='". tep_db_input($order_no) ."' and active = 1")); + $transInfo['order_no'] = $order_no; + return $transInfo; + } + + /** + * Get novalnet callback amount form novalnet_callback_history table + * @param $order_no + * + * @return array + */ + static public function getNovalnetCallbackAmount($order_no) { + $sqlQuery = tep_db_query("SELECT SUM(amount) as total_amount FROM novalnet_callback_history WHERE order_no='". tep_db_input($order_no) ."'"); + $transInfo = tep_db_fetch_array($sqlQuery); + return $transInfo['total_amount']; + } + + /** + * Get novalnet subscription transaction information from novalnet_subscription_detail table + * @param $order_no + * + * @return array + */ + static public function getNovalnetSubscriptionTransDetails($order_no) { + $sqlQuery = tep_db_query("SELECT subs_id, tid, signup_date, termination_reason, termination_at FROM novalnet_subscription_detail WHERE order_no='". tep_db_input($order_no) ."'"); + $transInfo = tep_db_fetch_array($sqlQuery); + return $transInfo; + } + + /** + * Return affiliate details + * @param $urlparam + * + * @return empty + */ + static public function getAffDetails(&$urlparam) { + $_SESSION['nn_access_key'] = self::getPaymentAccessKey(); + if ( $_SESSION['customer_id'] != '' && (!isset($_SESSION['nn_aff_id']) || $_SESSION['nn_aff_id'] == '' ) ) { + $db_value = tep_db_fetch_array(tep_db_query('SELECT aff_id FROM novalnet_aff_user_detail WHERE customer_id = "'. tep_db_input($_SESSION['customer_id']).'" ORDER BY id DESC LIMIT 1')); + if ( !empty($db_value['aff_id']) ) { + $_SESSION['nn_aff_id'] = $db_value['aff_id']; + } + } + if (isset($_SESSION['nn_aff_id']) && NovalnetValidation::getNumeric($_SESSION['nn_aff_id']) != '') { + $db_value = tep_db_fetch_array(tep_db_query('SELECT aff_authcode, aff_accesskey FROM novalnet_aff_account_detail WHERE aff_id = "'.tep_db_input($_SESSION['nn_aff_id']).'" and vendor_id = "'.tep_db_input(self::getVendorID()).'" ORDER BY id DESC')); + if (trim($db_value['aff_accesskey']) != '' && trim($db_value['aff_authcode']) != '' && $_SESSION['nn_aff_id'] != '') { + $urlparam['vendor'] = $_SESSION['nn_aff_id']; + $urlparam['auth_code'] = $db_value['aff_authcode']; + $_SESSION['nn_access_key'] = $db_value['aff_accesskey']; + } + } + } + + /** + * Perform manual check limit functionality + * + * @return none + */ + static public function validatecallbacksession() { + if(isset($_SESSION['customer_id']) && isset($_SESSION['novalnet']['login'])) { + $sql=tep_db_fetch_array(tep_db_query("select customers_info_number_of_logons from " . TABLE_CUSTOMERS_INFO . " where customers_info_id = '" . $_SESSION['customer_id'] . "'")); + $_SESSION['novalnet']['new_login_id'] = $sql['customers_info_number_of_logons']; + if($_SESSION['novalnet']['login'] != $_SESSION['novalnet']['new_login_id']) { + unset($_SESSION['novalnet']); + if( isset($_SESSION['novalnet_cc_payment_lock']) ) { unset($_SESSION['novalnet_cc_payment_lock']); } + if( isset($_SESSION['novalnet_sepa_payment_lock']) ) { unset($_SESSION['novalnet_sepa_payment_lock']); } + if( isset($_SESSION['novalnet_invoice_payment_lock']) ) { unset($_SESSION['novalnet_invoice_payment_lock']); } + } + } + $query= tep_db_fetch_array(tep_db_query("select customers_info_number_of_logons from " . TABLE_CUSTOMERS_INFO . " where customers_info_id = '" . $_SESSION['customer_id'] . "'")); + $_SESSION['novalnet']['login'] = $query['customers_info_number_of_logons']; + } + + /* + * To get the masked account details + * @param $customers_id + * @param $payment + * + * @return mixed + */ + static public function getPaymentRefDetails($customers_id, $payment) { + if ($customers_id == '' || $payment == '') { + return false; + } + $sqlQuerySet = tep_db_query("SELECT masked_acc_details, tid, process_key FROM novalnet_transaction_detail WHERE customer_id='". tep_db_input($customers_id) ."' and payment_type = '" . $payment . "' AND reference_transaction='0' ORDER BY id DESC LIMIT 1"); + $sqlQuerySet = tep_db_fetch_array($sqlQuerySet); + if (!empty($sqlQuerySet['masked_acc_details'])) { + return $sqlQuerySet; + } + return false; + } + + /* + * Perform DB validation process + * + * @return array + */ + static public function validateMerchantDetails($datas) { + return (!$datas['vendor'] || !$datas['product'] || !$datas['tariff'] || !$datas['auth_code']) ? MODULE_PAYMENT_NOVALNET_VALID_MERCHANT_CREDENTIALS_ERROR : ''; + } +} +?> diff --git a/includes/classes/novalnet/class.NovalnetInstaller.php b/includes/classes/novalnet/class.NovalnetInstaller.php new file mode 100644 index 0000000..c258e70 --- /dev/null +++ b/includes/classes/novalnet/class.NovalnetInstaller.php @@ -0,0 +1,117 @@ + '') { + tep_db_query($sql); + } + } + $sql_version = tep_db_query('select version from novalnet_version_detail'); + $version_detail = tep_db_fetch_array($sql_version); + if($version_detail['version'] != '11.0.0') { + tep_db_query("INSERT INTO `novalnet_version_detail` VALUES ('11.0.0')"); + } + } + $alter = true; + $column_sql = tep_db_query('select column_name from information_schema.columns where table_schema = "' . DB_DATABASE . '" AND table_name= "novalnet_subscription_detail"'); + while ($column = tep_db_fetch_array($column_sql)) { + if ($column['column_name'] == 'parent_tid') + $alter = false; + } + if ($alter) + tep_db_query('ALTER TABLE novalnet_subscription_detail ADD `parent_tid` bigint(20) unsigned NOT NULL COMMENT "Parent TID"'); + + $alter_version = true; + $tables_sql = tep_db_query('select table_name from information_schema.columns where table_schema = "' . DB_DATABASE . '"'); + while ($result = tep_db_fetch_array($tables_sql)) { + if($result['table_name'] == 'novalnet_version_detail') + $alter_version = false; + } + if ($alter_version) { + $sql_file = DIR_FS_CATALOG . 'includes/classes/novalnet/db_version11.sql'; + $sql_lines = file_get_contents($sql_file); + $sql_linesArr = explode(";",$sql_lines); + foreach ($sql_linesArr as $sql) { + if (trim($sql) > '') { + tep_db_query($sql); + } + } + } + $module_keys = NovalnetPaymentKeys::getKeyValues($module); + if (!empty($module_keys)) { + $sort_order = 1; + foreach ($module_keys as $mkey => $mval) { + tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, use_function, date_added) values ('".$mval['title']."', '".$mkey."', '".$mval['value']."', '".$mval['desc']."', '6', '".($sort_order++)."', '".str_replace("'","\'",$mval['set_function'])."', '".str_replace("'","\'",$mval['use_function'])."', now())"); + } + unset($sort_order); + } + return true; + } + + /** + * Function for checking particular module installed status + * @param $module + * + * @return integer + */ + static public function installedStatus($module = '') { + $module_keys = NovalnetPaymentKeys::getKeyValues($module); + $noofrowcheck = 0; + if (!empty($module_keys)) { + $conf_key = array_keys($module_keys); + $check_query = tep_db_query("select configuration_value from " . TABLE_CONFIGURATION . " where configuration_key = '".$conf_key[1]."'"); + $noofrowcheck = tep_db_num_rows($check_query); + } + return $noofrowcheck; + } + + /** + * Function for uninstalling particular module + * @param $module + * + * @return boolean + */ + static public function uninstall($module = '') { + $module_keys = NovalnetPaymentKeys::getKeyValues($module); + if (!empty($module_keys)) { + tep_db_query("delete from " . TABLE_CONFIGURATION . " where configuration_key in ('" . implode("', '", array_keys($module_keys)) . "')"); + } + return true; + } +} +?> diff --git a/includes/classes/novalnet/class.NovalnetInterface.php b/includes/classes/novalnet/class.NovalnetInterface.php new file mode 100644 index 0000000..e0c45a5 --- /dev/null +++ b/includes/classes/novalnet/class.NovalnetInterface.php @@ -0,0 +1,1779 @@ + array('payment_type'=>'CREDITCARD', + 'key' => 6, + 'paygate_url' => array( + 'novalnet_cc' => 'https://payport.novalnet.de/paygate.jsp', + 'novalnet_cc3d' => 'https://payport.novalnet.de/global_pci_payport', + 'novalnet_cc_pci' => 'https://payport.novalnet.de/pci_payport')), + 'novalnet_sepa' => array('payment_type'=>'DIRECT_DEBIT_SEPA', + 'key' => 37, + 'paygate_url' => array('novalnet_sepa' => 'https://payport.novalnet.de/paygate.jsp')), + 'novalnet_sofortbank' => array('payment_type'=>'ONLINE_TRANSFER', + 'key' => 33, + 'paygate_url' => array('novalnet_sofortbank' => 'https://payport.novalnet.de/online_transfer_payport')), + 'novalnet_paypal' => array('payment_type'=>'PAYPAL', + 'key' => 34, + 'paygate_url' => array('novalnet_paypal' => 'https://payport.novalnet.de/paypal_payport')), + 'novalnet_ideal' => array('payment_type'=>'IDEAL', + 'key' => 49, + 'paygate_url' => array('novalnet_ideal' => 'https://payport.novalnet.de/online_transfer_payport')), + 'novalnet_invoice' => array('payment_type'=>'INVOICE', + 'key' => 27, + 'paygate_url' => array('novalnet_invoice' => 'https://payport.novalnet.de/paygate.jsp')), + 'novalnet_prepayment' => array('payment_type'=>'PREPAYMENT', + 'key' => 27, + 'paygate_url' => array('novalnet_prepayment' => 'https://payport.novalnet.de/paygate.jsp')), + 'novalnet_eps' => array('payment_type'=>'EPS', + 'key' => 50, + 'paygate_url' => array('novalnet_eps' => 'https://payport.novalnet.de/eps_payport')) ); + $arrayValue[$payment_name] = $payment[$payment_name]; + $arrayValue[$payment_name]['test_mode_status'] = defined('MODULE_PAYMENT_'.strtoupper($payment_name).'_TEST_MODE') ? constant('MODULE_PAYMENT_'.strtoupper($payment_name).'_TEST_MODE') : ''; + $arrayValue[$payment_name]['success_order_status'] = defined('MODULE_PAYMENT_'.strtoupper($payment_name).'_ORDER_STATUS') ? constant('MODULE_PAYMENT_'.strtoupper($payment_name).'_ORDER_STATUS') : ''; + $arrayValue[$payment_name]['visibility_amount_limit'] = defined('MODULE_PAYMENT_'.strtoupper($payment_name).'_VISIBILITY_BYAMOUNT') ? constant('MODULE_PAYMENT_'.strtoupper($payment_name).'_VISIBILITY_BYAMOUNT') : ''; + $arrayValue[$payment_name]['payment_zone'] = defined('MODULE_PAYMENT_'.strtoupper($payment_name).'_PAYMENT_ZONE') ? constant('MODULE_PAYMENT_'.strtoupper($payment_name).'_PAYMENT_ZONE') : ''; + if($payment_name == 'novalnet_paypal') { + $arrayValue[$payment_name]['payment_pending_order_status'] = defined('MODULE_PAYMENT_NOVALNET_PAYPAL_PAYPENDING_ORDER_STATUS') ? MODULE_PAYMENT_NOVALNET_PAYPAL_PAYPENDING_ORDER_STATUS : ''; + } + return $arrayValue; + } + return array(); + } + + /** + * Get payment method's custom parameters + * @param $payment_type + * + * @return array + */ + static public function getCustomParametersInfoAry($payment_type) { + $payment = array( 'CC' => 'CREDITCARD','SEPA' => 'DIRECT_DEBIT_SEPA', 'SOFORTBANK' => 'ONLINE_TRANSFER', 'PAYPAL' => 'PAYPAL', 'IDEAL' => 'IDEAL', 'INVOICE' => 'INVOICE', 'PREPAYMENT' => 'PREPAYMENT', 'EPS' => 'EPS' ); + foreach($payment as $k => $v) { + $value[$v]['inputval1'] = defined('MODULE_PAYMENT_NOVALNET_'.$k.'_TRANS_REFERENCE1') ? constant('MODULE_PAYMENT_NOVALNET_'.$k.'_TRANS_REFERENCE1') : ''; + $value[$v]['inputval2'] = defined('MODULE_PAYMENT_NOVALNET_'.$k.'_TRANS_REFERENCE2') ? constant('MODULE_PAYMENT_NOVALNET_'.$k.'_TRANS_REFERENCE2') : ''; + } + return $value[$payment_type]; + } + + /** + * Perform novalnet payment call + * @param $datas + * + * @return mixed + */ + static public function doPayment($datas) { + $given_payment_name = $datas['payment']; + $language = MODULE_PAYMENT_NOVALNET_LANGUAGE_TEXT; + list($firstName, $lastName, $streetAddress, $city, $postCode, $telephone, $countryCode) = self::getPaymentCustomerAddressInfo($datas); + $payment_type_val = self::getPaymentType($given_payment_name); + $order_amount = $datas['payment_amount']; + if ($order_amount == '') { + $payment_error_return = 'payment_error=' . $given_payment_name . '&error=' . MODULE_PAYMENT_NOVALNET_PLEASE_SPECIFY_AMOUNT_ERROR_MESSAGE; + $payment_error_return = self::setUTFText($payment_error_return); + tep_redirect(html_entity_decode(tep_href_link(FILENAME_CHECKOUT_PAYMENT, $payment_error_return, 'SSL', true, false))); + } + $tariff_type = ''; + $tariff_val = NovalnetCore::getTariffID(); + $tariff_details = explode('-', $tariff_val); + $tariff_type = $tariff_details[0]; + $tariff = $tariff_details[1]; + $tid_onhold = self::checkManualCheckLimit($given_payment_name, $order_amount); + list($customers_id, $customer_gender, $customer_dob, $customer_fax) = self::collectCustomerDobGenderFax($datas['customer']['email_address']); + $is_redirect_method = 0; + $card_account_holder = ""; + $urlparam = array( + 'vendor' => NovalnetCore::getVendorID(), + 'product' => NovalnetCore::getProductID(), + 'key' => self::getPaymentKey($given_payment_name), + 'payment_type' => $payment_type_val, + 'tariff' => $tariff, + 'auth_code' => NovalnetCore::getVendorAuthCode(), + 'currency' => $datas['info']['currency'], + 'first_name' => $firstName, + 'last_name' => $lastName, + 'gender' => $customer_gender, + 'email' => $datas['customer']['email_address'], + 'birth_date' => $customer_dob, + 'street' => $streetAddress, + 'search_in_street' => 1, + 'city' => $city, + 'zip' => $postCode, + 'lang' => $language, + 'language' => $language, + 'country' => $countryCode, + 'country_code' => $countryCode, + 'tel' => $telephone, + 'fax' => $customer_fax, + 'remote_ip' => self::getRemoteAddr(), + 'test_mode' => self::getPaymentTestModeStatus($given_payment_name), + 'customer_no' => (($customers_id != '')?$customers_id:'Guest'), + 'amount' => $order_amount, + 'system_name' => 'oscommerce', + 'system_version' => (function_exists('tep_get_version') ? 'osCommerce'.tep_get_version() : PROJECT_VERSION) . '-NN' . getPaymentModuleVersion(), + 'system_url' => NovalnetValidation::getSiteDomain(), + 'system_ip' => self::getServerAddr(), + 'notify_url' => MODULE_PAYMENT_NOVALNET_CALLBACK_URL + ); + $current_process_key = ''; + if (NovalnetCore::getReferrerID() != '') { + $urlparam['referrer_id'] = NovalnetCore::getReferrerID(); + } + if (NovalnetCore::getTariffPeriod() != '') { + $urlparam['tariff_period'] = NovalnetCore::getTariffPeriod(); + } + if (NovalnetCore::getTariffPeriod2() != '') { + $urlparam['tariff_period2'] = NovalnetCore::getTariffPeriod2(); + } + if (NovalnetCore::getTariffPeriod2Amount() != '') { + $urlparam['tariff_period2_amount'] = NovalnetCore::getTariffPeriod2Amount(); + } + + if ( !in_array($tariff_type, array(1, 3, 4)) && ( ( $payment_type_val == 'CREDITCARD' && MODULE_PAYMENT_NOVALNET_CC_SHOP_TYPE == 'ZEROAMOUNT' ) || ( $payment_type_val == 'DIRECT_DEBIT_SEPA' && MODULE_PAYMENT_NOVALNET_SEPA_SHOP_TYPE == 'ZEROAMOUNT' ) ) ) { + $urlparam['amount'] = 0; + } + + // TID onhold process + if ($tid_onhold == 1 && in_array($payment_type_val, array('CREDITCARD','INVOICE','DIRECT_DEBIT_SEPA'))) { + $urlparam['on_hold'] = 1; + } + // Appending Credit Card / 3D Secure payment parameters + if ($payment_type_val == 'CREDITCARD' && (MODULE_PAYMENT_NOVALNET_CC_FORM_TYPE != 'Redirect' || MODULE_PAYMENT_NOVALNET_CC_3D_SECURE == 'True')) { + if (!empty($_SESSION['novalnet'][$given_payment_name]['nn_payment_ref_tid']) && $datas['novalnet_ccchange_account'] == 1) { + if (MODULE_PAYMENT_NOVALNET_CC_CVC_ON_ONE_CLICK_ACCEPT == 'True') { + $urlparam['cc_cvc2'] = $datas['novalnet_cc_cvc_ref']; + $urlparam['pan_hash'] = $current_process_key = $datas['nn_ref_process_key']; + $urlparam['unique_id'] = NovalnetCore::uniqueRandomString(); + } else { + $current_process_key = $datas['nn_ref_process_key']; + } + $urlparam['payment_ref'] = $_SESSION['novalnet'][$given_payment_name]['nn_payment_ref_tid']; + unset($_SESSION['novalnet'][$given_payment_name]['nn_payment_ref_tid']); + } else { + $urlparam['cc_cvc2'] = $datas['novalnet_cc_cvc']; + $urlparam['pan_hash'] = $current_process_key = $datas['nn_cc_hash']; + $urlparam['unique_id'] = $datas['nn_cc_uniqueid']; + } + if (MODULE_PAYMENT_NOVALNET_CC_3D_SECURE == 'True') { + $_SESSION['novalnet'][$given_payment_name]['card_account_holder'] = $datas['novalnet_cc_holder']; + $is_redirect_method = 1; + } else { + $card_account_holder = isset($datas['novalnet_cc_holder']) ? $datas['novalnet_cc_holder'] : ''; + } + } + // Appending Direct Debit SEPA payment parameters + elseif ($payment_type_val == 'DIRECT_DEBIT_SEPA') { + if (!empty($_SESSION['novalnet'][$given_payment_name]['nn_payment_ref_tid_sepa']) && $datas['novalnet_sepachange_account'] == 1) { + $urlparam['payment_ref'] = $_SESSION['novalnet'][$given_payment_name]['nn_payment_ref_tid_sepa']; + $current_process_key = $datas['nn_ref_process_key']; + unset($_SESSION['novalnet'][$given_payment_name]['nn_payment_ref_tid_sepa']); + } else { + $urlparam['iban_bic_confirmed'] = 1; + $urlparam['bank_account_holder'] = $card_account_holder = parent::getValidHolderName($datas['novalnet_sepa_account_holder']); + $urlparam['sepa_hash'] = $current_process_key = $datas['nn_sepa_hash']; + $urlparam['sepa_unique_id'] = $datas['nn_sepa_uniqueid']; + } + $sepa_due_date_limit_tmp = NovalnetCore::getSepaPaymentDuration(); + $sepa_due_date_limit = (($sepa_due_date_limit_tmp != '' && $sepa_due_date_limit_tmp >= 7) ? $sepa_due_date_limit_tmp : 7); + unset($sepa_due_date_limit_tmp); + $urlparam['sepa_due_date'] = (date('Y-m-d', strtotime('+'.$sepa_due_date_limit.' days'))); + } + // Append values for Invoice and Prepayment payment methods + elseif (in_array($payment_type_val, array('INVOICE','PREPAYMENT'))) { + if ($payment_type_val == 'INVOICE') { + $invoice_due_date = self::getInvoiceDueDate(); + if ($invoice_due_date != '') { + $urlparam['due_date'] = $invoice_due_date; + } + } + $urlparam['invoice_type'] = $payment_type_val; + } + + // Affiliate process + NovalnetCore::getAffDetails($urlparam); + // Append values for redirection methods + if (in_array($payment_type_val, array('PAYPAL', 'IDEAL', 'ONLINE_TRANSFER', 'EPS')) || ($payment_type_val == 'CREDITCARD' && (MODULE_PAYMENT_NOVALNET_CC_FORM_TYPE == 'Redirect' && MODULE_PAYMENT_NOVALNET_CC_3D_SECURE != 'True'))) { + $encoded_values = self::generateHashValue(array( + 'auth_code' => $urlparam['auth_code'], + 'product' => $urlparam['product'], + 'tariff' => $urlparam['tariff'], + 'amount' => $order_amount, + 'test_mode' => $urlparam['test_mode'], + 'uniqid' => time()) + ); + foreach($encoded_values as $k => $v) { + $urlparam[$k] = $v; + } + $urlparam['user_variable_0'] = str_replace(array('http://','https://'), '', NovalnetValidation::getSiteDomain()); + $urlparam['implementation'] = ($payment_type_val == 'CREDITCARD' && MODULE_PAYMENT_NOVALNET_CC_FORM_TYPE == 'Redirect') ? 'PHP_PCI' : 'PHP'; //Encoding type + $is_redirect_method = 1; + } + if ($is_redirect_method == 1) { + if ($payment_type_val == 'CREDITCARD' && MODULE_PAYMENT_NOVALNET_CC_3D_SECURE == 'True') { + $urlparam['encoded_amount'] = self::generateEncode($urlparam['amount']); + } + $urlparam['return_method'] = $urlparam['error_return_method'] = 'POST'; + $urlparam['return_url'] = $urlparam['error_return_url'] = tep_href_link(FILENAME_CHECKOUT_PROCESS, '', 'SSL'); + } + + $urlparam = self::appendCustomParameters($urlparam); // input1, input2 parameters + if (in_array($payment_type_val, array ('CREDITCARD', 'INVOICE', 'DIRECT_DEBIT_SEPA')) && !isset($_SESSION['novalnet'][$given_payment_name]['nn_payment_ref_enable'])) { + if ( !empty($datas['fraud_module']) && $datas['fraud_module_status'] ) { + switch ($datas['fraud_module']) { + case 'CALLBACK': + $urlparam['tel'] = trim($datas[$given_payment_name.'_fraud_tel']); + $urlparam['pin_by_callback'] = '1'; + break; + case 'EMAIL': + $urlparam['email'] = trim($datas[$given_payment_name.'_fraud_email']); + $urlparam['reply_email_check'] = '1'; + break; + case 'SMS': + $urlparam['mobile'] = trim($datas[$given_payment_name.'_fraud_mobile']); + $urlparam['pin_by_sms'] = '1'; + break; + } + } + } + $paygate_url = self::getPaygateURL($given_payment_name); + $urlparam = array_map('html_entity_decode', $urlparam); + if ($is_redirect_method == 0) { + $payment_response = self::doPaymentCurlCall($paygate_url, $urlparam); // Sending parameters to novalnet gateway + $paymentresponse = self::checkPaymentStatus($given_payment_name, $payment_response, $datas); // Validate novalnet paygate response + $maskedvalues = ''; + if ($payment_type_val == 'CREDITCARD') { + $maskedvalues = serialize(array( + 'cc_holder' => html_entity_decode($paymentresponse['gateway_response']['cc_holder'], ENT_QUOTES, "UTF-8"), + 'cc_no' => self::novalnet_masking($paymentresponse['gateway_response']['cc_no']), + 'cc_exp_year' => (isset($datas['novalnet_cc_exp_year']) && $datas['novalnet_cc_exp_year'])?$datas['novalnet_cc_exp_year']:$datas['nn_ref_cc_exp_year'], + 'cc_exp_month' => (isset($datas['novalnet_cc_exp_month']) && $datas['novalnet_cc_exp_month'])?$datas['novalnet_cc_exp_month']:$datas['nn_ref_cc_exp_month'], + )); + } elseif ($payment_type_val == 'DIRECT_DEBIT_SEPA') { + $maskedvalues = serialize(array( + 'bankaccount_holder' => html_entity_decode($paymentresponse['gateway_response']['bankaccount_holder'], ENT_QUOTES, "UTF-8"), + 'iban' => self::novalnet_masking($paymentresponse['gateway_response']['iban']), + 'bic' => self::novalnet_masking($paymentresponse['gateway_response']['bic']) + )); + } + $zero_transaction = 0; + if(!in_array($tariff_type, array(1, 3, 4)) && (($payment_type_val == 'CREDITCARD' && MODULE_PAYMENT_NOVALNET_CC_SHOP_TYPE == 'ZEROAMOUNT') || ($payment_type_val == 'DIRECT_DEBIT_SEPA' && MODULE_PAYMENT_NOVALNET_SEPA_SHOP_TYPE == 'ZEROAMOUNT'))) { + $zero_transaction = 1; + if($payment_type_val == 'DIRECT_DEBIT_SEPA' && isset($sepa_due_date_limit)) { + unset($urlparam['sepa_due_date']); + $urlparam['sepa_due_date_limit'] = $sepa_due_date_limit; + } + unset($urlparam['pin_by_callback']); + unset($urlparam['reply_email_check']); + unset($urlparam['pin_by_sms']); + $zerotrxndetails = serialize($urlparam); + } + if ($paymentresponse['status'] == 100) { // Payment success + $_SESSION[$given_payment_name.'_callback_max_time'] = time() + (30 * 60); + $_SESSION['novalnet'][$given_payment_name] = array( + 'order_amount' => $order_amount, + 'order_currency' => $paymentresponse['gateway_response']['currency'], + 'test_mode' => $paymentresponse['gateway_response']['test_mode'], + 'tid' => $paymentresponse['tid'], + 'vendor' => $urlparam['vendor'], + 'product' => $urlparam['product'], + 'tariff' => $urlparam['tariff'], + 'auth_code' => $urlparam['auth_code'], + 'gateway_response' => $paymentresponse['gateway_response'], + 'additional_note' => $paymentresponse['additional_note'], + 'card_account_holder' => $card_account_holder, + 'customer_id' => (($customers_id != '') ? $customers_id : ''), + 'process_key' => (($current_process_key != '') ? $current_process_key:''), + 'nntrxncomments' => $paymentresponse['comments'], + 'masked_acc_details' => isset($maskedvalues) ? $maskedvalues : '', + 'reference_transaction' => isset($urlparam['payment_ref'])?'1':'0', + 'zerotrxnreference' => ($zero_transaction == 1) ? $paymentresponse['tid'] : '', + 'zerotrxndetails' => isset($zerotrxndetails) ? $zerotrxndetails : '', + 'zero_transaction' => $zero_transaction + ); + + return $paymentresponse; // For after_process functionality + } else { // Payment failed + $payment_error_return = 'payment_error=' . $given_payment_name . '&error=' . self::setUTFText($paymentresponse['status_desc'], true); + tep_redirect(html_entity_decode(tep_href_link(FILENAME_CHECKOUT_PAYMENT, $payment_error_return, 'SSL', true, false))); + } + } elseif ($is_redirect_method == 1) { + $frmData = ''; + if ($payment_type_val == 'CREDITCARD') { + $_SESSION['novalnet'][$given_payment_name] = array_merge($_SESSION['novalnet'][$given_payment_name], array('request' => $urlparam, 'card_details' => $datas)); + if (MODULE_PAYMENT_NOVALNET_CC_FORM_TYPE == 'Redirect' && MODULE_PAYMENT_NOVALNET_CC_3D_SECURE != 'True') { + $urlparam['vendor_id'] = $urlparam['vendor']; + $urlparam['vendor_authcode'] = $urlparam['auth_code']; + $urlparam['product_id'] = $urlparam['product']; + $urlparam['tariff_id'] = $urlparam['tariff']; + unset($urlparam['vendor']); + unset($urlparam['auth_code']); + unset($urlparam['product']); + unset($urlparam['tariff']); + } + } + foreach ($urlparam as $k => $v) { + $frmData .= ''; + } + return $frmData; + } + tep_redirect(tep_href_link(FILENAME_CHECKOUT_PAYMENT, '', 'SSL', true, false)); + } + + /* + * Perform masking of the account details + * @param $number + * + * @return string + */ + static public function novalnet_masking($number) { + return str_repeat("X", strlen($number) - 4) . substr($number, -4); + } + + /** + * Perform manual check limit functionality + * @param $payment_name + * @param $order_amount + * + * @return integer + */ + static public function checkManualCheckLimit($payment_name = '', $order_amount = '') { + $tid_onhold = 0; + if ( $payment_name != '' && in_array($payment_name, array('novalnet_cc', 'novalnet_sepa', 'novalnet_invoice')) && $order_amount != '' ) { + $manual_check_limit_value = self::getPaymentManualCheckLimit(); + if ( $manual_check_limit_value != '' && $order_amount >= $manual_check_limit_value ) { + $tid_onhold = 1; + } + } + return $tid_onhold; + } + + /** + * Perform paygate second call for updating order_no and confirm the transaction + * @param $datas + * + * @return boolean + */ + static public function doPaymentSecondCall($datas) { + if ( $datas['nn_vendor'] != '' && $datas['nn_auth_code'] != '' && $datas['nn_product'] != '' && $datas['nn_tariff'] != '' && $datas['tid'] != '' && $datas['payment'] != '' ) { + $payment_key = self::getPaymentKey($datas['payment']); + if($payment_key == 6 && MODULE_PAYMENT_NOVALNET_CC_3D_SECURE == 'True' || MODULE_PAYMENT_NOVALNET_CC_FORM_TYPE == 'Redirect') { + $urlparam = array('vendor_id' => $datas['nn_vendor'], + 'product_id' => $datas['nn_product'], + 'tariff_id' => $datas['nn_tariff'], + 'vendor_authcode' => $datas['nn_auth_code']); + } else { + $urlparam = array('vendor' => $datas['nn_vendor'], + 'product' => $datas['nn_product'], + 'tariff' => $datas['nn_tariff'], + 'auth_code' => $datas['nn_auth_code']); + } + $trans_details = array( + 'key' => $payment_key, + 'status' => 100, + 'tid' => $datas['tid'], + 'order_no' => $datas['order_no'], + ); + $urlparam = array_merge($urlparam, $trans_details); + if ($payment_key == 27) { + if ( !empty($datas['invoice_ref']) ) { + $urlparam['invoice_ref'] = $datas['invoice_ref']; + } + // Update order number for invoice and prepayment transaction table + self::updatePrepaymentInvoiceTransOrderRef(array('order_id' => $datas['order_no'], + 'tid' => $datas['tid'], + 'additional_note' => $datas['tid'] + )); + } + if(isset($_SESSION['nn_aff_id'])) { unset($_SESSION['nn_aff_id']); } + $payment_response = self::doPaymentCurlCall('https://payport.novalnet.de/paygate.jsp', $urlparam); + return true; + } + } + + /** + * Get payment amount of given order + * @param $datas + * + * @return integer + */ + static public function getPaymentAmount($datas, $code) { + $total = $datas['info']['total'] * $datas['info']['currency_value']; + $total = sprintf('%0.2f', $total); + $total = (string)($total * 100); // Convert into Cents + if ( preg_match('/[^\d\.]/', $total) || !$total ) { + $payment_error_return = 'payment_error='. $code .'&error=' . MODULE_PAYMENT_NOVALNET_PLEASE_SPECIFY_AMOUNT_ERROR_MESSAGE; + $payment_error_return = self::setUTFText($payment_error_return); + tep_redirect(html_entity_decode(tep_href_link(FILENAME_CHECKOUT_PAYMENT, $payment_error_return, 'SSL', true, false))); + } + return $total; + } + + /** + * Get reference parameters + * @param $urlparam + * + * @return array + */ + static public function appendCustomParameters($urlparam) { + $custom_params = self::getCustomParametersInfoAry($urlparam['payment_type']); + foreach ($custom_params as $ukey => $uval) { + $uval = trim(strip_tags($uval)); + $customparam_id = explode('inputval',$ukey); + if ( $customparam_id[1] > 0 && $customparam_id[1] <= 7 && $uval != '' ) { + $urlparam['input'.$customparam_id[1]] = 'Reference '.$customparam_id[1]; + $urlparam[$ukey] = str_replace(array("+","(",")","$","~","%",".",":","*","?","<",">","{","}"), '', $uval); + } + } + return $urlparam; + } + + /** + * Validate gateway response status + * @param $payment_name + * @param $response + * @param $order_obj + * + * @return array + */ + static public function checkPaymentStatus($payment_name = '', $response = '', $order_obj = array()) { + $trans_comments = $trans_status = $trans_status_desc = ''; + parse_str($response, $data); // Parse paygate response into array + if ( $data['status'] == 100 || ($payment_name == 'novalnet_paypal' && $data['status'] == 90) ) { // Payment success + $trans_status = $data['status']; + $payment_test_mode_in_shop = self::getPaymentTestModeStatus($payment_name); + $test_mode_msg = (((!empty($data['test_mode']) == 1) || + $payment_test_mode_in_shop == 1) ? MODULE_PAYMENT_NOVALNET_TEST_ORDER_MESSAGE : ''); + $data['test_mode'] = (($data['test_mode']==1)?$data['test_mode']:$payment_test_mode_in_shop); + if (in_array($payment_name, array('novalnet_invoice','novalnet_prepayment'))) { + list($trans_comments, $invoice_due_date) = self::formInvoicePrepaymentComments($data, $test_mode_msg); + // Append end customer comments + $trans_user_comments = self::getCustomerCustomComments($order_obj); + $trans_comments = $trans_user_comments.$trans_comments; + self::logPrepaymentInvoiceTransAccountInfo(array( + 'order_no' => '', + 'tid' => $data['tid'], + 'test_mode' => (($data['test_mode']==1) ? $data['test_mode'] : $payment_test_mode_in_shop), + 'account_holder' => 'NOVALNET AG', + 'account_number' => $data['invoice_account'], + 'bank_code' => $data['invoice_bankcode'], + 'bank_name' => $data['invoice_bankname'], + 'bank_city' => $data['invoice_bankplace'], + 'amount' => $data['amount'], + 'currency' => $data['currency'], + 'bank_iban' => $data['invoice_iban'], + 'bank_bic' => $data['invoice_bic'], + 'due_date' => $invoice_due_date, + 'additional_note' => self::getCustomerCustomComments($order_obj) + )); + } else { + $trans_comments = MODULE_PAYMENT_NOVALNET_TRANSACTION_ID.$data['tid'].PHP_EOL.$test_mode_msg; + } + } else { // Payment failed + $trans_status_desc = ( (!empty($data['status_text'])) ? $data['status_text'] : ((isset($data['status_desc']) && + $data['status_desc'] != '' ) ? $data['status_desc'] : MODULE_PAYMENT_NOVALNET_TRANSACTION_ERROR) ); + } + $result = array( 'status' => $trans_status, + 'status_desc' => $trans_status_desc, + 'tid' => ((isset($data['tid'])) ? $data['tid'] : ''), + 'comments' => $trans_comments, + 'gateway_response' => $data, + 'additional_note' => self::getCustomerCustomComments($order_obj) + ); + return $result; + } + + /** + * Get Invoice due date + * @param $format + * + * @return mixed + */ + static public function getInvoiceDueDate($format = 'Y-m-d') { + $invoice_due_date = trim(MODULE_PAYMENT_NOVALNET_INVOICE_DUE_DATE); + if ($invoice_due_date != '' && ctype_digit($invoice_due_date)) { + return (date($format, strtotime('+'.$invoice_due_date.' days'))); + } + return ''; + } + + /** + * Get Invoice / Prepayment comments + * @param $data + * + * @return array + */ + static public function formInvoicePrepaymentComments($data , $testmode = '') { + $currencies = new currencies(); + $trans_comments = MODULE_PAYMENT_NOVALNET_TRANSACTION_ID.$data['tid'].PHP_EOL.$testmode; + $trans_comments .= PHP_EOL.MODULE_PAYMENT_NOVALNET_INVOICE_COMMENTS_PARAGRAPH.PHP_EOL; + $invoice_due_date = $data['due_date']; + if ($invoice_due_date != '') { + $trans_comments .= MODULE_PAYMENT_NOVALNET_DUE_DATE.' : '.tep_date_short($invoice_due_date).PHP_EOL; + } + $trans_comments .= MODULE_PAYMENT_NOVALNET_ACCOUNT_HOLDER.' : NOVALNET AG'.PHP_EOL; + $trans_comments .= MODULE_PAYMENT_NOVALNET_IBAN.' : '.$data['invoice_iban'].PHP_EOL; + $trans_comments .= MODULE_PAYMENT_NOVALNET_SWIFT_BIC.' : '.$data['invoice_bic'].PHP_EOL; + $trans_comments .= MODULE_PAYMENT_NOVALNET_BANK.' : '.$data['invoice_bankname'].' '.$data['invoice_bankplace'].PHP_EOL; + $trans_comments .= MODULE_PAYMENT_NOVALNET_AMOUNT.' : '.$currencies->format($data['amount'], false, $data['currency']); + return array($trans_comments, $invoice_due_date); + } + + /** + * Get the payment key of the given payment name + * @param $payment_name + * + * @return integer + */ + static public function getPaymentKey($payment_name = '') { + if ($payment_name != '') { + $payment_types_info = self::getPaymentTypeInfoAry($payment_name); + if (isset($payment_types_info[$payment_name])) { + $payment_type = $payment_types_info[$payment_name]; + $current_payment_key = $payment_type['key']; + return $current_payment_key; + } + } + } + + /** + * Get payment visibility amount limit of the given payment name + * @param $payment_name + * + * @return mixed + */ + static public function getPaymentVisibilityAmount($payment_name) { + $payment_types_info = self::getPaymentTypeInfoAry($payment_name); + if (isset($payment_types_info[$payment_name])) { + $payment_type = $payment_types_info[$payment_name]; + return ((!empty($payment_type['visibility_amount_limit'])) ? trim($payment_type['visibility_amount_limit']) : ''); + } + } + + /** + * Get manual check limit value + * + * @return mixed + */ + static public function getPaymentManualCheckLimit() { + $tmp_manual_limit = NovalnetCore::getManualCheckLimit(); + return (($tmp_manual_limit != '') ? $tmp_manual_limit : ''); + } + + /** + * Get payment_zone of the given payment name + * @param $payment_name + * + * @return string + */ + static public function getPaymentZoneID($payment_name) { + $payment_types_info = self::getPaymentTypeInfoAry($payment_name); + if (isset($payment_types_info[$payment_name])) { + return $payment_types_info[$payment_name]['payment_zone']; + } + } + + /** + * Validate payment zone for module visibility + * @param $datas + * @param $payment_name + * @param $enabled_status + * + * @return boolean + */ + static public function checkValidPaymentZoneID($datas, $payment_name = '', $enabled_status = false) { + if ( $payment_name != '' && $enabled_status ) { + $payment_zone_id = self::getPaymentZoneID($payment_name); + $check_flag = false; + if ( $payment_zone_id != '' && $payment_zone_id != 0 ) { + $sqlQuery = tep_db_query("select zone_id from " . TABLE_ZONES_TO_GEO_ZONES . " where geo_zone_id = '".tep_db_input($payment_zone_id)."' and zone_country_id = '".tep_db_input($datas['billing']['country']['id'])."' order by zone_id"); + while ($check = tep_db_fetch_array($sqlQuery)) { + if ($check['zone_id'] < 1) { + $check_flag = true; + break; + } + elseif ($check['zone_id'] == $datas['billing']['zone_id']) { + $check_flag = true; + break; + } + } + } else { + $check_flag = true; + } + return $check_flag; + } + } + + /** + * Collect customer DOB, FAX, Gender information from the database + * @param $customer_email + * + * @return array + */ + static public function collectCustomerDobGenderFax($customer_email = '') { + $result = array('', 'u', '', ''); + if ($customer_email != '') { + $querySearch = (isset($_SESSION['customer_id'])) ? 'customers_id= "'. tep_db_input($_SESSION['customer_id']).'"' : 'customers_email_address= "'. tep_db_input($customer_email).'"'; + $sqlQuery = tep_db_query("SELECT customers_id, customers_gender, customers_dob, customers_fax FROM ". TABLE_CUSTOMERS . " WHERE ".$querySearch." ORDER BY customers_id DESC"); + $customer_dbvalue = tep_db_fetch_array($sqlQuery); + if (!empty($customer_dbvalue)) { + $customer_dbvalue['customers_dob'] = ($customer_dbvalue['customers_dob'] != '0000-00-00 00:00:00') ? date('Y-m-d', strtotime($customer_dbvalue['customers_dob'])) : ''; + return array($customer_dbvalue['customers_id'], $customer_dbvalue['customers_gender'], $customer_dbvalue['customers_dob'], $customer_dbvalue['customers_fax']); + } + } + return $result; + } + + /** + * Get payment type of given payment name + * @param $payment_name + * + * @return string + */ + static public function getPaymentType($payment_name) { + $payment_types_info = self::getPaymentTypeInfoAry($payment_name); + if (isset($payment_types_info[$payment_name])) { + return $payment_types_info[$payment_name]['payment_type']; + } + } + + /** + * Get paygate URL of given payment + * @param $payment_name + * + * @return string + */ + static public function getPaygateURL($payment_name) { + $payment_types_info = self::getPaymentTypeInfoAry($payment_name); + if (isset($payment_types_info[$payment_name])) { + $payment_type = $payment_types_info[$payment_name]; + return ($payment_name == 'novalnet_cc' && MODULE_PAYMENT_NOVALNET_CC_3D_SECURE == 'True') ? $payment_type['paygate_url']['novalnet_cc3d'] : (($payment_name == 'novalnet_cc' && MODULE_PAYMENT_NOVALNET_CC_3D_SECURE != 'True' && MODULE_PAYMENT_NOVALNET_CC_FORM_TYPE == 'Redirect') ? $payment_type['paygate_url']['novalnet_cc_pci'] : $payment_type['paygate_url'][$payment_name]); + } + return ''; + } + + /** + * Get order status of given payment + * @param $payment_name + * @param $payment_status + * + * @return integer + */ + static public function getPaymentOrderStatus($payment_name = '', $payment_status = '') { + $payment_types_info = self::getPaymentTypeInfoAry($payment_name); + if (isset($payment_types_info[$payment_name])) { + if ($payment_status == '90') { + return ($payment_types_info[$payment_name]['payment_pending_order_status'] > 0 && !empty($payment_types_info[$payment_name]['payment_pending_order_status'])) ? $payment_types_info[$payment_name]['payment_pending_order_status'] : DEFAULT_ORDERS_STATUS_ID; + } + return ($payment_types_info[$payment_name]['success_order_status'] > 0 && !empty($payment_types_info[$payment_name]['success_order_status'])) ? $payment_types_info[$payment_name]['success_order_status'] : DEFAULT_ORDERS_STATUS_ID; + } + } + + /** + * Get address information of given order + * @param $datas + * + * @return array + */ + static public function getPaymentCustomerAddressInfo($datas) { + $arrayValue = array('firstname', 'lastname', 'street_address', 'city', 'postcode', 'telephone'); + foreach($arrayValue as $v) { + $value[] = ((!empty($datas['billing'][$v])) ? $datas['billing'][$v] : $datas['customer'][$v]); + } + $value[] = ((!empty($datas['billing']['country']['iso_code_2'])) ? $datas['billing']['country']['iso_code_2'] : $datas['customer']['country']['iso_code_2']); + return $value; + } + + /** + * Process payment visibility status + * @param $payment_name + * @param $order_amount + * + * @return boolean + */ + static public function hidePaymentVisibility($payment_name, $order_amount = '') { + if ( $payment_name == '' || $order_amount == '' ) { + return false; + } + $payment_visible_amount = self::getPaymentVisibilityAmount($payment_name); + if ($payment_visible_amount == '') return true; + if ( $payment_visible_amount != '' && (int)$payment_visible_amount <= (int)$order_amount ) { + return true; + } + return false; + } + + /** + * Get remote ip address + * + * @return string + */ + static public function getRemoteAddr() { + $remoteip_address = tep_get_ip_address(); + return (($remoteip_address == '::1') ? '127.0.0.1' : $_SERVER['REMOTE_ADDR']); + } + + /** + * Get server ip address + * + * @return string + */ + static public function getServerAddr() { + return (($_SERVER['SERVER_ADDR'] == '::1') ? '127.0.0.1' : $_SERVER['SERVER_ADDR']); + } + + /** + * Get customer custom comments + * @param $order_obj + * + * @return string + */ + static public function getCustomerCustomComments($order_obj) { + return ((!empty($order_obj['comments'])) ? PHP_EOL.$order_obj['comments'] : ((!empty($order_obj['info']['comments'])) ? PHP_EOL.$order_obj['info']['comments'] : '')); + } + + /** + * Get test mode status + * @param $payment_name + * + * @return boolean; + */ + static public function getPaymentTestModeStatus($payment_name) { + $payment_types_info = self::getPaymentTypeInfoAry($payment_name); + if (isset($payment_types_info[$payment_name])) { + $payment_type = $payment_types_info[$payment_name]; + return ((isset($payment_type['test_mode_status']) && $payment_type['test_mode_status'] == 'True') ? 1 : 0); + } + } + + /** + * Function to communicate transaction parameters with novalnet paygate + * @param $paygate_url + * @param $datas + * @param $build_query + * + * @return array + */ + static public function doPaymentCurlCall($paygate_url, $datas = array(), $build_query = true) { + $paygate_query = ($build_query) ? http_build_query($datas) : $datas; // Build gateway string from the array + $curl_timeout = NovalnetCore::getGatewayTimeout(); + $ch = curl_init($paygate_url); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, $paygate_query); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0); + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); + curl_setopt($ch, CURLOPT_TIMEOUT, (($curl_timeout != '' && $curl_timeout > 240) ? $curl_timeout : 240)); // Custom curl time-out + if (trim(MODULE_PAYMENT_NOVALNET_PROXY) != '') { // Custom proxy option + curl_setopt($ch, CURLOPT_PROXY, trim(MODULE_PAYMENT_NOVALNET_PROXY)); + } + $response = curl_exec($ch); + curl_close($ch); + return $response; + } + + /** + * Function to update order status as per merchant selection + * @param $order_id + * @param $payment_name + * @param $payment_status + * + * @return boolean + */ + static public function updateOrderCustomStatus($order_id = '', $payment_name = '', $payment_status = '') { + if ( $order_id != '' && $payment_name != '' ) { + $payment_order_status = self::getPaymentOrderStatus($payment_name, $payment_status); + $payment_order_status = ($payment_order_status > 0) ? $payment_order_status : DEFAULT_ORDERS_STATUS_ID; + //Update the Merchant selected order status + $dbVal1['orders_status'] = $dbVal2['orders_status_id'] = $payment_order_status; + if (in_array($payment_name, array('novalnet_invoice', 'novalnet_prepayment'))) { + $invpre_comments = self::novalnetReferenceComments($order_id, $payment_name); + $dbVal2['comments'] = $_SESSION['novalnet'][$payment_name]['nntrxncomments'].$invpre_comments; + } + tep_db_perform(TABLE_ORDERS, $dbVal1, "update", "orders_id='$order_id'"); + tep_db_perform(TABLE_ORDERS_STATUS_HISTORY, $dbVal2, "update", "orders_id='$order_id'"); + } + return true; + } + + /** + * Function to update order status in orders table + * @param $order_id + * @param $orders_status_id + * @param $message + * @param $insertstatushistory + * @param $customer_notified + * + * @return boolean + */ + static public function updateOrderStatus($order_id = '', $orders_status_id = '', $message = '', $insertstatushistory = true, $customer_notified = 0) { + $orders_status_id = ($orders_status_id > 0) ? $orders_status_id : DEFAULT_ORDERS_STATUS_ID; + $param['orders_status'] = $orders_status_id; + $param['last_modified'] = 'now()'; + //Update order orders_status_id + tep_db_perform(TABLE_ORDERS, $param, "update", "orders_id='$order_id'"); + if ($insertstatushistory) { + self::insertOrderStatusHistory($order_id, $message, $orders_status_id, $customer_notified); + } + return true; + } + + /** + * Function to update comments in orders_status_history + * @param $order_id + * @param $message + * @param $orders_status_id + * @param $customer_notified + * + * @return none + */ + static public function insertOrderStatusHistory($order_id = '', $message = '', $orders_status_id = DEFAULT_ORDERS_STATUS_ID, $customer_notified = 0) { + if ( $order_id != '' && $message != '' ) { + $message = tep_db_input($message); + $orders_status_id = ($orders_status_id > 0) ? $orders_status_id : DEFAULT_ORDERS_STATUS_ID; + tep_db_query("insert into ".TABLE_ORDERS_STATUS_HISTORY."(orders_id, date_added, customer_notified, comments, orders_status_id) values ( " . $order_id . ", NOW(), " . $customer_notified . ", '" . $message . "', " . $orders_status_id . ")"); + } + } + + /** + * Perform the encoding process for redirection payment methods + * @param $data + * + * @return string + */ + static public function generateEncode($data = '') { + try { + $crc = sprintf('%u', crc32($data)); + $data = $crc . "|" . $data; + $data = bin2hex($data . $_SESSION['nn_access_key']); + $data = strrev(base64_encode($data)); + } catch (Exception $e) { + echo('Error: ' . $e); + } + return $data; + } + + /** + * Perform the decoding process for redirection payment methods + * @param $data + * + * @return string + */ + static public function generateDecode($data = '') { + try { + $data = base64_decode(strrev($data)); + $data = pack("H" . strlen($data), $data); + $data = substr($data, 0, stripos($data, $_SESSION['nn_access_key'])); + $pos = strpos($data, "|"); + if ($pos === false) { + return("Error: CKSum not found!"); + } + $crc = substr($data, 0, $pos); + $value = trim(substr($data, $pos + 1)); + if ($crc != sprintf('%u', crc32($value))) { + return("Error; CKSum invalid!"); + } + return $value; + } catch (Exception $e) { + echo('Error: ' . $e); + } + return $data; + } + + /** + * Perform the decoding paygate response process for redirection payment methods + * @param $datas + * + * @return array + */ + static public function decodePaygateResponse($datas) { + $result = array(); + $datas['vendor'] = isset($datas['vendor']) ? $datas['vendor'] : $datas['vendor_id']; + $datas['auth_code'] = isset($datas['auth_code']) ? $datas['auth_code'] : $datas['vendor_authcode']; + $datas['tariff'] = isset($datas['tariff']) ? $datas['tariff'] : $datas['tariff_id']; + $datas['product'] = isset($datas['product']) ? $datas['product'] : $datas['product_id']; + foreach ($datas as $key => $value) { + $result[$key] = (in_array($key, array('tariff','auth_code','amount','product','uniqid','test_mode'))) ? self::generateDecode($value) : $value; + } + return $result; + } + + /** + * Perform hash generation process for redirection payment methods + * @param $datas + * + * @return array + */ + static public function generateHashValue($datas) { + foreach($datas as $k => $v) { + $result[$k] = self::generateEncode($v); + } + $result['hash'] = self::generatemd5Value($result); + return $result; + } + + /** + * Get hash value + * @param $datas + * + * @return string + */ + static public function generatemd5Value($datas) { + return md5($datas['auth_code'].$datas['product'].$datas['tariff'].$datas['amount'].$datas['test_mode'].$datas['uniqid']. strrev($_SESSION['nn_access_key'])); + } + + /** + * Perform hash validation with paygate response + * @param $datas + * + * @return boolean + */ + static public function validateHashResponse($datas) { + return (isset($datas['hash2']) && $datas['hash2'] != self::generatemd5Value($datas)) ? false : true; + } + + /** + * Function to log all novalnet transaction in novalnet_transaction_detail table + * @param $datas + * + * @return none + */ + static public function logInitialTransaction($datas) { + $table_values = array( + 'tid' => $datas['tid'], + 'vendor' => $datas['vendor'], + 'product' => $datas['product'], + 'tariff' => $datas['tariff'], + 'auth_code' => $datas['auth_code'], + 'subs_id' => $datas['subs_id'], + 'payment_id' => $datas['payment_id'], + 'payment_type' => $datas['payment_type'], + 'amount' => ((!empty($datas['amount'])) ? $datas['amount'] : 0), + 'total_amount' => ((!empty($datas['total_amount'])) ? $datas['total_amount'] : 0), + 'currency' => $datas['currency'], + 'status' => $datas['status'], + 'gateway_status' => $datas['gateway_status'], + 'order_no' => $datas['order_no'], + 'callback_status' => $datas['callback_status'], + 'date' => date('Y-m-d H:i:s'), + 'test_mode' => ((!empty($datas['test_mode'])) ? 1 : 0), + 'additional_note' => $datas['additional_note'], + 'customer_id' => $datas['customer_id'], + 'language' => $_SESSION['language'], + 'masked_acc_details' => $datas['masked_acc_details'], + 'reference_transaction' => $datas['reference_transaction'], + 'zerotrxnreference' => $datas['zerotrxnreference'], + 'zerotrxndetails' => $datas['zerotrxndetails'], + 'zero_transaction' => $datas['zero_transaction'] + ); + if (isset($datas['refund_amount'])) { + $table_values['refund_amount'] = $datas['refund_amount']; + } + if (!empty($datas['account_holder'])) { + $table_values['account_holder'] = $datas['account_holder']; + } + if ( !empty($datas['process_key']) ) { // Update hash value for endcustomer next order auto refill feature + $table_values['process_key'] = $datas['process_key']; + } + tep_db_perform('novalnet_transaction_detail', $table_values, "insert"); + } + + /** + * Function to log novalnet prepayment and invoice transaction's account details in novalnet_preinvoice_transaction_detail table + * @param $datas + * + * @return none + */ + static public function logPrepaymentInvoiceTransAccountInfo($datas) { + $due_date = ''; + if ($datas['due_date'] != '') { + $due_date = date('Y-m-d', strtotime(str_replace('/','.',$datas['due_date']))); + } + tep_db_perform('novalnet_preinvoice_transaction_detail', array( + 'order_no' => $datas['order_no'], + 'tid' => $datas['tid'], + 'account_holder' => $datas['account_holder'], + 'account_number' => $datas['account_number'], + 'bank_code' => $datas['bank_code'], + 'bank_name' => $datas['bank_name'], + 'bank_city' => $datas['bank_city'], + 'amount' => ($datas['amount']*100), // Convert into cents + 'currency' => $datas['currency'], + 'bank_iban' => $datas['bank_iban'], + 'bank_bic' => $datas['bank_bic'], + 'due_date' => $due_date, + 'date' => date('Y-m-d H:i:s'), + 'test_mode' => ( (!empty($datas['test_mode'])) ? 1 : 0 ) + ), "insert"); + } + + /** + * Function to log novalnet subscription transaction's details in novalnet_subscription_detail table + * @param $datas + * + * @return none + */ + static public function logSubscriptionTransInfo($datas) { + tep_db_perform('novalnet_subscription_detail', array( + 'order_no' => $datas['order_no'], + 'subs_id' => $datas['subs_id'], + 'tid' => $datas['tid'], + 'parent_tid' => $datas['tid'], + 'signup_date' => $datas['signup_date'], + 'termination_reason' => ((!empty($datas['termination_reason'])) ? $datas['termination_reason'] : ''), + 'termination_at' => ((!empty($datas['termination_at'])) ? $datas['termination_at'] : '') + ), "insert"); + } + + /** + * Function to log novalnet transaction's details in novalnet_callback_history table + * @param $datas + * + * @return boolean + */ + static public function logCallbackProcess($datas) { + $datas['date'] = date('Y-m-d H:i:s'); + tep_db_perform('novalnet_callback_history', $datas, 'insert'); + } + + /** + * Function to update subscription termination details in novalnet_subscription_detail table + * @param $datas + * + * @return none + */ + static public function updateSubscriptionTransInfo($datas) { + if ( !empty($datas['termination_reason']) ) { + $param['termination_reason'] = $datas['termination_reason']; + } + if ( !empty($datas['termination_at']) ) { + $param['termination_at'] = $datas['termination_at']; + } + tep_db_perform('novalnet_subscription_detail', $param, "update", "parent_tid='" . $datas['parent_tid'] . "'"); + } + + /** + * Function to update novalnet prepayment and invoice transaction order reference in novalnet_preinvoice_transaction_detail table + * @param $datas + * + * @return none + */ + static public function updatePrepaymentInvoiceTransOrderRef($datas) { + if ( $datas['order_id'] != '' && $datas['tid'] != '' ) { + $param['order_no'] = $datas['order_id']; + if ($datas['amount'] != '') { + $param['amount'] = $datas['amount']; + } + if ($datas['due_date'] != '') { + $param['due_date'] = $datas['due_date']; + } + tep_db_perform('novalnet_preinvoice_transaction_detail', $param, "update", "tid='" . $datas['tid'] . "'"); + } + } + + /** + * Function to update real time novalnet transactions in novalnet_transaction_detail table + * @param $datas + * @param $return_trans_info + * @param $transdetails_active + * @param $preinvoice_table_update + * @param $refund_amount + * @param $update_amount + * + * @return mixed + */ + static public function updateLiveNovalnetTransStatus($datas, $return_trans_info = false, $transdetails_active = true, $preinvoice_table_update = false, $refund_amount = '', $update_amount = false) { + $cancel_order_status = MODULE_PAYMENT_NOVALNET_ONHOLD_ORDER_CANCELLED > 0 ? MODULE_PAYMENT_NOVALNET_ONHOLD_ORDER_CANCELLED : DEFAULT_ORDERS_STATUS_ID; + $tid = $datas['tid']; + if ($tid != '') { + $trans_novalnet_info = self::getTransDetails(array( 'nn_vendor' => $datas['vendor'], + 'nn_auth_code' => $datas['auth_code'], + 'nn_product' => $datas['product'], + 'tid' => $tid + )); + if ($return_trans_info) { + return $trans_novalnet_info; + } + if (!$transdetails_active) { + $param['active'] = 0; + } + $param['amount'] = $trans_novalnet_info->amount; + if ( !empty($refund_amount) ) { + $param['refund_amount'] = $refund_amount; + if ( isset($trans_novalnet_info->status) && $trans_novalnet_info->status == '103' ) { + $order_id = $datas['order_id']; + tep_db_perform(TABLE_ORDERS, array('orders_status' => $cancel_order_status, 'last_modified' => 'now()'), "update", "orders_id='$order_id'"); + tep_db_query("UPDATE ". TABLE_ORDERS_STATUS_HISTORY." SET orders_status_id = ".$cancel_order_status." WHERE orders_id = ".tep_db_input($order_id)." ORDER BY orders_status_history_id DESC LIMIT 1"); + } + } elseif ($update_amount) { + $param['total_amount'] = $trans_novalnet_info->amount; + } + $param['gateway_status'] = ((isset($trans_novalnet_info->status)) ? $trans_novalnet_info->status : 0); + + tep_db_perform('novalnet_transaction_detail', $param, "update", "tid='$tid'"); + + if ($preinvoice_table_update) { + tep_db_perform('novalnet_preinvoice_transaction_detail', array( 'amount' => $trans_novalnet_info->amount), "update", "tid='$tid'"); + } + } + return true; + } + + /** + * Send transaction status request to novalnet gateway + * @param $datas + * + * @return mixed + */ + static public function getTransDetails($datas) { + if ( $datas['nn_vendor'] != '' && $datas['nn_auth_code'] != '' && $datas['nn_product'] != '' && $datas['tid'] != '' ) { + $xml_request = " + + + ".$datas['nn_vendor']." + ".$datas['nn_auth_code']." + TRANSACTION_STATUS + ".$datas['nn_product']." + ".$datas['tid']." + + "; + $response = self::doPaymentCurlCall('https://payport.novalnet.de/nn_infoport.xml',$xml_request,false); + $xml_response = simplexml_load_string($response); + return $xml_response; + } + return ''; + } + + /** + * Perform onhold transaction debit/cancel process + * @param $datas + * + * @return string + */ + static public function onholdTransConfirm($datas) { + $transAPIValidate = NovalnetCore::validateMerchantDetails($datas); + if($transAPIValidate != '') + return $transAPIValidate; + $response = self::doPaymentCurlCall('https://payport.novalnet.de/paygate.jsp',array( + 'vendor' => $datas['vendor'], + 'product' => $datas['product'], + 'key' => $datas['payment_id'], + 'tariff' => $datas['tariff'], + 'auth_code' => $datas['auth_code'], + 'edit_status' => '1', + 'tid' => $datas['tid'], + 'status' => $datas['status'] // 100 / 103 + )); + parse_str($response, $reponse_data); // Parse Paygate response into array + + if ($reponse_data['status'] == 100) { + if ($datas['status'] == 100) { + self::updateOrderStatus($datas['order_id'], MODULE_PAYMENT_NOVALNET_ONHOLD_ORDER_COMPLETE,sprintf(MODULE_PAYMENT_NOVALNET_TRANS_CONFIRM_SUCCESSFUL_MESSAGE, tep_date_short(date('Y/m/d')), date('H:i:s')), true, 1); + } else { + self::updateOrderStatus($datas['order_id'], MODULE_PAYMENT_NOVALNET_ONHOLD_ORDER_CANCELLED, sprintf(MODULE_PAYMENT_NOVALNET_TRANS_DEACTIVATED_MESSAGE, tep_date_short(date('Y/m/d')), date('H:i:s')), true, 1); + } + self::updateLiveNovalnetTransStatus($datas); + } else { + $message = MODULE_PAYMENT_NOVALNET_TRANS_CONFIRM_FAILED_MESSAGE.((!empty($reponse_data['status_desc'])) ? $reponse_data['status_desc'] : ((!empty($reponse_data['status_text'])) ? $reponse_data['status_text'] : '')).'( Status : '.$reponse_data['status'].')'; + self::updateOrderStatus($datas['order_id'], self::getOrderStatus($datas['order_id']), $message, true, 1); + return $message; + } + return ''; + } + + /** + * Get order status of given order id + * @param $order_id + * + * @return integer + */ + static public function getOrderStatus($order_id) { + $orderInfo = tep_db_fetch_array(tep_db_query("select orders_status from ".TABLE_ORDERS." where orders_id = ".tep_db_input($order_id))); + return $orderInfo['orders_status']; + } + + /** + * Perform subscription stop process + * @param $datas + * + * @return mixed + */ + static public function subscriptionTransStop($datas = array()) { + $transAPIValidate = NovalnetCore::validateMerchantDetails($datas); + if($transAPIValidate != '') + return $transAPIValidate; + + $sql_val = tep_db_fetch_array(tep_db_query('SELECT parent_tid FROM `novalnet_subscription_detail` where tid='.$datas['tid'])); + $parent_tid = $sql_val['parent_tid']; + $response = self::doPaymentCurlCall('https://payport.novalnet.de/paygate.jsp',array( + 'vendor' => $datas['vendor'], + 'product' => $datas['product'], + 'key' => $datas['payment_id'], + 'tariff' => $datas['tariff'], + 'auth_code' => $datas['auth_code'], + 'cancel_sub' => '1', + 'tid' => $parent_tid, + 'cancel_reason' => $datas['termination_reason'] + )); + parse_str($response, $data); // Parse Paygate response into array + if ($data['status'] == 100) { + $message = MODULE_PAYMENT_NOVALNET_SUBS_CANCEL_REASON_MESSAGE.$datas['termination_reason']; + $order_status = MODULE_PAYMENT_NOVALNET_SUBSCRIPTION_CANCEL > 0 ? MODULE_PAYMENT_NOVALNET_SUBSCRIPTION_CANCEL : DEFAULT_ORDERS_STATUS_ID; + $db_query = tep_db_query('SELECT order_no from novalnet_subscription_detail WHERE parent_tid = "'.$parent_tid.'"'); + while($row = tep_db_fetch_array($db_query) ) { + self::updateOrderStatus($row['order_no'], $order_status); + } + $parent_order_no = tep_db_fetch_array(tep_db_query('SELECT order_no from novalnet_transaction_detail WHERE tid = "'.$parent_tid.'"')); + + self::insertOrderStatusHistory($parent_order_no['order_no'], $message, $order_status, 1); + self::updateSubscriptionTransInfo(array( + 'termination_reason' => $datas['termination_reason'], + 'termination_at' => date('Y-m-d H:i:s'), + 'parent_tid' => $parent_tid + )); + } else { + return ( (!empty($data['status_desc']) ) ? $data['status_desc'] : ((!empty($data['status_text'])) ? $data['status_text'] : MODULE_PAYMENT_NOVALNET_TRANSACTION_ERROR) ); + } + } + + /** + * Perform transaction refund process + * @param $datas + * + * @return string + */ + static public function refundTransAmount($datas = array()) { + $transAPIValidate = NovalnetCore::validateMerchantDetails($datas); + if($transAPIValidate != '') + return $transAPIValidate; + if ($datas['payment_id'] == 27) + $paid_amount = NovalnetCore::getNovalnetCallbackAmount($datas['order_id']); + if ( !isset($datas['refund_trans_amount']) || ( trim($datas['refund_trans_amount']) <= 0 || !is_numeric($datas['refund_trans_amount'])) || ($datas['payment_id'] == 27 && $datas['refund_trans_amount'] > ($paid_amount - $datas['refund_amount']))) + return MODULE_PAYMENT_NOVALNET_REFUND_ZERO_AMOUNT_ERROR_MESSAGE; + + $currencies = new currencies(); + $refund_param = $datas['refund_trans_amount']; + $refund_params = array( 'vendor' => $datas['vendor'], + 'product' => $datas['product'], + 'key' => $datas['payment_id'], + 'tariff' => $datas['tariff'], + 'auth_code' => $datas['auth_code'], + 'refund_request' => '1', + 'tid' => $datas['tid'], + 'refund_param' => $refund_param + ); + if ($datas['refund_ref'] != '') + $refund_params['refund_ref'] = $datas['refund_ref']; + + if ($datas['refund_paymenttype'] == 'sepa') { + $refund_params['iban'] = $datas['iban']; + $refund_params['bic'] = $datas['bic']; + $refund_params['account_holder'] = $datas['account_holder']; + } + $amount_formated = $currencies->format($refund_param/100, false, $datas['refund_trans_amount_currency']); + $response = self::doPaymentCurlCall('https://payport.novalnet.de/paygate.jsp', $refund_params); + parse_str($response, $data); // Parse Paygate response into array + $order_status = ''; + if ($data['status'] == 100) { + $nn_tid = (!empty($data['tid']) ? $data['tid'] : $datas['tid']); + $trans_novalnet_info = self::getTransDetails(array( 'nn_vendor' => $datas['vendor'], + 'nn_auth_code' => $datas['auth_code'], + 'nn_product' => $datas['product'], + 'tid' => $nn_tid + )); + $message = ''; + $order_server_response = utf8_decode((!empty($data['status_desc'])) ? $data['status_desc'] : ((!empty($data['status_message'])) ? ($data['status_message']) : ((!empty($data['status_text'])) ? $data['status_text'] : MODULE_PAYMENT_NOVALNET_STATUS_SUCCESSFULL_TEXT))); + $message .= sprintf(MODULE_PAYMENT_NOVALNET_REFUND_PARENT_TID_MSG, $datas['tid'], $amount_formated); + if (!empty($data['tid'])) { + $message .= sprintf(MODULE_PAYMENT_NOVALNET_REFUND_CHILD_TID_MSG, $data['tid']); + } + if ( $datas['payment_id'] == 34 && !empty($data['paypal_refund_tid']) ) { + $message .= MODULE_PAYMENT_NOVALNET_PARTIAL_REFUND_MESSAGE."[ ".$amount_formated." ] : ".$order_server_response."."; + $message .= ' - PayPal Ref: '.$data['paypal_refund_tid']; + } + $refund_amount = ($datas['refund_amount'] + $refund_param); + if ($refund_amount >= $datas['total_amount']) { + $order_status = ( ($datas['payment_id'] == 27 && isset($trans_novalnet_info->status) && $trans_novalnet_info->status == 100) ? self::getOrderStatus($datas['order_id']) : MODULE_PAYMENT_NOVALNET_ONHOLD_ORDER_CANCELLED ); + } else { + $order_status = self::getOrderStatus($datas['order_id']); + } + self::updateOrderStatus($datas['order_id'], $order_status, $message, true, 1); + if ( !empty($data['tid']) && $datas['payment_id'] != 6 ) { + $nn_existing_trans_data = NovalnetCore::getNovalnetTransDetails($datas['order_id']); + self::updateLiveNovalnetTransStatus($datas, false, false); // Update status along with active = 0 + self::logInitialTransaction(array( + 'tid' => $data['tid'], + 'vendor' => $datas['vendor'], + 'product' => $datas['product'], + 'tariff' => $datas['tariff'], + 'auth_code' => $datas['auth_code'], + 'subs_id' => $datas['subs_id'], + 'payment_id' => $datas['payment_id'], + 'payment_type' => $datas['payment_type'], + 'amount' => $trans_novalnet_info->amount, + 'refund_amount' => $refund_amount, + 'total_amount' => $trans_novalnet_info->amount, + 'currency' => $trans_novalnet_info->currency, + 'status' => 100, + 'order_no' => $datas['order_id'], + 'callback_status' => 0, + 'test_mode' => $datas['test_mode'], + 'additional_note' => $datas['additional_note'], + 'account_holder' => ((!empty($datas['account_holder'])) ? $datas['account_holder'] : ((!empty($nn_existing_trans_data['account_holder']) ) ? $nn_existing_trans_data['account_holder'] : '')), + 'gateway_status' => ((isset($trans_novalnet_info->status)) ? $trans_novalnet_info->status : 0), + 'process_key' => $nn_existing_trans_data['process_key'], + 'customer_id' => $nn_existing_trans_data['customer_id'] + )); + } else { + ($datas['payment_id'] == 27) ? self::updateLiveNovalnetTransStatus($datas, false, true, true, $refund_amount, false) : self::updateLiveNovalnetTransStatus($datas, false, true, false, $refund_amount, false); + } + return ''; + } else { + return (!empty($data['status_desc'])) ? $data['status_desc'] : ((!empty($data['status_message'])) ? ($data['status_message']) : ((!empty($data['status_text'])) ? $data['status_text'] : MODULE_PAYMENT_NOVALNET_TRANSACTION_ERROR)); + } + } + + /** + * Perform transaction amount / due_date update process + * @param $datas + * + * @return string + */ + static public function updateTransAmount($datas = array()) { + if (!is_numeric($datas['amount']) || $datas['amount'] <= 0) + return MODULE_PAYMENT_NOVALNET_PLEASE_SPECIFY_AMOUNT_ERROR_MESSAGE; + $transAPIValidate = NovalnetCore::validateMerchantDetails($datas); + if($transAPIValidate != '') + return $transAPIValidate; + + $currencies = new currencies(); + $amountChange_request = array( 'vendor' => $datas['vendor'], + 'product' => $datas['product'], + 'key' => $datas['payment_id'], + 'tariff' => $datas['tariff'], + 'auth_code' => $datas['auth_code'], + 'edit_status' => '1', + 'tid' => $datas['tid'], + 'status' => 100, + 'update_inv_amount' => '1', + 'amount' => $datas['amount'] + ); + if ( $datas['due_date'] != '0000-00-00' && $datas['due_date'] != '' ) { + $amountChange_request['due_date'] = $datas['due_date']; + } + $response = self::doPaymentCurlCall('https://payport.novalnet.de/paygate.jsp', $amountChange_request); + parse_str($response, $data); // Parse Paygate response into array + if ($data['status'] == 100) { + $amount_formated = $currencies->format($datas['amount']/100, false, $datas['amount_currency']); + $message = sprintf(MODULE_PAYMENT_NOVALNET_TRANS_UPDATED_MESSAGE, $amount_formated, tep_date_short(date('Y/m/d')), date(' H:i:s')); + self::insertOrderStatusHistory($datas['order_id'], $message, self::getOrderStatus($datas['order_id']), 1); + ($datas['payment_id'] == 27) ? self::updateLiveNovalnetTransStatus($datas, false, true, true, '', true) : self::updateLiveNovalnetTransStatus($datas, false, true, false, '', true); + if ($datas['payment_id'] == 27) { + // Update new comments in orders table for invoice and prepayment payment methods + self::updatePrepaymentInvoiceTransOrderRef(array( + 'order_id' => $datas['order_id'], + 'tid' => $datas['tid'], + 'amount' => $datas['amount'], + 'due_date' => $datas['due_date'] + )); + $tidAccountInfo = NovalnetCore::getPreInvoiceAcccountInfo($datas['tid']); + $test_mode_msg = (($tidAccountInfo['test_mode'] == 1) ? MODULE_PAYMENT_NOVALNET_TEST_ORDER_MESSAGE : ''); + $trans_comments = ''; + list($transDetails, $due_date) = self::formInvoicePrepaymentComments(array( + 'invoice_account' => $tidAccountInfo['account_number'], + 'invoice_bankname' => $tidAccountInfo['bank_name'], + 'invoice_bankplace' => $tidAccountInfo['bank_city'], + 'amount' => sprintf("%.2f",($tidAccountInfo['amount']/100)), + 'currency' => $tidAccountInfo['currency'], + 'tid' => $datas['tid'], + 'invoice_iban' => $tidAccountInfo['bank_iban'], + 'invoice_bic' => $tidAccountInfo['bank_bic'], + 'due_date' => $datas['due_date'] + ), $test_mode_msg); + $transDetails .= self::novalnetReferenceComments($datas['order_id'], $datas['payment_type'], $datas['tid'], 1); + } + $trans_comments .= $transDetails; + self::updateOrderStatus($datas['order_id'], self::getOrderStatus($datas['order_id']), $trans_comments, true, 1); + } else { + return (!empty($data['status_desc'])) ? $data['status_desc'] : ((!empty($data['status_text'])) ? $data['status_text'] : MODULE_PAYMENT_NOVALNET_TRANSACTION_ERROR); + } + return ''; + } + + /** + * Build reference comments for invoice + * @param $insert_id + * @param $payment_type + * @param $tid + * @param $amount_update + * + * @return string + */ + static public function novalnetReferenceComments($insert_id, $payment_type, $tid='', $amount_update = '') { + $invoice_comments = ''; + if($amount_update == 1) { + $payment_ref_value = tep_db_fetch_array(tep_db_query("SELECT payment_ref FROM novalnet_preinvoice_transaction_detail WHERE tid='". tep_db_input($tid) ."' ")); + $reference = unserialize($payment_ref_value['payment_ref']); + $references[1] = $reference['payment_ref1']; + $references[2] = $reference['payment_ref2']; + $references[3] = $reference['payment_ref3']; + } + else { + $references[1] = $data['payment_ref1'] = constant('MODULE_PAYMENT_' . strtoupper($payment_type) . '_PAYMENT_REFERENCE1') == 'True' ? 1 : 0; + $references[2] = $data['payment_ref2'] = constant('MODULE_PAYMENT_' . strtoupper($payment_type) . '_PAYMENT_REFERENCE2') == 'True' ? 1 : 0; + $references[3] = $data['payment_ref3'] = constant('MODULE_PAYMENT_' . strtoupper($payment_type) . '_PAYMENT_REFERENCE3') == 'True' ? 1 : 0; + } + $i = 1; + $ac_reference = array_count_values($references); + $tid = (empty($tid)) ? $_SESSION['novalnet'][$payment_type]['tid'] : $tid; + $invoice_comments .= PHP_EOL . (($ac_reference['1'] > 1) ? MODULE_PAYMENT_NOVALNET_PAYMENT_MULTI_TEXT : MODULE_PAYMENT_NOVALNET_PAYMENT_SINGLE_TEXT) . PHP_EOL; + foreach ($references as $k => $v) { + if ($references[$k] == '1') { + $invoice_comments .= ($ac_reference['1'] == 1) ? MODULE_PAYMENT_NOVALNET_INVPRE_REF : str_replace('@i',$i++, MODULE_PAYMENT_NOVALNET_INVPRE_MULTI_REF); + $invoice_comments .= (($k == 1) ? 'BNR-' . NovalnetCore::getProductID() . '-' . $insert_id : ( $k == 2 ? 'TID '. $tid : MODULE_PAYMENT_NOVALNET_ORDER_NUMBER . ' ' . $insert_id)). PHP_EOL; + } + } + if($amount_update == '') { + $payment_ref = serialize($data); + tep_db_perform('novalnet_preinvoice_transaction_detail', array('payment_ref' => $payment_ref), "update", "tid='".$_SESSION['novalnet'][$payment_type]['tid'] . "'"); + } + return $invoice_comments; + } + + /** + * Build fraudmodules input fields + * @param $fraud_module + * @param $code + * + * @return mixed + */ + static public function buildCallbackInputFields($fraud_module, $code) { + global $order; + if(in_array($fraud_module,array('EMAIL', 'CALLBACK', 'SMS'))) { + $fraud_module_value = array('EMAIL' => array('name' =>'_fraud_email', 'value' => 'email_address'), 'CALLBACK' => array('name' =>'_fraud_tel', 'value' => 'telephone'), 'SMS' => array('name' =>'_fraud_mobile', 'value' => 'mobile')); + return array('title' => constant('MODULE_PAYMENT_NOVALNET_FRAUDMODULE_'. $fraud_module . '_INPUT_TITLE') ." * ", 'field' => tep_draw_input_field($code . $fraud_module_value[$fraud_module]['name'], (isset($order->customer[$fraud_module_value[$fraud_module]['value']]) ? $order->customer[$fraud_module_value[$fraud_module]['value']] : ''), 'id="' . $code . '-' . strtolower($fraud_module) .'"' )); + } + return array(); + } + + /** + * build input fields to get PIN + * @param $fraud_module + * @param $code + * + * @return array + */ + static public function buildCallbackFieldsAfterResponse($fraud_module, $code) { + if (in_array($fraud_module, array('CALLBACK', 'SMS'))) { + $pin_field[] = array('title' => MODULE_PAYMENT_NOVALNET_FRAUDMODULE_PIN_REQUEST_DESC." * ", + 'field' => tep_draw_input_field($code . '_fraud_pin', '', 'id="' . $code . '-callbackpin" autocomplete=off' )); + $pin_field[] = array('title' => '', + 'field' => tep_draw_checkbox_field($code . '_new_pin', '1', false, 'id="' . $code . '-new_pin"') . MODULE_PAYMENT_NOVALNET_FRAUDMODULE_NEW_PIN); + } + else { + $pin_field[] = array('title' => '', + 'field' => MODULE_PAYMENT_NOVALNET_FRAUDMODULE_MAIL_INFO); + } + return $pin_field; + } + + /** + * Redirect to checkout on success using fraud module + * @param $code + * @param $fraud_module + * @param $fraud_module_status + * + * @return none + */ + static public function gotoPaymentOnCallback($code, $fraud_module = NULL, $fraud_module_status = NULL) { + if ($fraud_module && $fraud_module_status) { + $_SESSION['novalnet'][$code]['secondcall'] = TRUE; + $error_message = ( ($fraud_module == 'EMAIL') ? MODULE_PAYMENT_NOVALNET_FRAUDMODULE_MAIL_INFO : ( ($fraud_module == 'SMS') ? MODULE_PAYMENT_NOVALNET_FRAUDMODULE_SMS_PIN_INFO : MODULE_PAYMENT_NOVALNET_FRAUDMODULE_TEL_PIN_INFO) ); + + $payment_error_return = 'payment_error='. $code .'&error=' . html_entity_decode($error_message, ENT_QUOTES, "UTF-8"); + tep_redirect(html_entity_decode(tep_href_link(FILENAME_CHECKOUT_PAYMENT, $payment_error_return, 'SSL', true, false))); + } + } + + /** + * Perform server xml request + * @param $requesttype + * @param $payment_type + * + * @return string + */ + static public function doCallbackRequest($requesttype, $payment_type = '') { + $xml = ' + + + ' . $_SESSION['novalnet'][$payment_type]['vendor'] . ' + ' . $_SESSION['novalnet'][$payment_type]['auth_code'] . ' + ' . $requesttype . ' + ' . $_SESSION['novalnet'][$payment_type]['tid'] . ''; + if ($requesttype == 'PIN_STATUS') + $xml .= '' .trim($_SESSION['novalnet'][$payment_type][$payment_type.'_fraud_pin']) . ''; + $xml .= ''; + $xml_response = self::doPaymentCurlCall('https://payport.novalnet.de/nn_infoport.xml',$xml,false); + return $xml_response; + } + + /** + * Confirm payment after sucessfull fraud check + * @param $payment_type + * @param $fraud_module + * + * @return mixed + */ + static public function doConfirmPayment($payment_type, $fraud_module = NULL) { + $callback_response = ( $fraud_module && in_array($fraud_module,array('SMS', 'CALLBACK')) ) ? self::doCallbackRequest('PIN_STATUS', $payment_type) : self::doCallbackRequest('REPLY_EMAIL_STATUS', $payment_type); + list($status, $statusMessage) = self::getStatusFromXmlResponse($callback_response); + if ($status != 100) { + if ($status == '0529006') { + $_SESSION[$payment_type.'_payment_lock'] = TRUE; + } + $payment_error_return = 'payment_error='. $payment_type .'&error=' . self::setUTFText($statusMessage, true); + tep_redirect(html_entity_decode(tep_href_link(FILENAME_CHECKOUT_PAYMENT, $payment_error_return, 'SSL', true, false))); + } else { + return $callback_response; + } + } + + /** + * Validate status of fraud module + * @param $payment + * @param $order + * @param $fraud_module + * + * @return boolean + */ + static public function setFraudModuleStatus($payment = NULL, $order = array(), $fraud_module = '') { + if ( !$fraud_module || !NovalnetValidation::validateCallbackCountry() || parent::getFraudModuleEnableLimit($payment) > self::getPaymentAmount($order, $payment) ) { + return false; + } + if ( $payment == 'novalnet_cc' && MODULE_PAYMENT_NOVALNET_CC_3D_SECURE == 'True' ) { + return false; + } + return true; + } + + /** + * Get status and message from server response + * @param $response + * + * @return array + */ + static public function getStatusFromXmlResponse($response) { + preg_match('/status>?([^<]+)/i', $response, $status); + preg_match('/status_message>?([^<]+)/i', $response, $statusMessage); + $status = isset($status['1']) ? $status['1'] : ''; + $statusMessage = isset($statusMessage['1']) ? $statusMessage['1'] : '()'; + return array($status, $statusMessage); + } + + /** + * To control the UTF-8 characters + * @param $data + * @param $server_error + * + * @return string + */ + static public function setUTFText($string, $server_error = false) { + if ($server_error) { + if (strtoupper(mb_detect_encoding($string)) == 'UTF-8'){ + return (strtoupper(CHARSET) == 'UTF-8') ? html_entity_decode($string, ENT_QUOTES, "UTF-8") : utf8_decode($string); + } else{ + return utf8_decode($string); + } + } else{ + return (strtoupper(CHARSET) == 'UTF-8') ? utf8_encode(html_entity_decode($string, ENT_QUOTES, "UTF-8")) : html_entity_decode($string); + } + } + + /* + * Log the novalnet process + * @param $trans_details + * @param $response + * + */ + static public function apiAmountCalculation(&$trans_details, $response) { + $payment_type = ($response['payment_id'] == 6) ? 'CREDITCARD_BOOKBACK' : 'REFUND_BY_BANK_TRANSFER_EU'; + if(in_array($response['payment_id'], array(6, 37)) && !empty($response['child_tid_info'])) { + $child_tid_info = json_decode(json_encode($response['child_tid_info']), TRUE); + if (isset($child_tid_info['follow_up']['payment_type']) && $child_tid_info['follow_up']['payment_type'] == $payment_type) + $refund_amount += $child_tid_info['follow_up']['amount']; + else { + foreach( $child_tid_info['follow_up'] as $value ) { + if(!empty( $value['payment_type'] ) && $value['payment_type'] == $payment_type) + $refund_amount += $value['amount']; + } + } + } else { + $refund_amount = $trans_details['total_amount'] - $response['amount']; + } + $trans_details['amount'] = $response['amount']; + $trans_details['status'] = $trans_details['gateway_status'] = $response['status']; + $trans_details['refund_amount'] = $refund_amount; + } + + /* + * To get the order amount for booking + * @param $datas + * + */ + static public function getOrderAmount($order_no) { + $order_total = tep_db_fetch_array(tep_db_query("SELECT value FROM " . TABLE_ORDERS_TOTAL . " where class = 'ot_total' AND orders_id = " . tep_db_input($order_no))); + return $order_total['value']*100; + } + + /* + * Perform to book the amount + * @param $datas + * + * @return string + */ + static public function bookTransAmount($datas) { + $transAPIValidate = NovalnetCore::validateMerchantDetails($datas); + if($transAPIValidate != '') + return $transAPIValidate; + + $sqlQuery = tep_db_query("SELECT zerotrxndetails FROM novalnet_transaction_detail WHERE order_no='". tep_db_input($datas['order_id']) ."'"); + $transInfo = tep_db_fetch_array($sqlQuery); + $urlparam = unserialize($transInfo['zerotrxndetails']); + if(isset($urlparam['sepa_due_date_limit'])) { + $urlparam['sepa_due_date'] = date('Y-m-d', strtotime('+'.$urlparam['sepa_due_date_limit'].' days')); + } + $urlparam['amount'] = $datas['book_amount']; + $urlparam['order_no'] = $datas['order_id']; + $urlparam['payment_ref'] = $datas['tid']; + $response = self::doPaymentCurlCall('https://payport.novalnet.de/paygate.jsp', $urlparam); + parse_str($response, $data); //Parse Paygate response into array + if($data['status'] == 100) { + $currencies = new currencies(); + $amount_formated = $currencies->format($datas['book_amount']/100, false, $datas['amount_currency']); + self::updateOrderStatus($datas['order_id'], self::getOrderStatus($datas['order_id']), PHP_EOL.sprintf(MODULE_PAYMENT_NOVALNET_TRANS_BOOKED_MESSAGE, $amount_formated, $data['tid']).PHP_EOL, true, true, true); + $test_mode_msg = (isset($urlparam['test_mode']) && $urlparam['test_mode'] == 1) ? PHP_EOL . MODULE_PAYMENT_NOVALNET_TEST_ORDER_MESSAGE : ''; + $message = MODULE_PAYMENT_NOVALNET_TRANSACTION_ID . $data['tid'] . $test_mode_msg; + $trans_novalnet_info = self::getTransDetails(array( + 'nn_vendor' => $urlparam['vendor'], + 'nn_auth_code' => $urlparam['auth_code'], + 'nn_product' => $urlparam['product'], + 'tid' => $data['tid'] + )); + $param['tid'] = $data['tid']; + tep_db_perform('novalnet_subscription_detail', $param, "update", "order_no='". tep_db_input($datas['order_id']) ."'"); + $param['amount'] = $param['total_amount'] = $urlparam['amount']; + $param['gateway_status'] = $trans_novalnet_info->status; + tep_db_perform('novalnet_transaction_detail', $param, "update", "order_no='". tep_db_input($datas['order_id']) ."'"); + self::updateOrderStatus($datas['order_id'], self::getOrderStatus($datas['order_id']), $message, true, true, true, true); + } else { + return utf8_decode((!empty($data['status_desc'])) ? $data['status_desc']:((!empty($data['status_text']))?$data['status_text']:MODULE_PAYMENT_NOVALNET_TRANSACTION_ERROR)); + } + return ''; + } + + /* + * Sets Iframe param for creditcard + * + * @return array + */ + static public function setCreditCardIframe () { + require_once DIR_FS_CATALOG.'/novalnet_css_link.php'; + if (NOVALNET_CC_CUSTOM_CSS) + $css = NOVALNET_CC_CUSTOM_CSS; + else + $css = 'body~~~input, select'; + if (NOVALNET_CC_CUSTOM_CSS_STYLE) + $cssval = NOVALNET_CC_CUSTOM_CSS_STYLE; + else + $cssval = 'color: #555555; font-family: Arial,Sans-serif !important; font-size: 12px !important; line-height: 18px;~~~border: 1px solid #666666; padding: 2px; max-width: 202px; min-width: 39px;'; + + $params['nn_language'] = MODULE_PAYMENT_NOVALNET_LANGUAGE_TEXT; + $params['iframe'] = 'creditcard'; + $params['hash'] = NovalnetCore::getCreditCardRefillHash(); + $params['fldvdr'] = isset($_SESSION['novalnet']['novalnet_cc']['cc_fldvalidator']) ? $_SESSION['novalnet']['novalnet_cc']['cc_fldvalidator'] : ''; + $params = http_build_query($params); + return array($css, $cssval, $params); + } + + /* + * Sets Iframe param for sepa + * @param $order + * + * @return array + */ + static public function setSepaIframe($order) { + require_once DIR_FS_CATALOG.'novalnet_css_link.php'; + if (NOVALNET_SEPA_CUSTOM_CSS) + $css = NOVALNET_SEPA_CUSTOM_CSS; + else + $css = 'body~~~input, select'; + if (NOVALNET_SEPA_CUSTOM_CSS_STYLE) + $cssval = NOVALNET_SEPA_CUSTOM_CSS_STYLE; + else + $cssval = 'color: #555555; font-family: Arial,Sans-serif !important; font-size: 12px !important; line-height: 18px;~~~border: 1px solid #666666; padding: 2px; max-width: 202px; min-width: 39px;'; + $params['nn_language'] = MODULE_PAYMENT_NOVALNET_LANGUAGE_TEXT; + $params['iframe'] = 'sepa'; + $firstname = $order->billing['firstname'] ? trim($order->billing['firstname']) : trim($order->customer['firstname']); + $lastname = $order->billing['lastname'] ? trim($order->billing['lastname']) : trim($order->customer['lastname']); + $params['hash'] = parent::getSepaRefillHash($order->customer['email_address'], 'novalnet_sepa'); + $params['fldvdr'] = isset($_SESSION['novalnet']['novalnet_sepa']['sepa_field_validator']) ? $_SESSION['novalnet']['novalnet_sepa']['sepa_field_validator'] : ''; + $params['country_code'] = $order->billing['country']['iso_code_2'] ? trim($order->billing['country']['iso_code_2']) : trim($order->customer['country']['iso_code_2']); + $params['name'] = $firstname . ' ' . $lastname; + $params['comp'] = $order->billing['company'] ? trim($order->billing['company']) : $order->customer['company']; + $params['address'] = $order->billing['street_address'] ? trim($order->billing['street_address']) : $order->customer['street_address']; + $params['zip'] = $order->billing['postcode'] ? trim($order->billing['postcode']) : $order->customer['postcode']; + $params['city'] = $order->billing['city'] ? trim($order->billing['city']) : $order->customer['city']; + $params['email'] = $order->customer['email_address'] ? trim($order->customer['email_address']) : ''; + $params = http_build_query($params); + return array($css, $cssval, $params); + } + + /* + * Check the novalnet version + * + * @return mixed + */ + static public function checkNovalnetVersion() { + $sql = tep_db_query('select table_name from information_schema.columns where table_schema = "' . DB_DATABASE . '"'); + while($result = tep_db_fetch_array($sql)) { + if($result['table_name'] == 'novalnet_version_detail') { + $db_version = tep_db_query('SELECT version from novalnet_version_detail'); + $novalnet_version = tep_db_fetch_array($db_version); + return $novalnet_version['version']; + } + } + return false; + } +} +?> diff --git a/includes/classes/novalnet/class.NovalnetPaymentKeys.php b/includes/classes/novalnet/class.NovalnetPaymentKeys.php new file mode 100644 index 0000000..c0d6fef --- /dev/null +++ b/includes/classes/novalnet/class.NovalnetPaymentKeys.php @@ -0,0 +1,1032 @@ + array( + 'title' => MODULE_PAYMENT_NOVALNET_PUBLIC_KEY_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_PUBLIC_KEY_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_VENDOR' => array( + 'title' => MODULE_PAYMENT_NOVALNET_VENDOR_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_VENDOR_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_AUTH_CODE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_AUTH_CODE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_AUTH_CODE_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_PROJECT' => array( + 'desc' => MODULE_PAYMENT_NOVALNET_PROJECT_DESC, + 'title' => MODULE_PAYMENT_NOVALNET_PROJECT_TITLE, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_TARIFF' => array( + 'title' => MODULE_PAYMENT_NOVALNET_TARIFF_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_TARIFF_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_ACCESS_KEY' => array( + 'title' => MODULE_PAYMENT_NOVALNET_ACCESS_KEY_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_ACCESS_KEY_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_MANUAL_CHECK_LIMIT' => array( + 'title' => MODULE_PAYMENT_NOVALNET_MANUAL_CHECK_LIMIT_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_MANUAL_CHECK_LIMIT_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_AUTO_REFILL' => array( + 'title' => MODULE_PAYMENT_NOVALNET_AUTO_REFILL_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_AUTO_REFILL_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_AUTO_REFILL', MODULE_PAYMENT_NOVALNET_AUTO_REFILL,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_LAST_SUCCESSFULL_PAYMENT_SELECTION' => array( + 'title' => MODULE_PAYMENT_NOVALNET_LAST_SUCCESSFULL_PAYMENT_SELECTION_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_LAST_SUCCESSFULL_PAYMENT_SELECTION_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_LAST_SUCCESSFULL_PAYMENT_SELECTION', MODULE_PAYMENT_NOVALNET_LAST_SUCCESSFULL_PAYMENT_SELECTION,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_PROXY' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PROXY_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_PROXY_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_CURL_TIMEOUT' => array( + 'title' => MODULE_PAYMENT_NOVALNET_CURL_TIMEOUT_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_CURL_TIMEOUT_DESC, + 'value' => '240', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_REFERRER_ID' => array( + 'title' => MODULE_PAYMENT_NOVALNET_REFERRER_ID_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_REFERRER_ID_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_LOGO_DISPLAY' => array( + 'title' => MODULE_PAYMENT_NOVALNET_LOGO_DISPLAY_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_LOGO_DISPLAY_DESC, + 'value' => 'True', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_LOGO_DISPLAY', MODULE_PAYMENT_NOVALNET_LOGO_DISPLAY,", + 'use_function' => '', + ), + 'MODULE_PAYMENT_NOVALNET_PAYMENT_LOGO_DISPLAY' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PAYMENT_LOGO_DISPLAY_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_PAYMENT_LOGO_DISPLAY_DESC, + 'value' => 'True', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_PAYMENT_LOGO_DISPLAY',MODULE_PAYMENT_NOVALNET_PAYMENT_LOGO_DISPLAY,", + 'use_function' => '', + ), + 'MODULE_PAYMENT_NOVALNET_ONHOLD_ORDER_COMPLETE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_ONHOLD_ORDER_COMPLETE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_ONHOLD_ORDER_COMPLETE_DESC, + 'value' => '', + 'set_function' => 'tep_cfg_pull_down_order_statuses(', + 'use_function' => 'tep_get_order_status_name' + ), + 'MODULE_PAYMENT_NOVALNET_ONHOLD_ORDER_CANCELLED' => array( + 'title' => MODULE_PAYMENT_NOVALNET_ONHOLD_ORDER_CANCELLED_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_ONHOLD_ORDER_CANCELLED_DESC, + 'value' => '', + 'set_function' => 'tep_cfg_pull_down_order_statuses(', + 'use_function' => 'tep_get_order_status_name' + ), + 'MODULE_PAYMENT_NOVALNET_TARIFF_PERIOD' => array( + 'title' => MODULE_PAYMENT_NOVALNET_TARIFF_PERIOD_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_TARIFF_PERIOD_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_TARIFF_PERIOD2_AMOUNT' => array( + 'title' => MODULE_PAYMENT_NOVALNET_TARIFF_PERIOD2_AMOUNT_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_TARIFF_PERIOD2_AMOUNT_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_TARIFF_PERIOD2' => array( + 'title' => MODULE_PAYMENT_NOVALNET_TARIFF_PERIOD2_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_TARIFF_PERIOD2_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_SUBSCRIPTION_CANCEL' => array( + 'title' => MODULE_PAYMENT_NOVALNET_SUBSCRIPTION_CANCEL_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_SUBSCRIPTION_CANCEL_DESC, + 'value' => '', + 'set_function' => 'tep_cfg_pull_down_order_statuses(', + 'use_function' => 'tep_get_order_status_name' + ), + 'MODULE_PAYMENT_NOVALNET_DEBUG_MODE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_DEBUG_MODE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_DEBUG_MODE_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_DEBUG_MODE', MODULE_PAYMENT_NOVALNET_DEBUG_MODE,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_TEST_MODE_CALLBACK' => array( + 'title' => MODULE_PAYMENT_NOVALNET_TEST_MODE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_TEST_MODE_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_TEST_MODE_CALLBACK', MODULE_PAYMENT_NOVALNET_TEST_MODE_CALLBACK,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_CALLBACK_MAIL_SEND' => array( + 'title' => MODULE_PAYMENT_NOVALNET_CALLBACK_MAIL_SEND_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_CALLBACK_MAIL_SEND_DESC, + 'value' => 'True', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_CALLBACK_MAIL_SEND', MODULE_PAYMENT_NOVALNET_CALLBACK_MAIL_SEND,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_CALLBACK_MAIL_TO' => array( + 'title' => MODULE_PAYMENT_NOVALNET_CALLBACK_MAIL_TO_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_CALLBACK_MAIL_TO_DESC, + 'value' => STORE_OWNER_EMAIL_ADDRESS, + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_CALLBACK_MAIL_BCC' => array( + 'title' => MODULE_PAYMENT_NOVALNET_CALLBACK_MAIL_BCC_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_CALLBACK_MAIL_BCC_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_CALLBACK_URL' => array( + 'title' => MODULE_PAYMENT_NOVALNET_CALLBACK_URL_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_CALLBACK_URL_DESC, + 'value' => ((($request_type == 'SSL') ? HTTPS_SERVER : HTTP_SERVER) . DIR_WS_CATALOG) . 'callback_novalnet2oscommerce.php', + 'set_function' => '', + 'use_function' => '', + ), + ); + } + + /** + * Get novalnet invoice module configuration keys + * + * @return array + */ + static public function getInvoiceKeys() { + return array( + 'MODULE_PAYMENT_NOVALNET_INVOICE_ENABLE_MODULE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_INVOICE_ENABLE_MODULE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_INVOICE_ENABLE_MODULE_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_INVOICE_ENABLE_MODULE', MODULE_PAYMENT_NOVALNET_INVOICE_ENABLE_MODULE,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_INVOICE_TEST_MODE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_INVOICE_TEST_MODE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_INVOICE_TEST_MODE_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_INVOICE_TEST_MODE', MODULE_PAYMENT_NOVALNET_INVOICE_TEST_MODE,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_INVOICE_ENABLE_FRAUDMODULE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_INVOICE_ENABLE_FRAUDMODULE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_INVOICE_ENABLE_FRAUDMODULE_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('False' => '" . MODULE_PAYMENT_NOVALNET_OPTION_NONE . "','CALLBACK' => '" . MODULE_PAYMENT_NOVALNET_FRAUD_OPTIONCALLBACK . "','SMS' =>'" . MODULE_PAYMENT_NOVALNET_FRAUD_OPTIONSMS . "','EMAIL' =>'" . MODULE_PAYMENT_NOVALNET_FRAUD_OPTIONEMAIL . "'), 'MODULE_PAYMENT_NOVALNET_INVOICE_ENABLE_FRAUDMODULE', MODULE_PAYMENT_NOVALNET_INVOICE_ENABLE_FRAUDMODULE,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_INVOICE_CALLBACK_LIMIT' => array( + 'title' => MODULE_PAYMENT_NOVALNET_INVOICE_CALLBACK_LIMIT_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_INVOICE_CALLBACK_LIMIT_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_INVOICE_DUE_DATE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_INVOICE_DUE_DATE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_INVOICE_DUE_DATE_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_INVOICE_VISIBILITY_BYAMOUNT' => array( + 'title' => MODULE_PAYMENT_NOVALNET_INVOICE_VISIBILITY_BYAMOUNT_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_INVOICE_VISIBILITY_BYAMOUNT_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_INVOICE_ENDCUSTOMER_INFO' => array( + 'title' => MODULE_PAYMENT_NOVALNET_INVOICE_ENDCUSTOMER_INFO_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_INVOICE_ENDCUSTOMER_INFO_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_INVOICE_SORT_ORDER' => array( + 'title' => MODULE_PAYMENT_NOVALNET_INVOICE_SORT_ORDER_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_INVOICE_SORT_ORDER_DESC, + 'value' => '0', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_INVOICE_ORDER_STATUS' => array( + 'title' => MODULE_PAYMENT_NOVALNET_INVOICE_ORDER_STATUS_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_INVOICE_ORDER_STATUS_DESC, + 'value' => '', + 'set_function' => 'tep_cfg_pull_down_order_statuses(', + 'use_function' => 'tep_get_order_status_name' + ), + 'MODULE_PAYMENT_NOVALNET_INVOICE_CALLBACKSCRIPT_ORDER_STATUS' => array( + 'title' => MODULE_PAYMENT_NOVALNET_INVOICE_CALLBACKSCRIPT_ORDER_STATUS_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_INVOICE_CALLBACKSCRIPT_ORDER_STATUS_DESC, + 'value' => '', + 'set_function' => 'tep_cfg_pull_down_order_statuses(', + 'use_function' => 'tep_get_order_status_name' + ), + 'MODULE_PAYMENT_NOVALNET_INVOICE_PAYMENT_ZONE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_INVOICE_PAYMENT_ZONE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_INVOICE_PAYMENT_ZONE_DESC, + 'value' => '', + 'set_function' => 'tep_cfg_pull_down_zone_classes(', + 'use_function' => 'tep_get_zone_class_title' + ), + 'MODULE_PAYMENT_NOVALNET_INVOICE_TRANS_REFERENCE1' => array( + 'title' => MODULE_PAYMENT_NOVALNET_INVOICE_TRANS_REFERENCE1_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_INVOICE_TRANS_REFERENCE1_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_INVOICE_TRANS_REFERENCE2' => array( + 'title' => MODULE_PAYMENT_NOVALNET_INVOICE_TRANS_REFERENCE2_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_INVOICE_TRANS_REFERENCE2_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_INVOICE_PAYMENT_REFERENCE1' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PAYMENT_REFERENCE_1, + 'desc' => '', + 'value' => 'True', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_INVOICE_PAYMENT_REFERENCE1', MODULE_PAYMENT_NOVALNET_INVOICE_PAYMENT_REFERENCE1,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_INVOICE_PAYMENT_REFERENCE2' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PAYMENT_REFERENCE_2, + 'desc' => '', + 'value' => 'True', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_INVOICE_PAYMENT_REFERENCE2', MODULE_PAYMENT_NOVALNET_INVOICE_PAYMENT_REFERENCE2,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_INVOICE_PAYMENT_REFERENCE3' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PAYMENT_REFERENCE_3, + 'desc' => '', + 'value' => 'True', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_INVOICE_PAYMENT_REFERENCE3', MODULE_PAYMENT_NOVALNET_INVOICE_PAYMENT_REFERENCE3,", + 'use_function' => '' + ) + ); + } + + /** + * Get novalnet prepayment module configuration keys + * + * @return array + */ + static public function getPrepaymentKeys() { + return array( + 'MODULE_PAYMENT_NOVALNET_PREPAYMENT_ENABLE_MODULE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PREPAYMENT_ENABLE_MODULE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_PREPAYMENT_ENABLE_MODULE_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_PREPAYMENT_ENABLE_MODULE', MODULE_PAYMENT_NOVALNET_PREPAYMENT_ENABLE_MODULE,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_PREPAYMENT_TEST_MODE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PREPAYMENT_TEST_MODE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_PREPAYMENT_TEST_MODE_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_PREPAYMENT_TEST_MODE', MODULE_PAYMENT_NOVALNET_PREPAYMENT_TEST_MODE,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_PREPAYMENT_VISIBILITY_BYAMOUNT' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PREPAYMENT_VISIBILITY_BYAMOUNT_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_PREPAYMENT_VISIBILITY_BYAMOUNT_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_PREPAYMENT_ENDCUSTOMER_INFO' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PREPAYMENT_ENDCUSTOMER_INFO_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_PREPAYMENT_ENDCUSTOMER_INFO_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_PREPAYMENT_SORT_ORDER' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PREPAYMENT_SORT_ORDER_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_PREPAYMENT_SORT_ORDER_DESC, + 'value' => '0', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_PREPAYMENT_ORDER_STATUS' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PREPAYMENT_ORDER_STATUS_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_PREPAYMENT_ORDER_STATUS_DESC, + 'value' => '', + 'set_function' => 'tep_cfg_pull_down_order_statuses(', + 'use_function' => 'tep_get_order_status_name' + ), + 'MODULE_PAYMENT_NOVALNET_PREPAYMENT_CALLBACKSCRIPT_ORDER_STATUS' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PREPAYMENT_CALLBACKSCRIPT_ORDER_STATUS_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_PREPAYMENT_CALLBACKSCRIPT_ORDER_STATUS_DESC, + 'value' => '', + 'set_function' => 'tep_cfg_pull_down_order_statuses(', + 'use_function' => 'tep_get_order_status_name' + ), + 'MODULE_PAYMENT_NOVALNET_PREPAYMENT_PAYMENT_ZONE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PREPAYMENT_PAYMENT_ZONE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_PREPAYMENT_PAYMENT_ZONE_DESC, + 'value' => '', + 'set_function' => 'tep_cfg_pull_down_zone_classes(', + 'use_function' => 'tep_get_zone_class_title' + ), + 'MODULE_PAYMENT_NOVALNET_PREPAYMENT_TRANS_REFERENCE1' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PREPAYMENT_TRANS_REFERENCE1_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_PREPAYMENT_TRANS_REFERENCE1_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_PREPAYMENT_TRANS_REFERENCE2' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PREPAYMENT_TRANS_REFERENCE2_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_PREPAYMENT_TRANS_REFERENCE2_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_PREPAYMENT_PAYMENT_REFERENCE1' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PAYMENT_REFERENCE_1, + 'desc' => '', + 'value' => 'True', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_PREPAYMENT_PAYMENT_REFERENCE1', MODULE_PAYMENT_NOVALNET_PREPAYMENT_PAYMENT_REFERENCE1,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_PREPAYMENT_PAYMENT_REFERENCE2' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PAYMENT_REFERENCE_2, + 'desc' => '', + 'value' => 'True', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_PREPAYMENT_PAYMENT_REFERENCE2', MODULE_PAYMENT_NOVALNET_PREPAYMENT_PAYMENT_REFERENCE2,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_PREPAYMENT_PAYMENT_REFERENCE3' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PAYMENT_REFERENCE_3, + 'desc' => '', + 'value' => 'True', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_PREPAYMENT_PAYMENT_REFERENCE3', MODULE_PAYMENT_NOVALNET_PREPAYMENT_PAYMENT_REFERENCE3,", + 'use_function' => '' + ) + ); + } + + /** + * Get novalnet credit card module configuration keys + * + * @return array + */ + static public function getCreditCardKeys() { + return array( + 'MODULE_PAYMENT_NOVALNET_CC_ENABLE_MODULE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_CC_ENABLE_MODULE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_CC_ENABLE_MODULE_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_CC_ENABLE_MODULE', MODULE_PAYMENT_NOVALNET_CC_ENABLE_MODULE,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_CC_TEST_MODE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_CC_TEST_MODE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_CC_TEST_MODE_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_CC_TEST_MODE', MODULE_PAYMENT_NOVALNET_CC_TEST_MODE,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_CC_ENABLE_FRAUDMODULE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_CC_ENABLE_FRAUDMODULE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_CC_ENABLE_FRAUDMODULE_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('False' => '" . MODULE_PAYMENT_NOVALNET_OPTION_NONE . "','CALLBACK' => '" . MODULE_PAYMENT_NOVALNET_FRAUD_OPTIONCALLBACK . "','SMS' =>'" . MODULE_PAYMENT_NOVALNET_FRAUD_OPTIONSMS . "','EMAIL' =>'" . MODULE_PAYMENT_NOVALNET_FRAUD_OPTIONEMAIL . "'), 'MODULE_PAYMENT_NOVALNET_CC_ENABLE_FRAUDMODULE', MODULE_PAYMENT_NOVALNET_CC_ENABLE_FRAUDMODULE,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_CC_CALLBACK_LIMIT' => array( + 'title' => MODULE_PAYMENT_NOVALNET_CC_CALLBACK_LIMIT_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_CC_CALLBACK_LIMIT_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_CC_3D_SECURE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_CC_3D_SECURE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_CC_3D_SECURE_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_CC_3D_SECURE', MODULE_PAYMENT_NOVALNET_CC_3D_SECURE,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_CC_AMEX_ACCEPT' => array( + 'title' => MODULE_PAYMENT_NOVALNET_CC_AMEX_ACCEPT_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_CC_AMEX_ACCEPT_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_CC_AMEX_ACCEPT', MODULE_PAYMENT_NOVALNET_CC_AMEX_ACCEPT,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_CC_MAESTRO_ACCEPT' => array( + 'title' => MODULE_PAYMENT_NOVALNET_CC_MAESTRO_ACCEPT_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_CC_MAESTRO_ACCEPT_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_CC_MAESTRO_ACCEPT', MODULE_PAYMENT_NOVALNET_CC_MAESTRO_ACCEPT,", + 'use_function' => '', + ), + 'MODULE_PAYMENT_NOVALNET_CC_CARTASI_ACCEPT' => array( + 'title' => MODULE_PAYMENT_NOVALNET_CC_CARTASI_ACCEPT_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_CC_CARTASI_ACCEPT_DESC, + 'value' => 'False', + 'set_function' =>"tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_CC_CARTASI_ACCEPT', MODULE_PAYMENT_NOVALNET_CC_CARTASI_ACCEPT,", + 'use_function' => '', + ), + 'MODULE_PAYMENT_NOVALNET_CC_SHOP_TYPE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_CC_SHOP_TYPE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_CC_SHOP_TYPE_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('False' => '" . MODULE_PAYMENT_NOVALNET_OPTION_NONE . "','ONECLICK' => '" . MODULE_PAYMENT_NOVALNET_ONE_CLICK . "','ZEROAMOUNT' => '" .MODULE_PAYMENT_NOVALNET_ZERO_AMOUNT. "'), 'MODULE_PAYMENT_NOVALNET_CC_SHOP_TYPE', MODULE_PAYMENT_NOVALNET_CC_SHOP_TYPE,", + 'use_function' => '', + ), + 'MODULE_PAYMENT_NOVALNET_CC_CVC_ON_ONE_CLICK_ACCEPT' => array( + 'title' => MODULE_PAYMENT_NOVALNET_CC_CVC_ON_ONE_CLICK_ACCEPT_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_CC_CVC_ON_ONE_CLICK_ACCEPT_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_CC_CVC_ON_ONE_CLICK_ACCEPT', MODULE_PAYMENT_NOVALNET_CC_CVC_ON_ONE_CLICK_ACCEPT,", + 'use_function' => '', + ), + 'MODULE_PAYMENT_NOVALNET_CC_FORM_TYPE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_CC_FORM_TYPE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_CC_FORM_TYPE_DESC, + 'value' => 'Local', + 'set_function' => "tep_mod_select_option(array('Local' => '" . MODULE_PAYMENT_NOVALNET_FORM_LOCAL . "', 'Iframe' => '" . MODULE_PAYMENT_NOVALNET_FORM_IFRAME . "', 'Redirect' => '" . MODULE_PAYMENT_NOVALNET_FORM_REDIRECT ."'), 'MODULE_PAYMENT_NOVALNET_CC_FORM_TYPE', MODULE_PAYMENT_NOVALNET_CC_FORM_TYPE,", + 'use_function' => '', + ), + 'MODULE_PAYMENT_NOVALNET_CC_FORM_VALIDYEAR_LIMIT' => array( + 'title' => MODULE_PAYMENT_NOVALNET_CC_FORM_VALIDYEAR_LIMIT_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_CC_FORM_VALIDYEAR_LIMIT_DESC, + 'value' => '25', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_CC_VISIBILITY_BYAMOUNT' => array( + 'title' => MODULE_PAYMENT_NOVALNET_CC_VISIBILITY_BYAMOUNT_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_CC_VISIBILITY_BYAMOUNT_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '', + ), + 'MODULE_PAYMENT_NOVALNET_CC_ENDCUSTOMER_INFO' => array( + 'title' => MODULE_PAYMENT_NOVALNET_CC_ENDCUSTOMER_INFO_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_CC_ENDCUSTOMER_INFO_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_CC_SORT_ORDER' => array( + 'title' => MODULE_PAYMENT_NOVALNET_CC_SORT_ORDER_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_CC_SORT_ORDER_DESC, + 'value' => '0', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_CC_ORDER_STATUS' => array( + 'title' => MODULE_PAYMENT_NOVALNET_CC_ORDER_STATUS_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_CC_ORDER_STATUS_DESC, + 'value' => '', + 'set_function' => 'tep_cfg_pull_down_order_statuses(', + 'use_function' => 'tep_get_order_status_name' + ), + 'MODULE_PAYMENT_NOVALNET_CC_PAYMENT_ZONE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_CC_PAYMENT_ZONE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_CC_PAYMENT_ZONE_DESC, + 'value' => '', + 'set_function' => 'tep_cfg_pull_down_zone_classes(', + 'use_function' => 'tep_get_zone_class_title' + ), + 'MODULE_PAYMENT_NOVALNET_CC_TRANS_REFERENCE1' => array( + 'title' => MODULE_PAYMENT_NOVALNET_CC_TRANS_REFERENCE1_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_CC_TRANS_REFERENCE1_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_CC_TRANS_REFERENCE2' => array( + 'title' => MODULE_PAYMENT_NOVALNET_CC_TRANS_REFERENCE2_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_CC_TRANS_REFERENCE2_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ) + ); + } + + /** + * Get novalnet sepa module configuration keys + * + * @return array + */ + static public function getDirectDebitSEPAKeys() { + return array( + 'MODULE_PAYMENT_NOVALNET_SEPA_ENABLE_MODULE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_SEPA_ENABLE_MODULE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_SEPA_ENABLE_MODULE_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_SEPA_ENABLE_MODULE', MODULE_PAYMENT_NOVALNET_SEPA_ENABLE_MODULE,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_SEPA_TEST_MODE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_SEPA_TEST_MODE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_SEPA_TEST_MODE_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_SEPA_TEST_MODE', MODULE_PAYMENT_NOVALNET_SEPA_TEST_MODE,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_SEPA_ENABLE_FRAUDMODULE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_SEPA_ENABLE_FRAUDMODULE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_SEPA_ENABLE_FRAUDMODULE_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('False' => '" . MODULE_PAYMENT_NOVALNET_OPTION_NONE . "','CALLBACK' => '" . MODULE_PAYMENT_NOVALNET_FRAUD_OPTIONCALLBACK . "','SMS' =>'" . MODULE_PAYMENT_NOVALNET_FRAUD_OPTIONSMS . "','EMAIL' =>'" . MODULE_PAYMENT_NOVALNET_FRAUD_OPTIONEMAIL . "'), 'MODULE_PAYMENT_NOVALNET_SEPA_ENABLE_FRAUDMODULE', MODULE_PAYMENT_NOVALNET_SEPA_ENABLE_FRAUDMODULE,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_SEPA_CALLBACK_LIMIT' => array( + 'title' => MODULE_PAYMENT_NOVALNET_SEPA_CALLBACK_LIMIT_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_SEPA_CALLBACK_LIMIT_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_SEPA_DUE_DATE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_SEPA_DUE_DATE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_SEPA_DUE_DATE_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_REFILL_BY_SUCCESSFUL_ORDER' => array( + 'title' => MODULE_PAYMENT_NOVALNET_REFILL_BY_SUCCESSFUL_ORDER_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_REFILL_BY_SUCCESSFUL_ORDER_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_REFILL_BY_SUCCESSFUL_ORDER', MODULE_PAYMENT_NOVALNET_REFILL_BY_SUCCESSFUL_ORDER,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_SEPA_SHOP_TYPE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_SEPA_SHOP_TYPE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_SEPA_SHOP_TYPE_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('False' => '" . MODULE_PAYMENT_NOVALNET_OPTION_NONE . "','ONECLICK' => '" . MODULE_PAYMENT_NOVALNET_ONE_CLICK . "','ZEROAMOUNT' => '" .MODULE_PAYMENT_NOVALNET_ZERO_AMOUNT. "'), 'MODULE_PAYMENT_NOVALNET_SEPA_SHOP_TYPE', MODULE_PAYMENT_NOVALNET_SEPA_SHOP_TYPE,", + 'use_function' => '', + ), + 'MODULE_PAYMENT_NOVALNET_SEPA_FORM_TYPE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_SEPA_FORM_TYPE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_SEPA_FORM_TYPE_DESC, + 'value' => 'Local', + 'set_function' => "tep_mod_select_option(array('Local' => '" . MODULE_PAYMENT_NOVALNET_FORM_LOCAL . "', 'Iframe' => '" . MODULE_PAYMENT_NOVALNET_FORM_IFRAME . "'), 'MODULE_PAYMENT_NOVALNET_SEPA_FORM_TYPE', MODULE_PAYMENT_NOVALNET_SEPA_FORM_TYPE,", + 'use_function' => '', + ), + 'MODULE_PAYMENT_NOVALNET_SEPA_VISIBILITY_BYAMOUNT' => array( + 'title' => MODULE_PAYMENT_NOVALNET_SEPA_VISIBILITY_BYAMOUNT_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_SEPA_VISIBILITY_BYAMOUNT_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_SEPA_ENDCUSTOMER_INFO' => array( + 'title' => MODULE_PAYMENT_NOVALNET_SEPA_ENDCUSTOMER_INFO_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_SEPA_ENDCUSTOMER_INFO_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_SEPA_SORT_ORDER' => array( + 'title' => MODULE_PAYMENT_NOVALNET_SEPA_SORT_ORDER_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_SEPA_SORT_ORDER_DESC, + 'value' => '0', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_SEPA_ORDER_STATUS' => array( + 'title' => MODULE_PAYMENT_NOVALNET_SEPA_ORDER_STATUS_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_SEPA_ORDER_STATUS_DESC, + 'value' => '', + 'set_function' => 'tep_cfg_pull_down_order_statuses(', + 'use_function' => 'tep_get_order_status_name' + ), + 'MODULE_PAYMENT_NOVALNET_SEPA_PAYMENT_ZONE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_SEPA_PAYMENT_ZONE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_SEPA_PAYMENT_ZONE_DESC, + 'value' => '', + 'set_function' => 'tep_cfg_pull_down_zone_classes(', + 'use_function' => 'tep_get_zone_class_title' + ), + 'MODULE_PAYMENT_NOVALNET_SEPA_TRANS_REFERENCE1' => array( + 'title' => MODULE_PAYMENT_NOVALNET_SEPA_TRANS_REFERENCE1_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_SEPA_TRANS_REFERENCE1_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_SEPA_TRANS_REFERENCE2' => array( + 'title' => MODULE_PAYMENT_NOVALNET_SEPA_TRANS_REFERENCE2_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_SEPA_TRANS_REFERENCE2_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ) + ); + } + + /** + * Get novalnet sofort bank module configuration keys + * + * @return array + */ + static public function getSofortBankKeys() { + return array( + 'MODULE_PAYMENT_NOVALNET_SOFORTBANK_ENABLE_MODULE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_SOFORTBANK_ENABLE_MODULE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_SOFORTBANK_ENABLE_MODULE_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_SOFORTBANK_ENABLE_MODULE', MODULE_PAYMENT_NOVALNET_SOFORTBANK_ENABLE_MODULE,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_SOFORTBANK_TEST_MODE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_SOFORTBANK_TEST_MODE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_SOFORTBANK_TEST_MODE_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_SOFORTBANK_TEST_MODE', MODULE_PAYMENT_NOVALNET_SOFORTBANK_TEST_MODE,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_SOFORTBANK_VISIBILITY_BYAMOUNT' => array( + 'title' => MODULE_PAYMENT_NOVALNET_SOFORTBANK_VISIBILITY_BYAMOUNT_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_SOFORTBANK_VISIBILITY_BYAMOUNT_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_SOFORTBANK_ENDCUSTOMER_INFO' => array( + 'title' => MODULE_PAYMENT_NOVALNET_SOFORTBANK_ENDCUSTOMER_INFO_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_SOFORTBANK_ENDCUSTOMER_INFO_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_SOFORTBANK_SORT_ORDER' => array( + 'title' => MODULE_PAYMENT_NOVALNET_SOFORTBANK_SORT_ORDER_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_SOFORTBANK_SORT_ORDER_DESC, + 'value' => '0', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_SOFORTBANK_ORDER_STATUS' => array( + 'title' => MODULE_PAYMENT_NOVALNET_SOFORTBANK_ORDER_STATUS_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_SOFORTBANK_ORDER_STATUS_DESC, + 'value' => '', + 'set_function' => 'tep_cfg_pull_down_order_statuses(', + 'use_function' => 'tep_get_order_status_name' + ), + 'MODULE_PAYMENT_NOVALNET_SOFORTBANK_PAYMENT_ZONE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_SOFORTBANK_PAYMENT_ZONE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_SOFORTBANK_PAYMENT_ZONE_DESC, + 'value' => '', + 'set_function' => 'tep_cfg_pull_down_zone_classes(', + 'use_function' => 'tep_get_zone_class_title' + ), + 'MODULE_PAYMENT_NOVALNET_SOFORTBANK_TRANS_REFERENCE1' => array( + 'title' => MODULE_PAYMENT_NOVALNET_SOFORTBANK_TRANS_REFERENCE1_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_SOFORTBANK_TRANS_REFERENCE1_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_SOFORTBANK_TRANS_REFERENCE2' => array( + 'title' => MODULE_PAYMENT_NOVALNET_SOFORTBANK_TRANS_REFERENCE2_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_SOFORTBANK_TRANS_REFERENCE2_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ) + ); + } + + /** + * Get novalnet iDEAL module configuration keys + * + * @return array + */ + static public function getIdealKeys() { + return array( + 'MODULE_PAYMENT_NOVALNET_IDEAL_ENABLE_MODULE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_IDEAL_ENABLE_MODULE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_IDEAL_ENABLE_MODULE_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_IDEAL_ENABLE_MODULE', MODULE_PAYMENT_NOVALNET_IDEAL_ENABLE_MODULE,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_IDEAL_TEST_MODE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_IDEAL_TEST_MODE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_IDEAL_TEST_MODE_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_IDEAL_TEST_MODE', MODULE_PAYMENT_NOVALNET_IDEAL_TEST_MODE,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_IDEAL_VISIBILITY_BYAMOUNT' => array( + 'title' => MODULE_PAYMENT_NOVALNET_IDEAL_VISIBILITY_BYAMOUNT_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_IDEAL_VISIBILITY_BYAMOUNT_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_IDEAL_ENDCUSTOMER_INFO' => array( + 'title' => MODULE_PAYMENT_NOVALNET_IDEAL_ENDCUSTOMER_INFO_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_IDEAL_ENDCUSTOMER_INFO_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_IDEAL_SORT_ORDER' => array( + 'title' => MODULE_PAYMENT_NOVALNET_IDEAL_SORT_ORDER_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_IDEAL_SORT_ORDER_DESC, + 'value' => '0', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_IDEAL_ORDER_STATUS' => array( + 'title' => MODULE_PAYMENT_NOVALNET_IDEAL_ORDER_STATUS_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_IDEAL_ORDER_STATUS_DESC, + 'value' => '', + 'set_function' => 'tep_cfg_pull_down_order_statuses(', + 'use_function' => 'tep_get_order_status_name' + ), + 'MODULE_PAYMENT_NOVALNET_IDEAL_PAYMENT_ZONE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_IDEAL_PAYMENT_ZONE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_IDEAL_PAYMENT_ZONE_DESC, + 'value' => '', + 'set_function' => 'tep_cfg_pull_down_zone_classes(', + 'use_function' => 'tep_get_zone_class_title' + ), + 'MODULE_PAYMENT_NOVALNET_IDEAL_TRANS_REFERENCE1' => array( + 'title' => MODULE_PAYMENT_NOVALNET_IDEAL_TRANS_REFERENCE1_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_IDEAL_TRANS_REFERENCE1_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_IDEAL_TRANS_REFERENCE2' => array( + 'title' => MODULE_PAYMENT_NOVALNET_IDEAL_TRANS_REFERENCE2_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_IDEAL_TRANS_REFERENCE2_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ) + ); + } + + /** + * Get novalnet paypal module configuration keys + * + * @return array + */ + static public function getPayPalKeys() { + return array( + 'MODULE_PAYMENT_NOVALNET_PAYPAL_ENABLE_MODULE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PAYPAL_ENABLE_MODULE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_PAYPAL_ENABLE_MODULE_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_PAYPAL_ENABLE_MODULE', MODULE_PAYMENT_NOVALNET_PAYPAL_ENABLE_MODULE,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_PAYPAL_TEST_MODE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PAYPAL_TEST_MODE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_PAYPAL_TEST_MODE_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_PAYPAL_TEST_MODE', MODULE_PAYMENT_NOVALNET_PAYPAL_TEST_MODE,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_PAYPAL_VISIBILITY_BYAMOUNT' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PAYPAL_VISIBILITY_BYAMOUNT_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_PAYPAL_VISIBILITY_BYAMOUNT_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_PAYPAL_ENDCUSTOMER_INFO' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PAYPAL_ENDCUSTOMER_INFO_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_PAYPAL_ENDCUSTOMER_INFO_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_PAYPAL_SORT_ORDER' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PAYPAL_SORT_ORDER_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_PAYPAL_SORT_ORDER_DESC, + 'value' => '0', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_PAYPAL_PAYPENDING_ORDER_STATUS' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PAYPAL_PAYPENDING_ORDER_STATUS_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_PAYPAL_PAYPENDING_ORDER_STATUS_DESC, + 'value' => '', + 'set_function' => 'tep_cfg_pull_down_order_statuses(', + 'use_function' => 'tep_get_order_status_name' + ), + 'MODULE_PAYMENT_NOVALNET_PAYPAL_ORDER_STATUS' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PAYPAL_ORDER_STATUS_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_PAYPAL_ORDER_STATUS_DESC, + 'value' => '', + 'set_function' => 'tep_cfg_pull_down_order_statuses(', + 'use_function' => 'tep_get_order_status_name' + ), + 'MODULE_PAYMENT_NOVALNET_PAYPAL_PAYMENT_ZONE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PAYPAL_PAYMENT_ZONE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_PAYPAL_PAYMENT_ZONE_DESC, + 'value' => '', + 'set_function' => 'tep_cfg_pull_down_zone_classes(', + 'use_function' => 'tep_get_zone_class_title' + ), + 'MODULE_PAYMENT_NOVALNET_PAYPAL_TRANS_REFERENCE1' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PAYPAL_TRANS_REFERENCE1_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_PAYPAL_TRANS_REFERENCE1_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_PAYPAL_TRANS_REFERENCE2' => array( + 'title' => MODULE_PAYMENT_NOVALNET_PAYPAL_TRANS_REFERENCE2_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_PAYPAL_TRANS_REFERENCE2_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ) + ); + } + + /** + * Get novalnet eps module configuration keys + * + * @return array + */ + static public function getEPSKeys() { + return array( + 'MODULE_PAYMENT_NOVALNET_EPS_ENABLE_MODULE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_EPS_ENABLE_MODULE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_EPS_ENABLE_MODULE_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_EPS_ENABLE_MODULE', MODULE_PAYMENT_NOVALNET_EPS_ENABLE_MODULE,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_EPS_TEST_MODE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_EPS_TEST_MODE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_EPS_TEST_MODE_DESC, + 'value' => 'False', + 'set_function' => "tep_mod_select_option(array('True' => '" . MODULE_PAYMENT_NOVALNET_TRUE . "','False' => '" . MODULE_PAYMENT_NOVALNET_FALSE . "'), 'MODULE_PAYMENT_NOVALNET_EPS_TEST_MODE', MODULE_PAYMENT_NOVALNET_EPS_TEST_MODE,", + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_EPS_VISIBILITY_BYAMOUNT' => array( + 'title' => MODULE_PAYMENT_NOVALNET_EPS_VISIBILITY_BYAMOUNT_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_EPS_VISIBILITY_BYAMOUNT_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_EPS_ENDCUSTOMER_INFO' => array( + 'title' => MODULE_PAYMENT_NOVALNET_EPS_ENDCUSTOMER_INFO_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_EPS_ENDCUSTOMER_INFO_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_EPS_SORT_ORDER' => array( + 'title' => MODULE_PAYMENT_NOVALNET_EPS_SORT_ORDER_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_EPS_SORT_ORDER_DESC, + 'value' => '0', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_EPS_ORDER_STATUS' => array( + 'title' => MODULE_PAYMENT_NOVALNET_EPS_ORDER_STATUS_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_EPS_ORDER_STATUS_DESC, + 'value' => '', + 'set_function' => 'tep_cfg_pull_down_order_statuses(', + 'use_function' => 'tep_get_order_status_name' + ), + 'MODULE_PAYMENT_NOVALNET_EPS_PAYMENT_ZONE' => array( + 'title' => MODULE_PAYMENT_NOVALNET_EPS_PAYMENT_ZONE_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_EPS_PAYMENT_ZONE_DESC, + 'value' => '', + 'set_function' => 'tep_cfg_pull_down_zone_classes(', + 'use_function' => 'tep_get_zone_class_title' + ), + 'MODULE_PAYMENT_NOVALNET_EPS_TRANS_REFERENCE1' => array( + 'title' => MODULE_PAYMENT_NOVALNET_EPS_TRANS_REFERENCE1_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_EPS_TRANS_REFERENCE1_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ), + 'MODULE_PAYMENT_NOVALNET_EPS_TRANS_REFERENCE2' => array( + 'title' => MODULE_PAYMENT_NOVALNET_EPS_TRANS_REFERENCE2_TITLE, + 'desc' => MODULE_PAYMENT_NOVALNET_EPS_TRANS_REFERENCE2_DESC, + 'value' => '', + 'set_function' => '', + 'use_function' => '' + ) + ); + } +} +?> diff --git a/includes/classes/novalnet/class.NovalnetTranslator.php b/includes/classes/novalnet/class.NovalnetTranslator.php new file mode 100644 index 0000000..282fe58 --- /dev/null +++ b/includes/classes/novalnet/class.NovalnetTranslator.php @@ -0,0 +1,96 @@ + $lval) { + defined($lkey) || define($lkey, utf8_decode($lval)); + } + } + } + + /** + * Load the language contents from the novalnet package language file (classes directory) + * @param $langID + * + * @return array + */ + static public function loadLocaleContents($langID = 'english') { + $lang_file = DIR_FS_CATALOG . 'includes/classes/novalnet/languages/'.strtolower($langID).'.php'; + if (!file_exists($lang_file)) { + $lang_file = DIR_FS_CATALOG . 'includes/classes/novalnet/languages/english.php'; // Default language file + } + require($lang_file); + return $localeValues; + } + + /** + * Set language constant mapping to avoid multiple entries in language file + * @param $input_lang + * + * @return array + */ + static public function mapConstantValues($input_lang = array()) { + if (!empty($input_lang)) { + $enabled_payment_modules = array('CC','SEPA','SOFORTBANK','PAYPAL','IDEAL','INVOICE','PREPAYMENT','EPS'); + $common_lang_key_for_map = array( + 'MODULE_PAYMENT_NOVALNET_ENABLE_MODULE_TITLE', + 'MODULE_PAYMENT_NOVALNET_ENABLE_MODULE_DESC', + 'MODULE_PAYMENT_NOVALNET_TEST_MODE_TITLE', + 'MODULE_PAYMENT_NOVALNET_TEST_MODE_DESC', + 'MODULE_PAYMENT_NOVALNET_MANUAL_CHECK_LIMIT_TITLE', + 'MODULE_PAYMENT_NOVALNET_MANUAL_CHECK_LIMIT_DESC', + 'MODULE_PAYMENT_NOVALNET_VISIBILITY_BYAMOUNT_TITLE', + 'MODULE_PAYMENT_NOVALNET_VISIBILITY_BYAMOUNT_DESC', + 'MODULE_PAYMENT_NOVALNET_ENDCUSTOMER_INFO_TITLE', + 'MODULE_PAYMENT_NOVALNET_ENDCUSTOMER_INFO_DESC', + 'MODULE_PAYMENT_NOVALNET_SORT_ORDER_TITLE', + 'MODULE_PAYMENT_NOVALNET_SORT_ORDER_DESC', + 'MODULE_PAYMENT_NOVALNET_ORDER_STATUS_TITLE', + 'MODULE_PAYMENT_NOVALNET_ORDER_STATUS_DESC', + 'MODULE_PAYMENT_NOVALNET_PAYMENT_ZONE_TITLE', + 'MODULE_PAYMENT_NOVALNET_PAYMENT_ZONE_DESC', + 'MODULE_PAYMENT_NOVALNET_TRANS_REFERENCE1_TITLE', + 'MODULE_PAYMENT_NOVALNET_TRANS_REFERENCE1_DESC', + 'MODULE_PAYMENT_NOVALNET_TRANS_REFERENCE2_TITLE', + 'MODULE_PAYMENT_NOVALNET_TRANS_REFERENCE2_DESC' + ); + foreach ($enabled_payment_modules as $pkey => $pval) { + foreach ($common_lang_key_for_map as $lkey => $lval) { + $original_lang_key = $lval; + $split_target_key = explode('MODULE_PAYMENT_NOVALNET', $original_lang_key); + $target_lang_key = 'MODULE_PAYMENT_NOVALNET_'.$pval.$split_target_key[1]; + if (isset($input_lang[$original_lang_key]) && !isset($input_lang[$target_lang_key])) { + $input_lang[$target_lang_key] = $input_lang[$original_lang_key]; + } + } + } + } + return $input_lang; + } +} +?> diff --git a/includes/classes/novalnet/class.NovalnetValidation.php b/includes/classes/novalnet/class.NovalnetValidation.php new file mode 100644 index 0000000..796a173 --- /dev/null +++ b/includes/classes/novalnet/class.NovalnetValidation.php @@ -0,0 +1,349 @@ +Novalnet'.$error_payment.'

'.($other_error != '' ? $other_error : MODULE_PAYMENT_NOVALNET_VALID_MERCHANT_CREDENTIALS_ERROR).''; + } + + /* + * Validate the Merchant API configuration and display the error/warning message + * + * return boolean + */ + static public function merchantValidate() { + $merchant_api_error = false; + $pattern = "/^\d+\|\d+\|[\w-]+\|\w+\|\w+\|(|\d+)\|(|\d+)\|(|\d+)\|(|\d+)\|(|\w+)\|(|\w+)$/"; + $value = parent::getVendorID(true) . '|' . parent::getProductID(true) . '|' . parent::getTariffID(true) . '|' . parent::getVendorAuthCode() . '|' . parent::getPaymentAccessKey() . '|' . parent::getManualCheckLimit(true) . '|' . parent::getReferrerID(true) . '|' . parent::getGatewayTimeout(true) . '|' . parent::getTariffPeriod2Amount() . '|' . parent::getTariffPeriod2() . '|' . parent::getTariffPeriod(); + preg_match($pattern, $value, $match); + if(empty($match[0])) { + $merchant_api_error = true; + } elseif ( parent::getTariffPeriod2Amount() != '' && !is_numeric(parent::getTariffPeriod2Amount()) ) { + $merchant_api_error = true; + } elseif ( parent::getTariffPeriod2Amount() != '' && is_numeric(parent::getTariffPeriod2Amount()) && parent::getTariffPeriod2() == '' ) { + $merchant_api_error = true; + } elseif ( ( parent::getTariffPeriod2Amount() == '' || !is_numeric(parent::getTariffPeriod2Amount()) ) && parent::getTariffPeriod2() != '' ) { + $merchant_api_error = true; + } elseif (self::getCallbackNotifyMail(true) != '' || self::getCallbackNotifyMailBCC(true) != '') { + $email = explode(',', self::getCallbackNotifyMail(true) . ',' . self::getCallbackNotifyMailBCC(true)); + foreach($email as $value) { + if (trim($value) != '' && !parent::isValidEmailFormat($value)) { + $merchant_api_error = true; + } + } + } + return $merchant_api_error; + } + + /** + * Validate input form parameters based on payment types + * @param $fraud_module + * @param $fraud_module_status + * @param $payment_module + * @param $datas + * + * @return none + */ + static public function validateUserInputs($fraud_module, $fraud_module_status, $payment_module = '', $datas = array()) { + $datas = array_map('trim', $datas); + if ( !empty($payment_module) && !empty($datas) ) { + $error_found = 0; + $error_message = ''; + switch ($payment_module) { + case 'novalnet_cc': + if ( !empty($datas['nn_cc_js_enabled']) ) { + $error_found = 1; + $error_message = MODULE_PAYMENT_NOVALNET_JS_DEACTIVATE_PROBLEM; + } + if ( !$error_found && ( empty($datas['novalnet_cc_cvc']) || empty($datas['nn_cc_hash']) || empty($datas['nn_cc_uniqueid']) ) ) { + $error_found = 1; + $error_message = MODULE_PAYMENT_NOVALNET_VALID_CC_DETAILS; + } + if ( !$error_found && $fraud_module && $fraud_module_status ) { + list ($error_found, $error_message) = self::validateCallbackFields($datas, $fraud_module, $payment_module); + } + break; + case 'novalnet_sepa': + if ( !empty($datas['nn_sepa_js_enabled']) ) { + $error_found = 1; + $error_message = MODULE_PAYMENT_NOVALNET_JS_DEACTIVATE_PROBLEM; + } + if ( !$error_found && ( empty($datas['novalnet_sepa_account_holder']) || empty($datas['nn_sepa_hash']) || empty($datas['nn_sepa_uniqueid']) ) ) { + $error_found = 1; + $error_message = MODULE_PAYMENT_NOVALNET_VALID_ACCOUNT_DETAILS; + } + if ( !$error_found && $fraud_module && $fraud_module_status ) { + list ($error_found, $error_message) = self::validateCallbackFields($datas, $fraud_module, $payment_module); + } + break; + case 'novalnet_invoice': + if ( !$error_found && $fraud_module && $fraud_module_status ) { + list ($error_found, $error_message) = self::validateCallbackFields($datas, $fraud_module, $payment_module); + } + break; + } + if(isset($_SESSION['novalnet'])) { unset($_SESSION['novalnet']); }// Unset existing novalnet values + if (MODULE_PAYMENT_NOVALNET_AUTO_REFILL == 'True') { // For refilling purpose + $_SESSION['novalnet'][$payment_module] = $datas; + } + if ($error_found == 1) { + if ($error_message == '') { + $error_message = MODULE_PAYMENT_NOVALNET_TRANSACTION_ERROR; + } + $payment_error_return = 'payment_error='. $payment_module .'&error=' . NovalnetInterface::setUTFText($error_message); + tep_redirect(html_entity_decode(tep_href_link(FILENAME_CHECKOUT_PAYMENT, $payment_error_return, 'SSL', true, false))); + } + } + } + + /** + * Validate input form callback parameters + * @param $datas + * @param $fraud_module + * @param $code + * + * @return array + */ + static public function validateCallbackFields ($datas, $fraud_module, $code) { + if ( $fraud_module == 'CALLBACK' && ( empty($datas[$code . '_fraud_tel']) || !is_numeric($datas[$code . '_fraud_tel']) ) ) { + return array ('1', MODULE_PAYMENT_NOVALNET_FRAUDMODULE_TELEPHONE_ERROR); + } elseif ( $fraud_module == 'EMAIL' && ( empty($datas[$code . '_fraud_email']) || empty($datas[$code . '_fraud_email']) || !parent::isValidEmailFormat($datas[$code . '_fraud_email']) ) ) { + return array ('1', MODULE_PAYMENT_NOVALNET_FRAUDMODULE_EMAIL_ERROR); + } elseif ( $fraud_module == 'SMS' && (empty($datas[$code . '_fraud_mobile']) || !is_numeric($datas[$code . '_fraud_mobile'])|| strlen($datas[$code . '_fraud_mobile']) < 8) ) { + return array ('1', MODULE_PAYMENT_NOVALNET_FRAUDMODULE_MOBILE_ERROR); + } + return array ('0', ''); + } + + /** + * Validate callback country and customer's country + * + * @return boolean + */ + static public function validateCallbackCountry() { + global $order; + $customer_iso_code = strtoupper($order->customer['country']['iso_code_2']); + return ($customer_iso_code && in_array($customer_iso_code, parent::getCallbackCountries())); + } + + /** + * Validate users input for callback + * @param $fraud_module + * @param $payment_module + * @param $datas + * + * @return none + */ + static public function validateUserInputsOnCallback($fraud_module, $payment_module = '', $datas = array()) { + $error_message = ''; + $datas = array_map('trim', $datas); + if ( ($payment_module == 'novalnet_cc' && !empty($datas['nn_cc_js_enabled'])) || ($payment_module == 'novalnet_sepa' && !empty($datas['nn_sepa_js_enabled'])) ) { + $error_message = MODULE_PAYMENT_NOVALNET_JS_DEACTIVATE_PROBLEM; + } + elseif ( in_array($fraud_module, array('CALLBACK', 'SMS')) ) { + if ( !isset($datas[$payment_module . '_new_pin']) && isset($datas[$payment_module . '_fraud_pin']) && ( empty($datas[$payment_module . '_fraud_pin']) || !preg_match('/^[a-zA-Z0-9]+$/', $datas[$payment_module . '_fraud_pin']) ) ) { + $error_message = MODULE_PAYMENT_NOVALNET_FRAUDMODULE_PIN_NOTVALID; + } else { + $_SESSION['novalnet'][$payment_module][$payment_module .'_new_pin'] = !isset($datas[$payment_module . '_new_pin']) ? 0 : ''; + } + } + if (!empty($error_message)) { + $payment_error_return = 'payment_error='. $payment_module .'&error=' . NovalnetInterface::setUTFText($error_message); + tep_redirect(html_entity_decode(tep_href_link(FILENAME_CHECKOUT_PAYMENT, $payment_error_return, 'SSL', true, false))); + } + } + + /** + * Validate amount for callback + * @param $payment_module + * @param $fraud_module + * + * @return none + */ + static public function validateAmountOnCallback($payment_module = '',$fraud_module='') { + global $order; + $error_message = ''; + if ($_SESSION['novalnet'][$payment_module]['order_amount'] != NovalnetInterface::getPaymentAmount((array)$order, $payment_module)) { + unset($_SESSION['novalnet'][$payment_module]); + $error_message = MODULE_PAYMENT_NOVALNET_FRAUDMODULE_AMOUNT_CHANGE_ERROR; + } + if (!empty($error_message)) { + $payment_error_return = 'payment_error='. $payment_module .'&error=' . NovalnetInterface::setUTFText($error_message); + tep_redirect(html_entity_decode(tep_href_link(FILENAME_CHECKOUT_PAYMENT, $payment_error_return, 'SSL', true, false))); + } + } + + /** + * Validate response of callback + * @param $response + * @param $request_type + * + * @return none + */ + static public function validateNewPinResponse($response, $request_type, $code) { + list($status, $statusMessage) = NovalnetInterface::getStatusFromXmlResponse($response); + if ( $request_type == 'TRANSMIT_PIN_AGAIN' && $status != 100 ) { + $payment_error_return = 'payment_error='. $code .'&error=' . $statusMessage; + tep_redirect(html_entity_decode(tep_href_link(FILENAME_CHECKOUT_PAYMENT, $payment_error_return, 'SSL', true, false))); + } + } + + /** + * Return JS script to disable confirm button + * + * @return string + */ + static public function confirmButtonDisableActivate() { + return ''; + } +} diff --git a/includes/classes/novalnet/css/loader.css b/includes/classes/novalnet/css/loader.css new file mode 100644 index 0000000..251eaa8 --- /dev/null +++ b/includes/classes/novalnet/css/loader.css @@ -0,0 +1,9 @@ +.loader { + position: fixed; + left: 0px; + top: 0px; + width: 100%; + height: 100%; + z-index: 9999; + background: url('../img/loader.gif') 50% 50% no-repeat; +} diff --git a/includes/classes/novalnet/db.sql b/includes/classes/novalnet/db.sql new file mode 100644 index 0000000..8f4ba6b --- /dev/null +++ b/includes/classes/novalnet/db.sql @@ -0,0 +1,120 @@ +CREATE TABLE IF NOT EXISTS `novalnet_callback_history` ( + `id` int NOT NULL AUTO_INCREMENT COMMENT 'Auto Increment ID', + `date` datetime NOT NULL COMMENT 'Callback DATE TIME', + `payment_type` varchar(100) NOT NULL COMMENT 'Callback Payment Type', + `status` varchar(20) DEFAULT NULL COMMENT 'Callback Status', + `callback_tid` bigint(20) unsigned NOT NULL COMMENT 'Callback Reference ID', + `org_tid` bigint(20) unsigned DEFAULT NULL COMMENT 'Original Transaction ID', + `amount` int(11) DEFAULT NULL COMMENT 'Amount in cents', + `currency` varchar(5) DEFAULT NULL COMMENT 'Currency', + `product_id` int(11) unsigned DEFAULT NULL COMMENT 'Callback Product ID', + `order_no` int(11) unsigned NOT NULL COMMENT 'Order ID from shop', + PRIMARY KEY (`id`), + KEY `order_no` (`order_no`) +) COMMENT='Novalnet Callback History'; + +CREATE TABLE IF NOT EXISTS `novalnet_preinvoice_transaction_detail` ( + `id` int NOT NULL AUTO_INCREMENT COMMENT 'Auto Increment ID', + `order_no` bigint(20) unsigned DEFAULT NULL COMMENT 'Order ID from shop ', + `tid` bigint(20) unsigned NOT NULL COMMENT 'Novalnet Transaction Reference ID ', + `test_mode` tinyint(1) unsigned NOT NULL DEFAULT '0', + `account_holder` varchar(150) DEFAULT NULL, + `account_number` varchar(100) DEFAULT NULL, + `bank_code` varchar(100) DEFAULT NULL, + `bank_name` varchar(150) DEFAULT NULL, + `bank_city` varchar(150) DEFAULT NULL, + `amount` int(11) NOT NULL, + `currency` char(3) NOT NULL, + `bank_iban` varchar(150) DEFAULT NULL, + `bank_bic` varchar(100) DEFAULT NULL, + `due_date` date DEFAULT NULL, + `date` datetime NOT NULL, + `payment_ref` text, + PRIMARY KEY (`id`), + KEY `order_no` (`order_no`) +) COMMENT='Novalnet Invoice and Prepayment transaction account History'; + +CREATE TABLE IF NOT EXISTS `novalnet_subscription_detail` ( + `id` int NOT NULL AUTO_INCREMENT COMMENT 'Auto increment ID', + `order_no` bigint(20) unsigned NOT NULL COMMENT 'Order ID from shop', + `subs_id` int(11) unsigned NOT NULL COMMENT 'Subscription ID', + `tid` bigint(20) unsigned NOT NULL COMMENT 'Novalnet Transaction Reference ID', + `parent_tid` bigint(20) unsigned NOT NULL COMMENT 'Parent TID', + `signup_date` datetime NOT NULL COMMENT 'Subscription signup date', + `termination_reason` varchar(255) DEFAULT NULL COMMENT 'Subscription termination reason by merchant', + `termination_at` datetime DEFAULT NULL COMMENT 'Subscription terminated date', + PRIMARY KEY (`id`), + KEY `order_no` (`order_no`) +) COMMENT='Novalnet Subscription Transaction History'; + +CREATE TABLE IF NOT EXISTS `novalnet_transaction_detail` ( + `id` int NOT NULL AUTO_INCREMENT COMMENT 'Auto Increment ID', + `tid` bigint(20) unsigned NOT NULL COMMENT 'Novalnet Transaction Reference ID', + `vendor` int(11) unsigned NOT NULL COMMENT 'Vendor ID', + `product` int(11) unsigned NOT NULL COMMENT 'Product ID', + `auth_code` varchar(40) NOT NULL COMMENT 'Vendor Authcode', + `tariff` int(11) unsigned NOT NULL COMMENT 'Tariff ID', + `subs_id` int(11) unsigned DEFAULT NULL COMMENT 'Subscription Status', + `payment_id` int(11) unsigned NOT NULL COMMENT 'Payment ID', + `payment_type` varchar(50) NOT NULL COMMENT 'Executed Payment type of this order', + `amount` int(11) NOT NULL COMMENT 'Transaction amount', + `currency` char(3) NOT NULL COMMENT 'Transaction currency', + `status` varchar(9) NOT NULL COMMENT 'Novalnet transaction status in respone', + `gateway_status` varchar(9) NOT NULL COMMENT 'Novalnet transaction status', + `test_mode` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT 'Transaction test mode status', + `customer_id` int(11) unsigned DEFAULT NULL COMMENT 'Customer ID from shop', + `order_no` bigint(20) unsigned NOT NULL COMMENT 'Order ID from shop', + `callback_status` enum('0','1') NOT NULL DEFAULT '0' COMMENT 'Callback script execution status', + `date` datetime NOT NULL COMMENT 'Transaction Date for reference', + `language` varchar(10) DEFAULT NULL COMMENT 'Shop language', + `active` tinyint(1) unsigned NOT NULL DEFAULT '1' COMMENT 'Status', + `process_key` varchar(255) DEFAULT NULL COMMENT 'Encrypted process key', + `additional_note` text COMMENT 'Customer custom comments', + `account_holder` varchar(150) DEFAULT NULL COMMENT 'Customer holder name for reference', + `refund_amount` int(11) NOT NULL COMMENT 'Refunded amount', + `total_amount` int(11) NOT NULL COMMENT 'Order total amount', + `masked_acc_details` text COMMENT 'Masked account details of customer', + `reference_transaction` enum('0','1') DEFAULT NULL COMMENT 'Notify the referenced order', + `zerotrxnreference` bigint(20) unsigned DEFAULT NULL COMMENT 'Zero transaction TID', + `zerotrxndetails` text COMMENT 'Zero amount order details', + `zero_transaction` enum('0','1') DEFAULT NULL COMMENT 'Notify the zero amount order', + PRIMARY KEY (`id`), + KEY `tid` (`tid`), + KEY `payment_type` (`payment_type`), + KEY `status` (`status`), + KEY `active` (`active`), + KEY `order_no` (`order_no`) +) COMMENT='Novalnet Transaction History'; + +CREATE TABLE IF NOT EXISTS `novalnet_aff_account_detail` ( + `id` int NOT NULL AUTO_INCREMENT, + `vendor_id` int(11) unsigned NOT NULL, + `vendor_authcode` varchar(40) NOT NULL, + `product_id` int(11) unsigned NOT NULL, + `product_url` varchar(200) NOT NULL, + `activation_date` datetime DEFAULT NULL, + `aff_id` int(11) unsigned NOT NULL, + `aff_authcode` varchar(40) NOT NULL, + `aff_accesskey` varchar(40) NOT NULL, + PRIMARY KEY (`id`), + KEY `vendor_id` (`vendor_id`), + KEY `aff_id` (`aff_id`) +) COMMENT='Novalnet merchant / affiliate account information'; + +CREATE TABLE IF NOT EXISTS `novalnet_aff_user_detail` ( + `id` int NOT NULL AUTO_INCREMENT, + `aff_id` int(11) unsigned NOT NULL, + `customer_id` varchar(40) NOT NULL, + `aff_order_no` varchar(40) NOT NULL, + PRIMARY KEY (`id`), + KEY `customer_id` (`customer_id`) +) COMMENT='Novalnet affiliate customer account information'; + +CREATE TABLE IF NOT EXISTS `novalnet_version_detail` ( + `version` varchar(10) NOT NULL, + KEY `version` (`version`) +) COMMENT='Novalnet version information'; + +ALTER TABLE configuration MODIFY set_function varchar(512); +ALTER TABLE configuration MODIFY configuration_description varchar(512); +ALTER TABLE orders_status_history MODIFY comments text; diff --git a/includes/classes/novalnet/db_version11.sql b/includes/classes/novalnet/db_version11.sql new file mode 100644 index 0000000..6c5ca2a --- /dev/null +++ b/includes/classes/novalnet/db_version11.sql @@ -0,0 +1,13 @@ +CREATE TABLE IF NOT EXISTS `novalnet_version_detail` ( + `version` varchar(10) NOT NULL, + KEY `version` (`version`) +) COMMENT='Novalnet version information'; + +INSERT INTO `novalnet_version_detail` VALUES ('11.0.0'); + +ALTER TABLE novalnet_transaction_detail ADD `masked_acc_details` text COMMENT 'Masked account details of customer', + ADD `reference_transaction` enum('0','1') COMMENT 'Notify the referenced order', + ADD `zerotrxnreference` bigint(20) unsigned NULL COMMENT 'Zero transaction TID', + ADD `zerotrxndetails` text NULL COMMENT 'Zero amount order details', + ADD `zero_transaction` enum('0','1') NULL COMMENT 'Notify the zero amount order'; +ALTER TABLE novalnet_preinvoice_transaction_detail ADD `payment_ref` text DEFAULT NULL; diff --git a/includes/classes/novalnet/img/amex.png b/includes/classes/novalnet/img/amex.png new file mode 100644 index 0000000000000000000000000000000000000000..517782c248a9912b2d6cb91bd1ccff6eb1929173 GIT binary patch literal 2506 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 U9GgI-jQ{`u07*qoM6N<$g3b$19{>OV literal 0 HcmV?d00001 diff --git a/includes/classes/novalnet/img/cartasi.png b/includes/classes/novalnet/img/cartasi.png new file mode 100644 index 0000000000000000000000000000000000000000..0a32e993fce6008c1a88ee4ae7f24b7988d40786 GIT binary patch literal 20381 zcmeI4cT`hZ)aY*jX(9#?M2ZBk&_WV=FH!`CE*+$W0HGv-gf1OHLC`@2D^&$Wq&HED zsHlj5Qe+SiLFphWAk}x#8D%m~-mLX~Z@qt#MY!2#pS}0JzjO9J=Vq;&lcvUpcQErX z0|2l?Ur*Z{JUW2y-Hi0$|9FDP5_n)D=-CnhKvH<~4GF%c9tZ%6vseool8up}5*qI- z>EecW#YhJG62RU7prRg3a6x-xNHAB72NtI)G*{Ok1jD+i3R%k{}O-x2lllW%-|;# ze>Zm}b8X!}!-0~jkSB>mP(mPrf`TN2q$TnG9tf18q9Ot*g^-ehgFWEH5FE)R7>*+f ze|PeiA8iZ~?T;mpuy`D7)31vwK7gbuB(xdm$Lr7Q@+JHTgd_gR4y1?(b|D~8l1Rj_ zjNH&aYzP7VKHpBw4UNF~V0 z+thqF`!*H6kB|y@tx8({7#9-W-vW>KQTsm2O#ea%)6)7jt6(D5SezR^h$yOpAUF9r z-aoxzv|UITHE=%4!ja&gf(1%mNeZQeloLlvDIt+toP6&|=EDf@hIJ45l@DofT5t8S zr6;)$Fn`=!NG|`$%htYI{J5c&-0}XtE+jRquZsr;LBM&aAbvJ(>G@+;DQV$-@c!Uw zVbr8m5Wi~PV)bpNDe2>gBo`bSqpz(7Hb`QzZc0*aite&5(sFQ=lq(W0t0*G}SCo-) zhs&UlZVGO4vaa%Iw{H-QjJBHp!?iXZ9k7`#pzH62#SM=J-Tyo-DK`aoIXPJj++9`? zjE2Iz<3xmOh);;syqDkw+`YOCd3E zY4^<#axy5mB2rogE`@SM%1R^A^3pO=e}(vkn}3AT!xF*S8nR^;gLC;?WjliL`+MtO z3LosZ3Po`7Ct^19PgUrz1pHCbepIYYn{RonCrX@>ph zaQ-(0-~Def|MwU{o){dZ^!o1VTd#k2Ld3h1f?WJDnjYW``7fFO-Rs}Y$la?THrE0l z?Eiy-Ai4zp&xYZ@W!3+17`9fZ|9`{qa~7jLU2q;4H#Njx6Zo%&|2A^p$Mf%*^;fq3 zGZR%d7bhh!i@_P?@-2H%Du{oy{fzv*zs+Vg`UHIIFOB^6LZCJef7))%IHLwbOJ5{pgEmoUr==TDD1l;an)Z}DkrNQz@-b`*`iVep2*l1(HN=)3W zD2iaDZ#LwLUmDu}G?W6Dl%IxM6n`3iAFM4Kvu|1Wy%pT{fjdsbk1gjv67)wM```TV z^NRjAy^{H&1|b7NS)}5k%!f=%#YF~$vPi{6nGczkii->gWs!=DG9NN66&D#0$|4mP zWj(^7Gf0ii5XaZ%<&rlsN{143D( z;-bulOiRT@286Om#YLG9nU;!+37gzFaEj_{Ygz>V zF>Q+_SyOZ2KT z-{aO+EiW%IM!|xDf~ejp9pe-ZEOz1yW)ELW6V8OT#qWGr%Zw);&j6H2BqXMm zEiN-x5BV`XbC=dOqig^4s>+wwIARrk>VU8m--U7YZ1ofYb^6S)PE)6y3C+=OFO-|v zm2Kh>w4RF{wQ_chzn8Th!w=j~qHB z&1SX7x9yMzl)KRHV|3SG+VS$YH4CJf1z#~09FG(pU{FB4f|v;J!Ye};wPp)+9Ku)~ zJcLi^3P2CMRyLTx@iX23a=bLC>v3}Tndkg5)AcNmTp1K(-GYPxF4Ku z@c;_5PV`MsdX`o|rpfT@9M3jJtwtmZqn?2H!HwKqaW0L15{!axU^;*fy_q+pQVnJI zyWr8=bm)p`egDTdA$h0S;*WRPY^$9y&uz%wrT~d^fut}nLXx*>JVc&gITOqm2kppu zpbLRA#_&|R@dnH8)P!btPdZoH=5%}JaM2-IXwxxG{(Ri=%MA%AqbMwr=S=Fw#H&~L zz4DQ>DYEhmu&b!76yi$Kgwk<;4h5%3+Nc{LJWtfJaoi9Fq|M4Dy(JF7g1V9|gf{r@ zdq0Z<3|EJ9YoWrHYD*^%&g|P8~KD;HJpeBn`6y3%+2^EQRp6&p46w{Da(d&fN4Y z%~9seSB#Tb5@;EAPPZ4`zFFVfKf-^#d%O#UdT(rEqMparmF3~?E+@?rd$ca_o|%=^ zhGCWTm>;VJ#BAQ#DDd&ow%Ql(IK(m51HLjm^vSINw+0);6dKRKxJ`je8_igFcc%DL z?7_SDxzD~Uj9wQm;oPR*v+qGJ>K0f>bV5RwUqp5+%m=H~AK1VD9b0w(j=U#vD=RBs z`^=`#1*e(YNVuEo2oCGn_*zMrB|W6EO%HpQGbv!KrP1ier;rlsSe#&0_%J^!e9={3 ze`34(tbM?WjC)(=wM$CAf3(_HA2YK7PniX{6*6~kw?eLL^mx&UE6QJ#=j#&HHGbEu z2!(29WN){nNoJ1{1o90!;&#Qp?!I=ezaiA@j{jtc<=0{9u4a$vgZGkXj2;_;BV08_NK53M$@a+lpikG0J}e)zS^FT&NJkT?-g!eo zFZIOaO|SECuB+GbN0NJ;BEP(ByW|7__nJCVvofl;WviK`tz1zJTbxZBO*@d(7sJGH z(4lmrZ}MZX%8ihakV-yo*xj&&M9+sg*L)HMo8DPKxVdE5fpgk~zS!SvynA#X2>Y7u zI>|jF#l#0k{rOi(?H8mON^N!tM0|ko@bDzz8`e|ao8=vDnh6A}$Agi10U-P3 zM0W4g@TX-BQKNn0hq61poGbsxemMox_ZuhKUA=m>(OKs0C49Z+%>mZx)^!+gPFOfL zQ$2ETYdXC7ZryAQypP^CJu(&XIaHM;l=e=YDk12OGjh_*DQM3nIeaKP@F<1fK5$7j z$Yk6Tp8!_pDrtsP5w!~$S%>$eG`Df!XG6xW1btLQ?cPJfi=C$593*9lO%rVf7-n~t z*~?EAr|FnTQIBcpir7?Wxs7yHR-Z|?hO4Tw0ybr&iE#+A2gl^WsGEHNt|3Czu81`0 zJ>G*(v{~&8)&0l$JdA^IICbr27a2LZ`y&(Vl{{@a#l5Y5rNUqbKxmx(;co(C^lKf4 zH4EWwX$keG_z@5bnm9iqn{p*Fw7{*8-nBxuOn+jkTlhL+tT@YUso`r^bxwN*T>e=k zmgeP48r@6ux+Ow=UXO0z8`|J-cnARCE+{P|$y?vDag6waWSv$AG@%+{XR9Py8R=s^ zy}g_Jq&+(Nx|wuxtTI|F1){1DRZpK9SXf!PzAAAMPx5$fck|^0lv#(cLh4pcHfn3= ztHuxI=bK!)Jy?ov$r1Z%zZT|MY(H21~J6xVUbA6dNmwYux1Ja5G!uERc#43#3 zJao%Rt_nY-R(d*Nu72vaWm_A(!?WVN6oy$$ObnLjdWb$s14`#mdu$s>6KO9|Ll{03 zisU{;J5B>-qthH#c+SH@zhG%;`I}X7M0ME23#a<~em<_uz`+JpMf>!3$^Z=C7&XG0 zK%1PL90D{V4Ykd7?GW5&C^`ci9Euw@R=jAwU~C6Va07Q*0>jrARCg>a#J_#p&*kQ!92V0Ali`8CmfSr##d{_r zBO%y9C|r(_RwP2?UgqPS(%aGqr*nhtVRcimOw|)M0g46Oqvx;6K#Q18bu#Or;;N3_ zh0o$5&InjKw3X~)V^Roxa@;tG0bKa}X4jUdAdNnyUwofD=?)06eiIk~6Bp+dKAfU$ zZq9DO$B;e(Tl%;V(7QXkgs_jE<#8e83>|Ebh7}HXn>cdaDE@-9$8EZ(cJ%cx-G(RHySX!EW3^FlG970P=&Rmpv%-BL%>d zMRx?1*BO`7do*%a6i*btMo$Iy<>j!Y+3o>k#M)uN)Xv=h>&n7Z=ZhCHK||q7O!+Tu znSkAr4kC_K(*bkw$-Is!x_PHmWjUAHoT6^sl7Ipdt(|K6Pj9T8Ua`BWcyx`!=rAWV zoq_E$%>`yTZjrdD?z=*ATBl#<^E8%BD_E zS*ZmgCq1Up;q_{J(zDqUhno|c-OHmfjM`>#eXjA{Ua^T|IaZ(Mw{7QY#8qqMb!UIn z+y951y%|{FD=R8U`qtLgw?z`MF?ODFbvj&04;LoAiwEqF9O0ND)%m^q$jO4>(~J!4 zZ!dLO4`l|p%J-NcY-4nmhIWFrqP&kKwh8J~Lx7yp<+vp$Ua!2$f3y8^Q?_Pol@*`b zu}C8E6Rf)5w?HLS23cNnzJBo!?-9pi6A!HsT@GJl0lpgwANz$l52s7ombtwLmxtP* zmCt)#RbYi5%O+fSX&n9~eBxvEY5g%{$Cm5Y9AcFrqYBXy5LY^bY6c5>?sABBUdv96 zURzjDtxPG}eyjvNcFXmeq#=(Ycd8_3Y}t$m9KHkmp_o|nn|qMXQHdi8qU_0s@?SR1 zEe)Id!jDC$e-5S9){oQ8i*Ej%)z%8>KdSd7y#CZcU7)&|wUhkqd-qgp%gW4u$Jlls zTs3r;MljOsQq)YMkIji#nmuY}lEGl?At&j0Cr&e#zR4MxU0!|`h$^&(tWVaCz0or{ zY~U|N|9(tZJ<@r0ai%|OdVV?4&fd-^Y;pScefpEF0=Mki3J0#tHrB7NYKT6(5;VAc zcWBJM*1LDM;fi`>1P?It^qlw-3$NPR?6&Q5LpAuJ!NNcUKro*{jYlj#NN#GJGk(y2 zi2)gU^iYu=%2eliT5nY8QY-<@+~|Lzx(8Z&k4w8~Rd9^g2-?p7JhA#{lw?Ot=eC`V z72|9y`c`?Bl?yMx{CKkvI&;DH!uplxmoJ)%FxsY2ju|yn)(s-wC z6HiAttxXn2+I^y(yH@>nYHByjaoEEV7|TTAfstWT#`zjLaDP|6pGj3!m8mYfw}04% zYxcP@Hw*nK9#tOTLytXveR8IH$Z-+PAL+aP{?l?nle31eFI;GtQRV1f1wPg#>2|fS zsb1xv!Mg!d=`&@w#`i`}&&%$=c1<}^mvdQ6T)g4*Ktte!;>6P@F7ey&@0pGt;bOb; zL`zuHR7~r07QDLd_vZpJd>F3T3nc3JdR@!Ow$zwcyeWMet_Zte(fII3tckV!0=;ogsoJw42 z%#^{t=&2=+4OTc0$K)`u?(J&3qP&z+&zvquH+mR0u@E}Guu`bQF#&%PX@rCsXe2nc>aNr&XjXZrw6eML+ty8YZ8Lw&gl-mgzR@Zk4?|Q;(Rx znGXgdet0V2q*$|$qIT3uvIGpEziEU;LU#cD+x=Q9Y>!HeLp z?gX^@0Ng6Ugo(Egced>T?@Vf6PN>KaU%zx8teH$};_X-4#RcOWytPsXj~!~e{$R=| zJe)sp_7!S3fU6mfH`yEhxpZ}9X)fq${E1bSPaO} zsv9~yJ*_F?QmnN$+rg2;U%04|82#bmoKx7S!f2p+MYT$eLHLNOWm-v;8mH1F+S=zn zSFc~scD8{;tgn4)UkE1+-VI^s4gdJ$>h$!c>b_T{kfP$Az%U-6;SxnIjCszTIdbzKf($5@ZR^Ofa}c)BeesTbCZ(;MkmQiM@XP zz=_-w&PY!hps@Q7j+D60t}d2yi7lC`VWy6b^#x1zeg>j1Uc7*wZt;!De(x*C`;mb) z&aAlQoVay~%lgWV@F4*yk|%%hdqMpdvJo{sGz0Ad;wx-nHx*r+-L6^6j87` zUezP_S{CovcjIh6SCLKWv7&wYk1E09)Bg0SSo`B=UnJTxdn6fYczAgk_|=Ymd1or} z`7Pkfa5w))J>xb9Y@ z>8HEf0WWXw!$qs3XU)L<%WyWvT6kRpCf#&+ZVhD$?x@yte`m~$@Ot88%%?v8c=^*`l@?we zp2S@`g5aHkrwp@gIur1?>{*?L0FFCnO8_17_f+4&3fN%`7V`I}C2#yd1UEA0+&aX<{3_8W?+??SOyZq#&NE_be+zL^CN zl5Ml38PF2c@s-*8GOC1m_&5yZ_4-t2pxrrHl5{7}BKtXdgAxWAF5|m?j%U+$8F0L~ z;sQ$)x_IfLsf|tW@)X;h(n{t++!RLFQv zLeH1=jehpkrXEP#+z@;j(q!3lK=n!AY({UO#lFTB>(_`g8%^e{{R4h=>PzA zFaQARU;qF*m;eA5Z<1fdMgRa{zez+vRCwBA{Qv(y!zdU9qW~2E1Q63`5R8IRfC&Hs zXf$Jtf>D4400huz#ux>o01E&JpwWym3Pu4I01!Z<8DkWT0xSR^04Y|G0x<{!BNi4s zdG$d)X%Bv3f8*7kc=qnOBu17l$hM`Zr2#Q9GnpJb%`yXuF@C)F?+^myoIy$nwN}tt z!@A;tUAx`piU}cp=bR&Ax4(DQ+I#D5K}46lb`$ZTK4X~seC9sClybS>U!M;9?(>-# z;YY6HUA?>WpSqsgUwblNDFrDdFvftj7M*ji8Qre{VkBg6dwcuKJ$v?u$;iksSXx>_ zk~%O`u(Gl;eEgPiz?$vBL_5{DA~$O#)g(StBEGZW5? z4VGtQ!pJ-*8Gs417DCVP_)2(20tNDaM(QSXd}^?Xql*#Ji%wH2&&i_%f*)uI*^NEp{mltd}2!m<}5Qb$A zLY^l!;bE&au$AQ4K_Uq%|N8HJRZ0$B{k$7csMcdD3fObW(rPVH{d%^4AQ6k_3ICVii#S;vu7_DX3d)Q7F(DA1Q13aqqDR7 z|Lt3M8H|mM89smh49sz?@U|`}BY;L(V37{Xk;o%U7$qb#6W(SMzQhD>BciDzl##IY zF(}bbsE@&f)`!9{p8kN}USa&T~f3waO?O2?qIo0J&KaOB7lj8FmyAdEi7jvYG~{QUyKH3i6kzkmOs zG@C$d*hmO$C=xvqF*=w8G6vp+N5rTPq0Tk6^kd7o_?lB-c>)=Ofsujee#byGohZ!| z#AXOu^)Unm1;I@z(C8;*u!I@hEdaH8U>O7(00i=QBXH2Rl0l!|T_t8N|iK!5IWLU4RY%0tlmz0UCw{4b6f&E3m{5 zYc|1}QXn-T8kP(3jrI_e_=z2BRi^2A6FogN&Tpm1VYm)L*c z$+Y!wpY-Mx-4b`chZz|~vkw7E(A51fAqa~8;BtXDlrdqV>IiCCij~ki>0~W!s{RE9 zz)+4tp>6Gekh5&wO^+P!^VP+QFjFUeIWM`A6DLv}Dt41yYF5J(dr}{MS`hg6x!Uju zhq3bh4sA4JYXQeAUmZgWJnbR-Ip?|eO~(Nb?&Qw!TG#4xaB*x5>X?!VFkbjfu^Ka51pyb?3+4@-fR|-;$Am-Y7=t%rvaTCAQOz&wOHsW|3)_e)Lf(ghnQug9`WnKmf5|n?m2deLJ}Q z1+tWxiJjzjC^kNFLWN}xloA8S_&rFTn5GSS^94CmV9TJ`5-HYx1v3NAjE?L+Vwyd~ z%xu#eP&!wF?0$0k5uheJK0A=*@MSh!O(|e^83X#YQjd(#JEO92Fq+Xsf+kXjZfq@ zKE9e3*Dx*eS}|;D7#W%I_F*+O)v>w@Ab>D31}7&cI8zWiDnY2KMGjbUG6A97jUI5= zChrI(PW+uh2AU-d*zh4OOLRhjQ2Y^+ClnUM);NS#7$e6st~et#ec@9N5I`*W0)m)8 z!B=8}ECwyxrm(Wdn>b;mJ}khHN6;X0#PyMI1r#GA{)CUdx|P((`S;$~?D#vea)e5J z^brc={tLE1A-49wmNBrEfTT8s(8F}F_b~{$k5K2C*!>{nEQcuFK9@b)TRKj{U~C?Vjux2 zH3~Ti5SLy;eLqS@-;i4vxBx%^v0!UjfI38wj`v@R1D4S0TS8*Qw!zVN^&v*3{$W(r zsMR%!D9I%zC8Z@jI?sc#79uu2sgvgZlGO|a2q2ch9(aV>homf97zLw%SO5?}EQ2Le z5Nhh+TH1juPmR)M6pR8800#6rzXL9QC~4m7^`4PuU&8SQ6`0!jfu0I^UbQ&1y=;2Kpz-?vRl zEi~Gc8U^G6fB<5lb*3OjKej#s45RONz}L?htszDMwE#c>TCQFNVHgO1Nlme}A_(Hz zH*j$F?Ol8b2S>q02(cxX#9JCmEkP>|84_~&yUT^k@qNjQ(Z^(@409}((d8wENWga* zPanN{h^&2G{z3E*bYbuUh$z$5Uu)~P%VgXzBuq%f7Qay4Px;LFB!f{vgu|*`LoW<$-axtl?-VN5^$r$$ayYO(YoN;K;xhFM4p!<>537_U$Z~p<)0vj-l8UHab{rg%J9g@OH4VZ9PRF=Ec>|z~_E!L%Y~A3#DhUQkpPH-8xKa zjX`ORLve-&9sA1kkKr%lF9ud%>xB0|D+9}aCWf#7L4IXnVEPBFLB9QA&}QIfi2Tpb zko@m2gCNT%V9oN2;S4ZpH?hbuJO^fwyZ=5jJpKOzm^m021c9}NG$R*-Fe5vI^Y6C| zhCnerHU@@JpnCHkObph*T4V*sZ-yi6zZrh8Vh=xn0K$5%6e#dP=h8wBbtZJVByuwb zvqXi3E9|&@$f+O5d$N%`-S}%4VmBi}G7D@;2@A=kGJ1HRW*|&^C~HbFP?Rw!HJ@$&9#d0nNh6@}F41d0VVff1YkKq#&E5kPyX7Jr>kNz_;kngvCnMFe|p%Z0sdH?%8hi z<`$vm3pR1|s|s+ji8*4Dl2b5fRijW^V-VWcPia$%ko(ygSs8u+YYbp&17;2ehWCGe zGJFQ|8G(shkb#*&4d}n*|6IUK!NBl<@gu_oZeVkWlY!yIPYwpgFDwkqOz(i1i-Ca! z=uUxuOyD~WL4F4L>n~9J{eM}8R~-Ksu5tZgIQ;Je!~5b7snyP=n=$#eGUR%b1?oxlZS3yg?7G?JKc;(2O)#p zfbVigY<(ScmmzoTk;PEi=oy3&rH@0ajws=b^AB%ggI)KGb99Bkt*)TU8)@13CafRW zw_s#rU;%|UQ0W(7=a>PQ@WmOK8I)dqVJPKiVlesfmEjstT|cmlUhOiy;w68-Mx65cv8l1H=7uDh!H7caU8L5I`6=D%slF{&#hCMO*{Sz=}~TpdW;c zO&;Iz`6#EABb_FWt>!`QeB)Y$i_Iw8G}&52VL1fNya2} zZWg6A5(}`y{ezQ}f#nY?0~@ea^MUO{~)L z4k7muvY+4)On-he{AS@~VEe(!!1{-o;XT)P21d3I45Ig6G5kJx30U@XF??~iXJAQ< zW6X|AM+OSGIPS z&AL(Xn=13v4W=)N4{MOfpe?*C%ghyM1iKS(51%otp&|z!A+g1{Mql{I?&^om=no;E zeo+(|eQ0a-M-F3jGkq3Wi}BGH%*Hs5O<$ftG0OAh-#f-&sHFME2dhGfS1RjA0 z6qdknC&oTJzGoR|u`|)@QK-Awo{k^yHN3cd*8FN;PVj(UUjhhg=Nn`JD3Cw_q^YHf zv$RDn5y(Bh2E7kKsD!5X1Qjgt!rTT56A%D}4vkRNF0UuZ22Q41P16cQ2u zs|UGC+bm1qC^<9LQ}T^&oem_eVf(VP$28 zn*nnFZ(!3%LP88I53xgvK*w;heunQq|1j`~iNU*wpFe+P;NjtBkdu=^stx}zurRZLFF=Bo zpP=*rs^p$MeaXPa&cbkj^*4hvC?j0D!~FZ=Wj{tu%js;K41WOvkajjJ2*WTO&%QbY z!K*K^gNje;OL-9mpTUa{Fd5s_{#sMI!KUD#htV`iL;gt?21%!!34rKqjVQfOQ#c6Pm*jZvw_(@cWv!%Aa{V*H}&Zb$BL7?M+ zqo7c}I3iA1*N;y|)WJCLEe7QgKvbZN1BvqG9D1Oe$^fLivlrh_V@%VugKP{P^z0jx zhsvWYjRV%)vM0r9lJ(LR))we}x=M1pOTMc__FMZ=u#lGp1=Oh(omt0TBD?Q`P6Q*a zrn-4M=K=Ht4cF><`g@Vxu<>QR5>ss?wes5I`Cx3d1^rt9(yn#|K_CdO2L+)%Li8a0 zkeJiX>R#vP2{JEbq@ARqm{*q?NiJK1eTHfy=wLwqrfa01bNcqJ6bgg)Q{RfD!c zE#Q0Ssdz(WV?rsI=b2VU=Vc~R6yl|i&EXgo=qUhgXV20w5XSK*zR|%z5JXCflL;B3 z5YQ?eV!uWg>8B}V6SC(+1O&%M2(F<9FD6q$usC(GOR>d!{fYp0~Rr zzs4&eo4&MDk?mgQ8I zC79Ao1l@!ab^T6hnv(0fkVREh03))T4a0zS7UB&SjK?xf6Ivj!*=z>fudeIp zgLAv8s%bPDk>`0bY*d;1{)_${3e|=HX~Hms!Le z_@qKw=^F?xA`~fRC=R-YJb`5Pp+p3?2yF;m3L*Fm4sMqWf{?*Dgu1j_p>2A0|Uutx2zTZmH6LZKBhQ^TN3=J&i05Uw_Ug-f? zENnf`lfd6gfW5K8cc8naq9{(^e?S&2XghFq{RH7S060j2I1mlsgahFK;6SAL+$X~@ zm}CGk=FxSX0SK@QA((`wX>yC+!{L?Hvn)%hs*05#$_XM_mc?@c&`?$!ASOUk*Y&C4 zW}fF9-?lBsG)+UcZIk0TObR$w7={!C0cn~>S(edkHl^kAk&+}Kl=@xQy}V+EG>-o$ zFH?6u|BwrSJv+|ve!_b|NAmI*4h+G(R_N(@MGuZktCuyCB281if8X~hj$?j5LTo9D zBHC;a^G@oG+NJLO#?{d`r?l#)B*x@!fl|hJSJRhrWIO#4fVA^>X&8v&_^U`M-P%%d z5YjD3#!xy0vCW>pB7cEHt#kj3?9#s=Yl?G*fV&|e!9k3JAZWFCpQkA<60k$yNRG?h z%lF57$3YJMsxRuIbDz}Z_j#lLUi;PvO;+A?u>-~SweR~o1-C3qT-Vh$prX%YGFCuW zRkah9vV2ei0ZM+S3rOo21IYFIMga*Sa1!o8!kR=74kw_9?e}}C>S>xPSn2CHju3+s%cNJ;#sc&jmF%s7q>nH^cJu2ndQ13B8^&+#C>4{;#& zTf@4|$im6$~OGA`Dek72u2jy37<*nSwH=mX;Qn4eNvxjQ@YI0eDC&3fzwZ)`;IhH%;;I z0);?}o`C&^AHe1h(9LWt>H>LQg1GT; zD04{t{yBBKM{+MlpULEwY}+Q!^U!W8&+qll;K0x5uLHU^lfr8R{4P=SE{IY6$8o-h z(`0JSHm#7x{8vj5#^wenjztu|%GQq5Q1nqNAdhpQQ^zN#G#Cvih&>=@gg(bWjyurN zb)YIE7TZgUZTI#M=m3-6WfB+d3(Q&+nMgCd;xL!;y!e`C$PP zY2wZE+~p!L7BLYAW8}W7Dks74mu2Z>5(Qrv2dnGaF%a*?M?XbTxc-?h7|<6*@9b+{ zC)q$C;Mfp_AR7ZYRo^Lme9}W48_ZChX5Z@&5M$*%%{9fV;R=te0mmf$-O|Njwm;%k6*XvCfANmduw=@P|q9z*5a*%zgJ zt4;j-mm!s+v1%LQV6^k}5PYC5U+EQ3p^xPJ5@{;BGxaOE$3CN@`!SlEJ{-?|a4h@z zUGofqv%G|@=2gqcF3hd9$%&+alk7u+MUImnPablNkdJQ<+2^%>f#QLU_!ssi>KP70 z1@uIiu*2;h8LNd1WGhI1l-i&ifUe%V4da42W_Y};D^EKD4za(s2l_Ldi}`pa^~SzW zIFTw$)#~8Z*3RMr-!xfcTIzD8vNy2kTL9*+Wd}hR2oA`}FYrH1h&TV+EB=t0NWmJN zX)|O)qE|f-dgzvInO*ipw*8dH_;okYe-n-vaWhbKceGAGviTrW%8I3CT(Q(s2`pY~ zokTULMDN-s&#|ys7z}!Y(b;Ybo935AL5(Uvi}DmvGHMI{iQ z@zqRK1we_Q(iuiVlj&gZd)(Ey{&Yr{F4!~~H&vx~)k}Z1C|Px+O#UWbb1Bc~R|K`^ zo)l23Wah6JJ&Bhq>3oHd>wK8|C}f!T5blV8s^DGRXrt=Di^V7Wb9?D zcgz&Y@rzl*j8=15BCa=x)dkJzoX8Q-APl;x_!Sni{|*OG!T3`8H)A85r( zxOL&)T^GHN=kf$zNKiyXsHSajUdpo}QoMlMKr+MdUS~4%(m`VUN%0+%`0Gl5NSaR& za7~I=0ZRlDXtYm&8~SaKKot{EV2_moY3D2kXqs)*eoxoC?pH75RLQ3EMOK!HDv#8$ zsMjwDb zn;QvygT_j%aVWbyT4z}!dyxf3pvwGzn1u?{QHwltsIMoK=Q{&}RZ-eaeZ7}YZvn`= zVikm8Ao|p*!BN2<5!|X@>)`6#mq<6eFh0EQ$G)afQ zP73_jgHy2cI->x2JtIXF1qoZ{Qd#33PYjx7QJQw*UYVb2g>}}X|23M~!UMvw0N5tJ8PBRVLJp{@5 z3=*d8YzgZ_FTK8Fqa7fiaxuw7?ifwgaY=)&_e!b)L`!);^&YB|fb02$m2XkawcXpz z7J2hI|3ttWoEZLcFz}x^&S1TC0kFTp z!0@Ud?+Zh$s}(x~E4UdC^d@~H5>IVUmu>~gKfY7mwg0J34x7F zftKh4d91)rH>m%>%)`x~biO z?Yj&o_~jU^y!@IN7=&IUy9*$ISa3BPh`m@I+bJN_Oh~joMT63WjqgN8YGf2zCu~a1 zr*!o44|uEy#P|>1v(3iH1{C|tzzkaUt_JK7H`X!mG&eE)Kd_5|vHTtb^TTHhJkf~^ zU&VnXKO1PQ=?{2S?mx695EFEn$zOJ0XB@}_)lBTKo-_PiFpq(G@oEO9t2Y?_Yicnp z{m;Q*Wn|fh?k<1;V!_w>hIB5`0}_?}|34#K40#9I&@B-e2ZdXR$xryyz~l&@D@B^U z=<<|~>N6u73`|Q*j7-3$(I0R$u(L2Sd~!5l;Q3v^z$75d@PGXVhTp}&n&ZGx2G;mU zhClAk46IDzzzo6&9?bd)%@7>_p=~q}=KRgT{NfP<$I*iff7h&L__bymSk((-3x+@O zVGO62tpVD_im~|!Ab@aY3{Vvb8ZHDaYD126Tw7Ri9n*>Jv~u*37+TgC1JM-1cl;+Q z`&r02KNpwz#JYjhlNXVjQuxji!=?WZuyw-n`yT`2kKe%b2`r3(nc)`$WTX$2S-yh? zFBCNxc+)Z%gn+dK_r_HWUpH@MVA_0yflJej;eov+1GAhc1B0eC!(SO821ZUc2A0pj zEb{an!@rjw7(|YrWZ<}SnSt@laqyN_PEjd_7lDBc&rM7ie#$E_{Ab^UH5>o}hy`C_ z1P#6YeEkz+vo4d85MbW`*qH}~t?(B!e7bmcpre(@-$HtA}g}oia7j8}l zpZD^QU(YhtQiA&;tF|b0QxaC_%a51je%?b^gw3}a!X)xY7BgbO{2?Ut5K2V z2xUNgBZ}Bgb;M;RuCslS;}4(z&}Y~&GRn_?3@ofH;3egtM9l^=512##{`?E>Jb(ND z6WF8zcBGlu7#PK67+y%qGW<0#WZ-qZ!60_?9s}paBMhwXzAOT4NB?)FUPH;H#PN4Q(Qe6H-HLW=Eduz-BhCk{*{D zY;Hqe^Mx+Y1|EfCVEFOtC&TZ*{}?#gI2joK|6};~8!~+SgZC4|chG+HpG*wAUzx${ zoZfOvGJG`_WB90J$-od4#qb9@7X)6q0zJJFmT5Wv05i-FUWQM`X-XzqH{TIgoQrj6D}D(5whE?;%0&^u^o?mY(!7KoBg21 zI5Uw5C&MR4tp`SUXbi(qPo(@AhtoH8&+WhyF6rp=gL1V+&i)-K!Os}UX8zFgPpOH= zLf^sL;Px!LAEp=Uz96o%&oMW^bu(`(n1cra-s8%v z|3s^u0nG#jvxD&xYkyLAjSc2UA6ML_?Le8eE-W@aY0YJ(hY0=)UzWEac>VXgH|F4#J@j|J+CYKg$jM)i|9{qv*7 z)E~%z#^(AO$E~b{e;W!<*G~XK?q~&J7>2?yf*`*C(<)w!PxS}%sKv}u|qDPeGSyrQx}2B%vZw01Gk@1=138a( zfe@C7<8)H#YOdxkfTQM&LNkImI(f7OlP7-y9?7O_Q2CvH#u<|%v*$$TcAC&h8+(?N zvK<-GkLoAz{nxkk_iODl0X!eCzxS?RA7OX**FykC?ihz*5QYM1hf3|xsuRrI|3EoU z^^Cs65YlD|4KcNi4FvK3{VFN05@H3}Fp3ajC#$y81^eRjhZ6g#?LU-ECjhK~~c`64*`CgmH#d2IC{+GUG(k zF5)bp+%DHRrV;=UhZ-*#kWq0D``|w3JV7p|>$*rjx=z1-4*h;)A%V?X1lJQZpo@gd z>^u9Wav>-@C>H9tc+Bz_{jzpX1d+d{Kf+%MS$FgGyL~Fp@zSt*dea2UxrYZdLep%3y zd!94P(tjbD+&NRQkqDf^1qYaAH?}u;3VwS`d7@HEoU7pBmcz_-iUOq-{B(sUyYDaz zVJ|?7}w47Tx6t?cv*%mJUac+*Jkcic=qf^}V2WOq(BN~4bKoHPtWX)qass22yWD&EVh zbRdW0DY#P>$V6-$$FWFbl|vXLB`~ngLvBkVa6+JtB z5k-I@q>>?EU^|-ywD)ksNTVsG)xOl*2TA%UV|(p$R~@TkVcz~26&4)ef3id21UoWk z9(~`}{V+KnMfUAKB?UK3kNe^0FEszj7*7ExyW15AK_Cjl(EVR@JjhFf1lEsWx78fS zGaqMU?fOc*_uuB{Ky2bBWYL9v;W>|8bqH8^42Hog0eM6;0?&)|JeT&RK^8$j9vXO0 zRjI}<$M1jFWEP@lg~@^f2v4i8NWlx2cEpXy(0JqoE^TM^qyy2)zs<>5lWcz3+ypE# z#dD0uvz8*#rzl0A?ni)U-mjg=(CH;~%n4*XzGp;q0gTCc+J7k;WJu%$bb4cCGp&9O zlwLqDqJ@)qkN(!&WzLcKB3PVl9gh9}&XfH$+J7rkw*Z8lJr06E5QSGX@uyXz9zjn5 z&9>Z83rhHJzosIphzIhbUriTtlh>Eb#jXBe&@=vG-Za0;)4ou zAUGloUXt&)fDw3nDOL;(hA$(LBDkks6dZ~;j;*dNUL515{0#=orBJT&nd&i77p|yd z{d0|?#AMa;8rFjHS+Ancm${36TCX*`#quu7brM;#EHh|v=I|2r>1$EU47eNlAfzmxEi~l)Jp)$?%=pVAcn&5#gyTs5(=Oc zs^dTvu{-j~^R4sGFqsTaxWRysR?@EY1lr4AtIlWNI*mfyxABHLIVb$*^r%#X);a_fH1Z#BR-!%xZR zP19=@6;_#Hf6yZqwzK<58!dvf^TX6ytfw9!mQW&Fa-?A)2rZ%VfxvKpZsssa9 zlc>goz7C8g1S@JC9OJ#sW!kKU44i^KJx}%=p+5wV_HYCS-c|VjdpreT>~3-p1Y$4@ zFYyrSH8=!>)3V`q=9%Or#0AQRh%(bo`}J?I+$P_@z!5O2(1b<;Cq%LA`}sOce}v?F z3NIf42yrp6WZ_wF9zcWM_CaEdauJ|KJC0+VS@hg@R;GP|>h-<-sA`gff&d|bEz5EW zsA`DuSa&ql&>2t)0osU^tDvLua-o!P&m471_nUQHhxe%wn|r6}ar-z21>X04c!+tP z$9=q<{Ab&?!7m!i7pw=vljXL?t{2mz17F6#6N6w59n~2cpYwWc65hq?*Z;Rm@EJq= z0beqg*ekr?R~tW{%~xSnl`jaK9n>k=0{Lz=HeUX=-3$Br zZy6JDnSj;(3>P^3PUdYpK6gf- zqfgfupPUTNE@)2fqgR=rt9YNHX?qBK(vAQemQgR6diRu2AzBV=X*o znY7cYcEZGZ35q=*7_g!QQ(LZ`#&KQW*Z0&RDEGpQmVOZ+)4<#%r=69`Q`2`AHMhuE z(U}5q#eCw4aiU+bm*-Nzwz6)=D0_AMB5(!JtiS&QMBnu*V8UC!V|~#z>#kqoML-Jp z+|PBTSZ2{E3);0nS;j&u^#7#YpORB=0T{cN6@-Bp3d0-0r%|Erzg8bgP`{zS%tA)p zh*r`}PcA1(ogRMPC-tXeWDpf?E)c`GUvE2QIDQP@90SlmI$h2qsxmU!rLGAh#L>wm zhYaT-*Tu{r0XTv*d;;0%1jx{Cjfs^VIMXRdwd``B>_=`Y*`p^%8)vv&lga2BL7}Cvl-(ho?X=TQ-^}auaL@NJ+&{19w06$AEokZ(V?UVU3F#Bf(Oc;2hfnCWBlby-warD$h!5k?CgSM+q*)Na^{I@R(GK1oeI=xlw|g zk9nqOCo*Wk1f9sZVU@OeE~D?eLbsvr@sxm+2y^e|6qC&fse;o_g5o@? zcWy}bYRzwNTh@Hr7gnU8aNRk~(3B0Ahp6<82Ie_UsMIIGF&#`~OrD&y24S*J84UOp zdZ(Hj@1nq&{jiEKr2 zQBggxxRb;2aM~_9`*+Pu*HZvt)EJ=C&Ub9z1z(X#=_wHZNjx8b*t4X_*^NiemQ7M; zQ8DEiDcX8Ui9EK_p46?a6x;ugk*48GXh{t&^I(NaZ*MEs8UrAJSQrKopmnAg%zze| zf>1b-v-6M~`zgs3ZcRap#7S(#lC$rel+uyXghz?} zq?|}X%48iWr>UUpfi05t`%wE{V%A|XA4sVPP2NgdQ^Dw1LrcC#4? zjtt?Gr-ol~P5R->m;eDpa0lOD$P}bZ(vX^|23w6mtAsOR8y7-`zaAU6C+tuX)sXi#5H zNo*g3ls?5^tTAZmesU5IDefB#eGFp!Olpk*5I}=wREnG?6{U%a(%O(Xc}Ai~ddRJ< zNUbr*9f=~xenK@Stw*)U1pom!JKGfiK^Tgr1-<{nMj<3I?dTL!=}!iMWrOu`?%lSp zES*5pAYohY3NsSy1F)t6QSX29Vyfe2E(`i~4?U)-HX_xK?AvKawk~uZ>^;u=!56_h0q!Kd$k%MqzR4OqvB&piT=c1J4= z!Y~wuRnXzZhVTD8eXQx`w-S*$H@03%P)JB z{@NF`EwJV0vyJ{XAWbnC@%&owwAnE2k=uNk!zXGjY(E~3&vykpi=V|xy0k_uR-5(x#1EO*!6h!b5Q2!%Ay1F8{U5|yaOy8PD_ji}d?aWOGn2vk3(XzAJ()Ewg zzGrMgc}wFqwUd5^-+UKZymlQ0&WiRdknWA+P|w<+GYTHwo#-Nvrosv84!IzrbYSkH zSQS6<=-R+ZaG!aY3~U{RmhD~g`uphaAWbwcVwQ+u9|QCPm(`)%;sJvu($+BUuNqiO|byIJaEXZAE#ficn} zY&VHKqLDw@U*`-M5-c8AuCb3*Tuf%wU&1qBkYo}NDN|f9aaHta%2T<$2fqtgv_IR$ znE!7Z$45&9e8yxP;uYyE3Vuw~Vx|$}c+6H86U=G_%XKv@WJV@f6Qk8`-gX z1N}5MOxb+8RbL%sRNS=Wt{2=_V3ZzN>RsRB&NTUtpLcq~vM@1BPY}WWND_if#Yr$O z>i`5?UIYM)F%Mgw5P~r>@`}9(U|>E0c+}!2&=;O+36OHDlszfIt!wfCk}Qx)b~{@K zSrA~5DP*@J|0_UWatwQ=Jl>?#DgY^GumUg$!%(kdzvtQi|APt6Fu z4lzcXpSl9}mn2smxN1YEb|7V91iVO{Ssy@^4qaZyBk9ZlJa#O5PK;Lo*6v^jAQ%V& zsN&@6|9?~nUf6_&l5njwUAoiGw4M4+rMkWv_;B|?Q@b{}|G8eV}sJ$@X+Qv)u9d>C{|rjZ{i1BR1XlDt;B*_=_g)z<=P?2X`ld% zIJx?~3(%O|JojDs$<<@l`mz*VnlTmuSi74Q24Nrwz+MZ|_kT{0#TNNur-*+GRgXDH z!e%zJ(V4vrjA5L$1&+$4TXrbLva!hCA}Zii1?^*;m3_^R=-GeW#Xmo(&3G~(z7+7y|q_@E}J74@Pq++ShtanjIO1C{q> z{OB)&mUW9Yi47A8G6pq|S_cs0EC|p*U=Nvl{I|>vl~Wf*T`0Cd6r+kpt6uNFY10{) zCILvhnw5ruAp9lW?It0K)`%j#35pjlN}s}q>cy*P@uc1g-h2+d`vQtW|BNXOX_C6% zHYvq}t$0{MlG)i|+00C4m~X_o7`kQKzcSj^E=%{}3BBh&pd!X0Ank0?4+(7I(0o?C6%4(8-56OojY`~I zUZ7dLB6JRM`}l&Z`yK{*^Y?}VLTQ;)0u?Ky(*wkMS?Le4Gl?M5J|>#qhaaMlDO%Y( zf}Bp-K4O_blyj&ehphf#a!VgFAyG7JI97&a@P+nn8}ay)4I1G2z|D16@7){RGWeG( zwT`Zi_0!#83GS+k$Ah&B@?3)=)0eL+?at3SOC@H25nLa~M<>f%M%~W9w0-<3!v+?k z$SVw9FEC>~imQ%bC7N;p^p?*`Q*cCDM|oy2Kd}|ID)^kanaflFxlu-AEvMO^>rpnf zEZ+hUcP={(!$1^0v7JYoLM#ZPpR_q@{RQ6n{eT+7=_JM@qTs4HU=xoS1P^^2g zmdc}7dg%8tNtiZEC}*T5q!5t%8}VxX6O($)O|oJkhw!Jbgm_=n?ikq(-<5X(Si6>#hM_2WVqOvxjie34abg9vAg;tU zxdivnC3NT#963=G6daU-)Is4DlD@p^z4<^44G2jVkU@C&oO|ERIY;y(UG72ZBRtv$W^#x5T0o6lBv(G}rcb!I^l_dLnz^ge{ckhI+dJ^`{DJ!i zAD@d5SujQrS@?RDh))Id<{PdNAs2d(pXB}%|JB7P?P6$J-e~>vr|oObPPIwhPj|!8asnHEYad7ii}h|FU0(!bRp3e_d74aJWh~nC5)^xg;9hgF&Tjz zG#Ts_%Q#Tjg`a0ZVcW`#~s0d5EFL*h>ZQ7`C<&p`izmv;yjc)h&L=aOk1{1FwiE!~0)v7=E$<3kgnOpX&D)sw8}JYZP3A9QaCX z^mRtG*e`;y@(0U>Kh&sE$OQlaSUZE&1Y#fz|FODeji|KrP>|AtqBlLYN1w_^@cpW# zdnrm$C<{x=ipuK7L??rI5EOKK&XO!)hdzg;L*=S;& z5_fn-HgJm@`tV!>OM?6`BA(%3BE1j+1s#*R5W? z8a#aX@#AL(85t>ti4!L>czSs;tX;d7p|Y|PJj9onmvoQPs z)mF^hz)ta3hA*H20AOc0`ul$d4Nj25I2b-Nb26~A@G!6e6YMX}cMKoDd}jE@s>vYs z`zM3YKURj%BAg6Qlz{ybq2~Q}10VoxXUvl@6h+~a_$Z}K1F3_NIJ$swC@U_mxcZw|VQ|2> z5E%_KBk{+W2pR=b3J>Tj=eBV%m`K1bFX`|)oqNC2ci+8gU$sU{DfA+D%gJ|o5}u9L z4K6NWQ6dj_T_Te79u<~#(QLL61a&kTw`jHQQ7)eoR}6Z+KK;ZRgTZrZ%%$aht#-wC z3Z2d)#$!Pe2flxn7NjMK6vHu+b2an{hTqW15{~q4DrDW)C3{p#AzZ}>9xkBrMQAI* z#6<9nO+lREt?&tZKE+BCk5(u27kRi5RsKO#d!YyNH7wiDMj(e-xr-wm#^smeOe6M) zg_A1xp5o>@ho|8y-bcqcS}SV{Y!uUBMH8$~HwOqU4(za~zUnulf zzx>;?5rDO8XK5e^!r$HIvYhc^qDD^?BSH!V(O@I75K^bpU*He16vRRh5&Q*~HrAFl zR)RJ@Qbe#wj9%U`uXAR@ibVn`EQTGpnb~EJxt;xXZ)V`>lSU*)GG_McPPf`zJE9GX zLKA~^X}+bHrqHCPC=wF5zPd#2^%2L12e`YvL9{ z)g*GMBtDG-+`U~axf$418=fp6TsM)I4rC$$xi*84G~rn`deTNEm`9BqO3ZD-Sj>>~ ztx)*K#kaHYzu%~Pn!a)gfp87osSWJR6%kz+$E+~%0f$y2b09qVpQKZy^0|ZtF#eW8 z(En)Yl%@K>RVSY7bX)ZO=%~32FbZL)O5%*5tE)E5*Be!cfT7+ow|>9Oypm;ImeV|= zf!u1Fjb=^hX#1?kGR*6~S>G^yMf{9qtf2TE2lFh$ytd17Y;vNeuc%`V8$It>6H6aIj-A zH#cRlva$eA^@oNAgYVABEhu2Pb^R*Cyh&3STC1wT>t{~vKg96j&OHVWV8RE66m&vR z1l&w!1$N*$8JU0?;uizwA0YehZw4Mi-Ez`j)5UG4A`I8$-o<; z&+zfheFnyFTnt?N>d z$QHK22Rsk~%p|a@0bqw>!}y@}N1zM=n&pO_AP&363wALM?9@ikWFYJcG1&biu;E{r zKG;d~uoK8(L&UJt>|y8F!bTurr^Lh7*unOOz%nZAenMD=hMmESd>1*WDGlO-S2i%R z5S3<;Ybav+HUI%=yLOcZq9A%mjCq>KMldmt!bd>RfTf+_2c)p~FRZK-1Zx`+w@7E< zCkW|81OrwfS{REYL_}h=*yL_VoRei5tAJQ+vkSWeJ7@09+;ivrnGzB*5d__^7fI#6 zj7LFuo8==(Yy9xVl2R-ioSt2v^EJTv;W272E!^BbAhM9bZfOtMLIIao*C?0Eux%R$ zM<=lI%Meu~1fy5#myK&r40w znjIqjEGtcMOCpSg-kXc>^(^KxQ8=#w#B-bYc&tmB6oRP_kS^_`(|E$t_A1c+gb@IS z&_uI#k6da4fm9L6#Wf(>1sW9~yMu1qLD*fvyBT{M_mZZujofzs%%}2r1YT zX=rg^9!g?kg8<-tof1yxWqX^{9X3Kp5ah*xLjaHp!W34e+~{;1s!du5->2%fbXxM7 zSTE`cJUX+g$`UZD4X6XKX(OMhaw~1&fg{p72nv3Ow(HPr+MrBaQbBYkG40gxqbiT! z`z2>R4JT?EaQp~B+SRi(3`NnSCQV~WOpUfw<5CJ0M7#SJbkNPeBCd|&;;+y}or+s= z5er?!XhbXcH3&*Gq>xla?`e48U_odgLy{L>0{6W0?tSOJJ316waFbx6M1!99$VbW) zX;7#?_cyaTEO9=O#Hb$~Vq<*`Uctrj!9KpkL9WeLVe1BNFKg3`oGxm?$~t&hAvu(il}z5=DXp3xPz9l*;9x5vw{HyhlSOqtL)rt!Ku(7#?-fR&G8JY#sVQKmB;qWWr43@ZH@emQKza%J^&;gHq7x^n6 zuht>r2Tk;ET)3qI3PB_m{!K(O$S)KTZ8s!T@J*4^Xk{MLQ)6&WFEDf6fhX}od}0po z);JQ~5Z?V0a#;z)!v_qX@8CAYqX;0AnKqnW5$#rh+~f-eehOYZLKgqKpxF0w0+7jr zn&QuyJ}MF``jm5z3af=lx@a?ZvM6c229LDJwARYIP8oU!DmtyVZQG{uPN^3NCS|+j zeV9ed>jWQ_o3cugz_ztCfk5Q*>ClV-Qhs$UxFRqKMozS_ZOX7+%_dfc*l_sqWAFN# z?Nb2Ku4ScRAc`KEGzFW|Skl%i2(El=+_)1I6kHS+frxd}Z*U=gMnA+4a4iUafh!@4 zA_~?TYKw)2w2k*9+@%lbDuD?znQ-qt=T7d-F&A-)w7M2Ga37T=Y?_@h+VfWe%b1*U z9mlPUbW)z@!K}J?>xbAmIE1^kjid7xZ236Nb{6IGg(BJ~P58c#PN#$G%PTb2H`3a{ z-MxLBdS|H-M6sZhE&Mr7U@_lJOw1#JN1=36$u%az?W2MOb!&o~$UyTY#5nGvVmjzQ zJ)<`gsBWyG*L_9t@gBLEfl{@OkM|x{AE*a0fa416Ee&BWZwfL9;>40O%q*<%%z#lD z^XaGLRf1087vkIy`C5Y8I~#+z1h*ng%WyDeB0F95T&CaKGJ(rX^Me6|#zy4Oljj*- zX>>Fwl?b52FyA0eVK7oPDcxAbzEsDY{cxF_*B}T|gC|u|83&~~teT~x5CJ$IBfJW` zsDc)$4>dJ!vmy zXQ7J_0%3-bdnf1Qo;zo4j(();Z6HqzOy1tnKJH>x z2)1s-XoUr~jv`nYV}<~Y&2~91g^W(-n+Drxh6cuc!bF0TU-xnUATL(9P3%0FSdvek z)&8@u@rRjJ|0}Ld1liPc?o+Y z)ZR?zV!|rzSjHnPA~I``gN(eNwxWiwCq@Knyi&qqziwIcqDml zu2r?oeQE_}x{U#Jtf3)7`zBe5pj4(u34`qjhzrc!fi{nyJSIbeCOTCRpPAqbtt|Kr z){(hJscy3aLyd{f4HcAUdgxU;S>-BMwdTQ6$7N58FxD{L*VC-h-gKtoqA;|1R(E`) z(dN+_ZZX7bw+-~0q1j|uX+-LZp~oU7FY8d3SAE^wTV2MHl5C)4V|A|@z4Zq>uFLfI zbsv(&wLs}ma(ZuiWR%~P)@Q%*9L9t4p`h$NHgIMtHjE6JIcEi#2+ZMNGSp9k9o`H2 zuqp{??(qcYoD9gRj&bu~Y63Y}Ai>FHs22ggv)lUp$QtAUu|O5Rfg$r8$N%}?;&=HJ zfU;|ANgxWsAD&%xS2NSH>;ge0hEZD3 z2JHehZ8>j|>R^%*FKoasOZD(tc(B4KH8H3L>OjH+70-u@L% zuZN*0r_k*@;>)h#Jraj$af|1VfqaR96~l6ITe=rE99vv&rpeJBhNj8HSReDVwP%6i z=o1Sz3n)kZD&?vOC37Lt6H_u?oL`Fa4kr3hnCt?G|tauu$axs+Qw69nTIXoXflOngJdS^)u}SV5#eJj z<(5%>D&yqjM%G*?dgHGVfO-$?k)Xnuyce_!7M zuy(~b4Ff@Ne2yJJX_JCL_wdA{5`*$4<~# zk%-cOB}+b8KCR{5+gb1J&M(7Yz{D5o+TWz^@G93|BlZJoQ_w7aA!O#_vK2zQF_=-q zqdjbz>EDQH(v`VZm*XTFw%+!WGR$9lG)aXduiyq}c&=K!uLE9ijO#&*%Y2FPQEA3% z!F9RB$eH(YW6W@hdq2cu=`or%xcV64_U6?fkp+5Y*KzZ+_bJ-o(_)(WVvf6q3{P(k zOfx11tz2VXu_hC#JP>s28G@RVPPFb)(nv&;$%Ti7&Q3Nu}fe6YhV=ZA_yL& z7Ig}5QKn}f(8c!0Ay1T^xSM8393$ibBFiT#w?vg%G+fiZ zL#uDmB9H$ZDSn%Oh{7w;1Cft-yh^j0>n*7o70*vWlImfu_QSkZ zVhrlQOB>DU<0kCoGu5`3=jrr}E@~$ymLd0PTar4V5+4eCzJAuGkVwuC*UEM3sbk4E z@%|>QTK(R6KkbWWLR;U#tq%c6ySAMMfhaf&3k0e)O-%Kr^%MMe|3zc$bM>L7X?h`S zrQqz=A$W<6kvFoiWW%1zoIU5vH^J~9na^K>1c$|+%6Z8QqTz&=<(8X))5Y`+WBS@H zwMiYLg85bZrBVDR-|*|$mSEdAL~zkHnqo{$lB29@)O%0X*x+)vK;=0B&k|yf1na%U zLw$uuuPC@boL$ldEYLWbSqf>EZ*Y;WkQ{c%HVvKz2D6#L-MufdogUY0shLv(-eF6? zKjzO^5|_WimCq=m0Y>LH*p_@hPygM9|J1k$JjFezljRP8Thj@IHf!I_aMfFwLz-64 zs#d+9VEDPf>CiQEJJ#8ofJMX`E`Y0fBuKI#{$AFjUrZ%eM@`p!nn-A}@zI7LUK@f(aWh0pQmBo zn6J!drcsQXb}Gx(c70vfmwqZBEX&<9EAT7Uy(W7}5R&*TH0m8jLP97EKyC{BptrzN zo>CwAOnK37nfFV|+jvs?=0;7C@4TH#TZsSn?mFj@J2*JvNrjkWfQK_O*Kd?gCJD zML7t9#t2bk5Y*SnBaIRg{>B1fUE1z#eeM1XqbLfgsw(70 zgd;JxOb^bx23`?(KH5MT6zf7jjUi}$#;cQ^OBX%mAam3Q%b#}(0Wpki-$?p!;q*!) zfhoL;du*ZnJ``ZfFGo51SX!?{xJ>rLA&lz^xOehT$=WYmd}~ETG}-~r{Sy*IfO!cv z^iVD(ExLG`)UecRJ*yYipC@|VhBeAOxjm%a*C#2!GR8FgyysO*(iyL=)%`{^!?6)PCG>suiQuO&z zMhW|kublB@%v^OWt)3@RoENqU`|7%uvMgr}<0AlN*Rp~z3iDB&byY=yKx?mdsmi?-x{^{Yo3Gc%woWhw( zVU>EB*S2Iuu;SX{=h@%noqY69dF2AnxhAY+A$8~t$|qv&P2s%nhg#iXrk<&N=m)Ii zyjh8_J6YI~SPkLvA-5id;q|AuUas@4ag+dqf~;p3Ew|Dr>FZo0(a%k>JtaGZ^-@Mj zrgAt_Saw&U9SY?*?M=t)L{(k|qY43V0a^6rUwMpw+k^vo4f5QBg2EBkbHWh{nSw}a z-V=&-&6)ikV|RL85^Nd(BM_qtw{4&ej|~n&qhnEf8fwlzI3AIL{3XWX{Y-Ky^yB{F zJ<~)xcs$n#%UCZROS_C1Wm$feOMeO=Mr@I^WXX~b>({U6Z*6U55Ec@LUuF;P>;Nr* z1t7k2O|flA!RBb(hXoUEm*ZPrfgC7=>?dZ^J}x!H_>b5_0kHd@fvClCxa=n;?C{1P z6AMM=6AB;X+5wmOluY9N|Mv&p4`N|~93>0dR{~na?d|Q&P*PIF0&cjV0e}Ev#AWd8 z*|R_F*s+7ZrMUyV_zX5A1{+I;Eh~n#XK{H9+qOb-A`X{cnFyczajRz_Xg?wUlX7YYhX4Oj7XJ83a(o2~vCG2=Weg@p#9?xv$w5#CnKyq9 z=y=Z;b#*n8xby)85FDPnUtuI3n_1z^Z*Li&+wG;HoeFYz$?Pz1~;RD$6f*+cJWk{W)8ccD=RUGiHk6> zva%9o%AY@f7~Z^j%W(VFJ%+!3|C$2?5DUm9a&j^ZQqtmJ1^@s5Bg!CVW+n!4aZv`4 zk8a+$lL-(&AcF#hLnTJ7`Llw+^{`EXo1BHYIK~x|>0D%nRXJTdq8uS-M zft6$-gRV$8irD2hD;bVG??(}1Vg^(E00G1VBLDsSi-OezJmH4C{eByaK>#Es!DWD< z9s~dahzSxdK!N{%;Mhbw4J>)_^)iMPH^adA#=Fg6F;nqW6ty4>0ssL7@*2Zmps9cV zF~Oa?`(X_OFPjv@y$}1qamACDOJKjz@o?-v4I!`{zFcvEbj|{|sL~{APIf{3nPz9Uy=h lp#_@(v|tM)w_pPZFaTqz|6>In0b}2t`TjEJT|mN2?r* zPFYtLAy>(fJHpa1v_D7UH`;1{f3&~n^*qn_`~AE=@Av2ZIsW*@yExfM?NZ()BqStd zXNxBaR*c{~ApV`;&&)jIELiq)tUNfb3?EJii3JE*QW)L<$c{$x1&9EN5*GLj5FkV} zscs$|4}v3_%%B;PwtWmkX-olHKzJyWNh13L9FRBQOQoBG7oOCDK~#!4*d0ND5|}u^ zk7~#}b^(!G0VL6AgicgoGG|7#T8Hz7QA+h1%wT!wm!;2JA38hZJf+XKQ?6zyoYD zi^}9s8FbJ#BgvZ)#4!g8l>VIpjro<9&i-5`LBSxQBqjuA2;ENUiz9*X|6OUcuik79 z5%@>%H;LJ9VN3u*1lWuq7Fp0ZAC2u$Of-%KkT?vM8-o$>rHU?o3=V_s$6$hRu1Js$ zfkdX#w+*_V5Cj6+j?U(g=w!eSZw?l47*eSev@sTkf?1lvjbSK3-K~tVrdSgc9Ayf{ z!w^PrBls6AoPf4Sx-_U}>Vc}3K zq=3)V`rBIm#!|kaO|EJYoOoI8@-hLfi!Qt!Z19ZW>vjl^!Rb;&- zBqUa4hqrVK9UStIbaCt3zsVa`oc~#LG7*$~a|dy64mDdVwXiVLktj}c_4nz?b$aJW z%x?6-UMaegpH<{q!U?!d(<&tQ^k?pUaj;*x(a}aY2J7N+7+j&>hVvSj;#HJ|J8wN1 zYKJBmsY)KZK9bFt9${~ywzhJ%!lav(p2}g4W4&~hmL2LU(?q*(>3obTW6u6@VI)R| z&MnE@xC7WBPXy13PmE4^M&YV>UU8?2@|=S~4I3JF7E^!1tf&X-`|9>THC`1q`>9V? z?_-JW!Qv#hnU+_>j}T%}qZ>VyuyU^Hyc6EW|E^z$ie2*CeJF=AjmAAYv5NKPzJ}Sq zWq}w=X-mU4k2rA&C-Js!$UNM!g&UW~Phex1y-g>ki`xg@qu7-<=gSIOBe-?EKl!8A zC`NgPTE?9{1P`&Sobuygr*e(tMwWwjKQCpMClkUkrKmZ5rJqUTLv_;~8JojV@$$-5 zEpBw%uCsa`!po^PE{{qkRq*V4{=K;vMyIT?mi)#G>DY^x<3#JVS*bzAO95O*?{uA2 znZY}!Yv(ZC_+_V^)PiW#{tOwtA%6#xt1r-M5V!vGP0V7`S=#KNoBVXnj41A4yNYDp zG3`Aw^Km8boyR`3PcN}~l@2$A;uoyEuEo%wpH>!Z!5CRcd4cCrdpf7klDW&fEx@uXcZ6KBSZV5>5;!#>jo z0#xo;K6@+Wd9iP5ZOvDAZ={P~wS?4^Zi!R!uNo(3$|4jWMsAoaS|SqXK=+f$msx2@ zdxw1)b=v!VJoOEd)BdF0`vH`Way(fjJnXvm-sfCB;=EVA*-R+UT--V-c5;H3?$o9q zc5bqj+bE9NXubxGSi*eI=v9YmX?v?q4f?HX16J{A>Up6!*;=my1zN%!m+nUoX-Z8K zZj*hy7z+2&FQma0l}UAwHK-W&Rr_hdG_gG;Jbi5B`?DmdDqeBfN zwTA~3k7p#LohkF^`-o&zJv7jd*?ZJ7|CUj7cf4s9Dr1rxG}_rBQgN{Z`&wRekQy7g3FSovP5XC`jby&a;*VQ_ z=X-WAx-yDumgW^c=xwzuM|#JYT8I?7KXrQ~`Ye5|&#uKio>v#pB|6q-XPuxWN`wk! z_+A)~`@`c{4Paswl2c{MpB=h=H+bzA8}+IPuQn;D`=q+>*3*g#F~tI@lljutycB8q zQd^?mVM@FGg0@6@tPa+>uN5~Bzd=%4i26ms7zB@xEWU9{Py95H9VZ@@F-y%JmnG-) ze26@^CXHDuz+hSk^&`v#=0SwX+-dgkbA3-oO_6x{5vFhfk({#p3RAVbt6}a}pJwdJ zy6E8<>2gG=Jv6#6^CsfLvQr}5@Z;4W?9T?@E9RP&JnG6{k%!6ZOzy5yF40||3ezsy z>h&PzD?E_BBvBGenX)x0sD3TM#XcaK4Yzi8>pU?X-=U5}5tDS@AGsuFB{1F9(TaL4 zetUW`!~9f2e#5@Lw1@qJJU{)xl(Xd|MJ7@|*HuvD9pCyn z61Zau8%$RWBMhX7Lu#X6&wFH0uy-5};S9t(bDumt+dc$zsoayb+PCS{mhkZz4iIIh zCxsqstz2Lromhj!7L+o_ot^xd$Gqs~H*r@k|L9$j#ic9Q z^E$E8&ucd~bQ`sm0+*X;ngxw@a<^@Af_6&awTXIYoQl@y4al6-dZ&W_eh=_c4GJR(i{G7zm9?_^N}vW`1((K$cntes>` zYL$P9^3jT+OCRLMKn`uY3VoaEVKcGTcctBF5LI2tK7;1O(mkfl=R~I09*w%9 zwWUy`^fs;V_ci|kG30ry+%=lmWPh7xgy)`{p7Ae$*kCIt3h63AwwI7k^H)V7!_z%7 z?pGI7M+Hu4Oh@01C5MNoj;_7sODY9!(c8Ux3UvA5E3c~B8VndN>vNFn;2&}{eH4nh zogbE-zv+hX3;9{KHNB42HHtO-h&%6RXiJ%wZ4n0o0{UrwzxQuZr}`ci@()V)9j9H@ zT`P8OyZGD%KI?74%`x$K#a!q553Jvxlb82~LZS3`r`3pxj8@8?cv9`5{O;M83wl3T z(|0G_d*l4)En~9%^u5gFYYo9MUyn1tf$R1w% jGxV>vP>vQ&pe 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 bPVn>Thk3v+8QS-6-&OH8PPi(ofQ0`5Dh0=# literal 0 HcmV?d00001 diff --git a/includes/classes/novalnet/img/invoice.png b/includes/classes/novalnet/img/invoice.png new file mode 100644 index 0000000000000000000000000000000000000000..2b2f2b82e26651c04cf08401d8386578bc75e5e2 GIT binary patch literal 865 zcmeAS@N?(olHy`uVBq!ia0vp^ra&ym!3HFIdc#_Q6lZ})WHAE+w=f7ZGR&GI0Tg6O zcl32+VA$AK^E+@dkgt&J5#-CjP^HSi(9q1l@bf>Ae#yX4YQVtoDuIE)Y6b&?c>bjL zqizfgOxHbK978H@CH?vT-=2AC!pTWT{Y6BlN}Rk{{r}(I|AvMejd(&>7#NQ@@j5%m zZQ8bNno{s@V>T`328N`C(;V&V|E2u+@Q}I9LR*`=dBOw(W?M!FhQPDI_xIN)SA2OP z*k&OvE`HaRRlp(S^Og7a>m}^!{&Xn*dw)NktqN$yqFKvZT3aP^a&iog%$zaf#XC)~ zm_y(52M-b?co-BKW=OOtGH@uYI(h|Yq~yMupH5q<+}zyQ?Ck7jRd6XZta!Fk-oDNt zW?xNbMR#O`gpQ6*<|C*nKRv_4`lI$%;(X2MLO?0!eRwMiv3?wYopP zy_G(Eb#?g05XKyys;XZm8-*1bGTv#LnVGR!T3YfHrlqCLy2%Oj`A3nA4=r;xw#_!r zZ~7V)9UXiXXweam-iu2PvN14aM2Lw1xrc64cyW5PJN;a}(8TPYt%4o*5j_VR?vBe1 z75r1``A@ltIfpG~Il6hmmHq9fj2(_jPWZ8U;j1v`qgD%lIsd;tyVU9K8>W==Oq(XY z6=9jlE#Tl|a5Uhs)r24E3&rL)S~+q0=4uG-m+6);x-YSc?O0gTtkVpp(oYu54ER^A z^X$+WF4ig~k$!832RaT62Pe%}xU#7_V4u(xhY2?#6FSzgwF-prsce(>GFE8Kk!lRN z*!k>4bwI6GK>vZHD1no55jqED;u(1vVi;sHfSzd)u`)Qr@U=rbXoVtk0M9O`OtvLY znsa6HJ|h7_X#q0I7OR}PSOsMw|IZx4o6Ret;a-= h8EvT(`2-ReE^I#Mrv6o-511VoJYD@<);T3K0RX7OQy~BV literal 0 HcmV?d00001 diff --git a/includes/classes/novalnet/img/loader.gif b/includes/classes/novalnet/img/loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..cf70c2efd0887795d64bfc0d6573733589eca929 GIT binary patch literal 7356 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
J?^qLna9e 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 U=MKb0M*si-07*qoM6N<$f@U$uY5)KL literal 0 HcmV?d00001 diff --git a/includes/classes/novalnet/img/maestro.png b/includes/classes/novalnet/img/maestro.png new file mode 100644 index 0000000000000000000000000000000000000000..512a82d116df40c693f49feded7f8076590a25cc GIT binary patch literal 16438 zcmeI3c~leE7sto8ZdgF2RI5;96hSeWBxE5&fD)pD7|^f?SSwj3keXy-5_S+!t5Okh zt5v9oEiQ;!DK7l9S{Fc6v})Z_a6!~!MOj3!Qus~67Dt@pIqmQK{+XPU<-YsA_s;vg zcW>sONuTXM!_s1m1pok+zCHpG`aKzaj~+4z{fwOcTL=0zRO1t-1At*R#`geVOU`Hj z;670Vh3Z3vvmhy=qKajR1g6HRH0W#q;CaSr#L|VZo+N=I6>4|#v!f@-B!$eKJeMV; z2{qnul)@)L3kN3n2T2naO1Uz!r-ubE4nhN{V7-_Wr&6kQP@Fs26c<8&8;3zM$uvd3 z(4FjMOh^h9&L(*yTA0M5vMEv;ok`+wsdN^b!{tmRF;E+%xq=KDg~o+gE)b1D>VA*_f#J)x9p2rZqjQmi{B}V z`CPL&GASfSv?{UQL!lB!!k|VS$piZa&1UwVD##mAB3ksaU=J4_*x#_3%5>5oU$ssz zR!d=Dfd@K3RVZYTD~G{hyPyRqm&(}`wwy_)xXNHQMdHe(v*=ug*o7fBK@{C3roU;85|di3lr@oQZdtoBH_47jNOYP<1%GT7LD1HqMtBt zr1DYd(9;@kc8bxnZ0c-*@S@j8dmKuIsY7YRS{-bxKX-CZ0rs}E-i~F|nCci3OO3tF zLuxD!SjGci8|}NSUS+pT(a(0i6N0YzX7ab^h>e2Pc;(d<$~5ckL3D^*A1l_vUXkbt zd6&xXiu$??8=eOm{|l6g|G`G+#4-PH8{Vm^{>e6AI@JGf8~RSMG)kIJ&jIck zc(WCn^7^bh$I*w_$Gl1pAW`M;KBgGHwj$$d@x=D7X}EvN#MfggYgo$FhKB40vA3X zjF-TL0fKK5xbXR4yaX-`5PXxsh0h1$C2(PY;F|<4d_EX2feQl!-z0G1^TButTo@qu zCV>l|55`O2!T`ZH30(MmFkS)|1_-`M;KJvF@e;T&K=4fh7d{`1m%xPqf^QPI@cCf8 z1TG8^e3QV1&j;fraAAPpn*=U=J{T{73j+k-Byi#L!FUN=7$Ep2feW7x#!KMB0Kqp2 zT=;x2UIG^e2);?+!smnW61Xrx@J(D?7JZL!!fN!n%~Yd8rUAg?2mpY-1%Oe=x&@`v0bt-6Ux8OpoZ+`k3pE?A*_Ti89Vu8> z_QSHz2SEcqaj4*r6p|jstgD_Fxjt({>iXJ8D?YcZkhjircj-)SZMyiXFGp zsck9yk8irXoISxa;A2DktSFm_#hbO2C59o+*I1hlh^l4z7DXcALD9gBHenmHY?pbU|FNWr0w!Qa-b-@Y{K zbbWo`{_qdEU<*C(mypl<49dFMfH?FnS`wu%EFwJjo z(0J(*tDh2!etnp=UW%ji#_e` zrUew-`r5w;p7(Lq9f)}3sC3Pmx$5ZJ3+LoBv#BGJC$8DDWsJx_ zcW3_3>+R#G)q>&t#UbqP9Q-ZrgqG(&RcDTywXOO=S#xQa=sL1(@19kD0bsfRs?n+K zdp3T#j&n9;sA_mRb;q&wY30{GyIA2dFwp%VOXUCMkhu7QN>yI^z zWIH7RO)4bIJI1YQYJ#U_?4J%X@*E(d;*Pa9!U-#HUSx1C{JS-5+otG6;{xXgp8u;* z@`cZ2^ubcwOZFW(S1*dRB2nFd@JzdWr7vy znqhg^Eu!7ie|vV~9k&aAhUN1b*4TYfxwqzeeVy_gwWcGve5Jop`kh~*j z=+Ks9huT%=-aqYR)#>o)RHTkAm@{(G*h*1jaKz}~G;vVCuyR|w^chpOEcxEa`onyP zmhsJ9C#9wqh&a&du*+IobNATu?DFxtR)jp-@M5^yYR@EKizVdgz6iGHLr#%PS^vE4}Dcu TP0$77ll{Ka`~~~?5lj9HaiR)X literal 0 HcmV?d00001 diff --git a/includes/classes/novalnet/img/paypal.png b/includes/classes/novalnet/img/paypal.png new file mode 100644 index 0000000000000000000000000000000000000000..04c71d7119fbd1a4cd1bec2be6734abfda19cfeb GIT binary patch literal 2565 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 literal 0 HcmV?d00001 diff --git a/includes/classes/novalnet/img/sofortbank.png b/includes/classes/novalnet/img/sofortbank.png new file mode 100644 index 0000000000000000000000000000000000000000..f301df4e2e814af10cdcb3d809ef9c8c3cc170af GIT binary patch literal 2903 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 n=}K2Kdt1X1#prkT^K0Z-X6Pz_~ zKE(U>fwu7e^ee%Zyh)m6XwR~txv~5R41iCcL~{iorWArZU=0vR{@(2X4X4vE4nq#HF+2haz#>4{6fY_h!`6d-=f&{W8^K3(!wCLAwM1{&l`i}hOx#O z{qV)x=|MeMEII}T^Yiml_tR9TG2CHr9UYww4g^AtXQ9UQr?LoaH7Zm7Cj$;(5*cJV zi%g?JHW&%6G#{28lo#ngDNyLYXsOH}W#SbK#wO5VaCME1lztlG@&DhHLiuIQWLX3M z#``~snYR9P0A>v^X+8`huW@ej8?NXWECV30Xbf8#&Fg0stvqNf8q zJ{Ht(u`pgRu#MLKSF3*>@$|E?{3Tr8=9lyVDo^hWp0F1$w2JWYfyzyB`nK%Bk0<@S z`UfQco}o49H9l@(_e&AI&Ypmnzm4sQLLN2H7sU&kLc*+|c9nT{`lh+ItO8KK8jCL` zc|VRL7n$nXE8cai6Y+91l;iaF%WBlfz6Y;X0!R0Y8g-oGB>QE}Tn>I*%hjFK9jQ$$ zD2#Z316q~#(zNK=6pZ#7#fo;0W)~mt^ zUVH~FWFT3S%s?vuljecs(7X3Tnx8KZ$tLdgIC$3nZSm=<)9z}n!JoD!tdu=iI7n#- z_m$bKYGPe=$z-p!;%(c;$rn3a^ra38#HEHi04k7@irmuOii&N=bAop&CLXtHb8NRM za)Z}%)2+2RyOMW~Mi+71y|z@Hn*;~Z15%hP>C-jkUQx`2n1jn$iWB^7&yCK~kbtyW z`XAvL(GX!mS>wkZS-1F=WvO!==ieX08ja_UMKz|OZ4U3$*`_QVb~EV29VzKzFn<^L zF2afFJ9D6ze~Y`~JDf`|XjJi3h{Posj?sEsL7{Wrs4-tr)@a|om=5#WxUP7T=Rl6< znBRff@GY$n4O(g4ojYk7VCR!rvXbSmnr?id=LVj;TPKhQ>((h>a$CFH7Kk8v+x(HS z4H;diFBsa6I&Z6A6K7B5;U*XJ`2Sv%8S6!-<-eUW3uJtIHUS?_EGJfw9j zeHBrjSm5lPP&((eqjN|pT3tU@H0=4SuT8ypMzf|}{&@(9hU0JCue#kwfg97BRE70O zv{5n9V_67_Xikl^^c@cfMagZx@+`7T#$|2$x7s5Oi2|(7r4_!}po14~?UDm7T`s*} zb8EUk06Fhc_~B)Q{3M*zo$}h}6w6t+)KfdcmXny7^O$?F8ZE0m*nzm2 z+4;G0-5YDsUsF@Dw5(iQLfWo0svFaKXy83fj`-ok6D&2taY*Ckv#{8p9j`MQrPQ-R zdl8!3`HwXJRU_e^?y_g1dBktK-VA1^Mer8P_z0a;Kl<&0iTSCR!4H<^;FMnOyy~|M zkXVqdQuT05;hfXfvVKYF^qz4yPyPriZG*ty;FTJH6t?HQhOf%*|#6Fz8x7&BS0Ti`(j+ z(=x2I#K((1kFz5TarLJzn)tQ^7i~^0tfG&M7>mRdyoBl(UV zcO!vf!*4dB*HMx{Ou`;li8&{;N8#Gs{2WiZ+j|j*He5Dz*ZX6J+7G_!K22B0?iQ}B zDYTMqY`4S5gt?qEGf&FFUNt;J$#pf7=>rSZ|LK&QMwEWxp{?_H;L7cWS2|#oBU< z(=wxX76$AOk8+0Z&vFX%8bNa0FgG2dvShxBp@otwV^Q|hwgz2lhr7RLNnuC2f}na~ zY@en4#F*%-Di&2W51ka@5`AUfGmz9+dn0on(WbRPNhnNy9Sa*iWjyT!jY&G}Ad&@^ z&T6l4OoMk-Z!##Z3uF{ZKGiK$S#wUV_NSolcq^~pEwg3L?cKF0Dhi)mU}R`lS=l+@ zdtaWq4VOI8lbI?exT@okfQWLqvei7t98kVKRKGLw65pD<@K?;@622`S;KU1|*XA@t(Z9yxdhg%zO?>pVxgOoOLB<<5dQ(FST&aOe_a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=n.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return n.each(this,a,b)},map:function(a){return this.pushStack(n.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},n.extend=n.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||n.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(n.isPlainObject(c)||(b=n.isArray(c)))?(b?(b=!1,f=a&&n.isArray(a)?a:[]):f=a&&n.isPlainObject(a)?a:{},g[d]=n.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},n.extend({expando:"jQuery"+(m+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===n.type(a)},isArray:Array.isArray||function(a){return"array"===n.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return a-parseFloat(a)>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==n.type(a)||a.nodeType||n.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(l.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&n.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(p,"ms-").replace(q,r)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=s(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:k&&!k.call("\ufeff\xa0")?function(a){return null==a?"":k.call(a)}:function(a){return null==a?"":(a+"").replace(o,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(s(Object(a))?n.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=s(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),n.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||n.guid++,e):void 0},now:function(){return+new Date},support:l}),n.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function s(a){var b=a.length,c=n.type(a);return"function"===c||n.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var t=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s="sizzle"+-new Date,t=a.document,u=0,v=0,w=eb(),x=eb(),y=eb(),z=function(a,b){return a===b&&(j=!0),0},A="undefined",B=1<<31,C={}.hasOwnProperty,D=[],E=D.pop,F=D.push,G=D.push,H=D.slice,I=D.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},J="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",K="[\\x20\\t\\r\\n\\f]",L="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",M=L.replace("w","w#"),N="\\["+K+"*("+L+")"+K+"*(?:([*^$|!~]?=)"+K+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+M+")|)|)"+K+"*\\]",O=":("+L+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+N.replace(3,8)+")*)|.*)\\)|)",P=new RegExp("^"+K+"+|((?:^|[^\\\\])(?:\\\\.)*)"+K+"+$","g"),Q=new RegExp("^"+K+"*,"+K+"*"),R=new RegExp("^"+K+"*([>+~]|"+K+")"+K+"*"),S=new RegExp("="+K+"*([^\\]'\"]*?)"+K+"*\\]","g"),T=new RegExp(O),U=new RegExp("^"+M+"$"),V={ID:new RegExp("^#("+L+")"),CLASS:new RegExp("^\\.("+L+")"),TAG:new RegExp("^("+L.replace("w","w*")+")"),ATTR:new RegExp("^"+N),PSEUDO:new RegExp("^"+O),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+K+"*(even|odd|(([+-]|)(\\d*)n|)"+K+"*(?:([+-]|)"+K+"*(\\d+)|))"+K+"*\\)|)","i"),bool:new RegExp("^(?:"+J+")$","i"),needsContext:new RegExp("^"+K+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+K+"*((?:-\\d)?\\d*)"+K+"*\\)|)(?=[^-]|$)","i")},W=/^(?:input|select|textarea|button)$/i,X=/^h\d$/i,Y=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,$=/[+~]/,_=/'|\\/g,ab=new RegExp("\\\\([\\da-f]{1,6}"+K+"?|("+K+")|.)","ig"),bb=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{G.apply(D=H.call(t.childNodes),t.childNodes),D[t.childNodes.length].nodeType}catch(cb){G={apply:D.length?function(a,b){F.apply(a,H.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function db(a,b,d,e){var f,g,h,i,j,m,p,q,u,v;if((b?b.ownerDocument||b:t)!==l&&k(b),b=b||l,d=d||[],!a||"string"!=typeof a)return d;if(1!==(i=b.nodeType)&&9!==i)return[];if(n&&!e){if(f=Z.exec(a))if(h=f[1]){if(9===i){if(g=b.getElementById(h),!g||!g.parentNode)return d;if(g.id===h)return d.push(g),d}else if(b.ownerDocument&&(g=b.ownerDocument.getElementById(h))&&r(b,g)&&g.id===h)return d.push(g),d}else{if(f[2])return G.apply(d,b.getElementsByTagName(a)),d;if((h=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return G.apply(d,b.getElementsByClassName(h)),d}if(c.qsa&&(!o||!o.test(a))){if(q=p=s,u=b,v=9===i&&a,1===i&&"object"!==b.nodeName.toLowerCase()){m=ob(a),(p=b.getAttribute("id"))?q=p.replace(_,"\\$&"):b.setAttribute("id",q),q="[id='"+q+"'] ",j=m.length;while(j--)m[j]=q+pb(m[j]);u=$.test(a)&&mb(b.parentNode)||b,v=m.join(",")}if(v)try{return G.apply(d,u.querySelectorAll(v)),d}catch(w){}finally{p||b.removeAttribute("id")}}}return xb(a.replace(P,"$1"),b,d,e)}function eb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function fb(a){return a[s]=!0,a}function gb(a){var b=l.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function hb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function ib(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||B)-(~a.sourceIndex||B);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function jb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function kb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function lb(a){return fb(function(b){return b=+b,fb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function mb(a){return a&&typeof a.getElementsByTagName!==A&&a}c=db.support={},f=db.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},k=db.setDocument=function(a){var b,e=a?a.ownerDocument||a:t,g=e.defaultView;return e!==l&&9===e.nodeType&&e.documentElement?(l=e,m=e.documentElement,n=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){k()},!1):g.attachEvent&&g.attachEvent("onunload",function(){k()})),c.attributes=gb(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=gb(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=Y.test(e.getElementsByClassName)&&gb(function(a){return a.innerHTML="
",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=gb(function(a){return m.appendChild(a).id=s,!e.getElementsByName||!e.getElementsByName(s).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==A&&n){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(ab,bb);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(ab,bb);return function(a){var c=typeof a.getAttributeNode!==A&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==A?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==A&&n?b.getElementsByClassName(a):void 0},p=[],o=[],(c.qsa=Y.test(e.querySelectorAll))&&(gb(function(a){a.innerHTML="",a.querySelectorAll("[t^='']").length&&o.push("[*^$]="+K+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||o.push("\\["+K+"*(?:value|"+J+")"),a.querySelectorAll(":checked").length||o.push(":checked")}),gb(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&o.push("name"+K+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||o.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),o.push(",.*:")})),(c.matchesSelector=Y.test(q=m.webkitMatchesSelector||m.mozMatchesSelector||m.oMatchesSelector||m.msMatchesSelector))&&gb(function(a){c.disconnectedMatch=q.call(a,"div"),q.call(a,"[s!='']:x"),p.push("!=",O)}),o=o.length&&new RegExp(o.join("|")),p=p.length&&new RegExp(p.join("|")),b=Y.test(m.compareDocumentPosition),r=b||Y.test(m.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},z=b?function(a,b){if(a===b)return j=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===t&&r(t,a)?-1:b===e||b.ownerDocument===t&&r(t,b)?1:i?I.call(i,a)-I.call(i,b):0:4&d?-1:1)}:function(a,b){if(a===b)return j=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],k=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:i?I.call(i,a)-I.call(i,b):0;if(f===g)return ib(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)k.unshift(c);while(h[d]===k[d])d++;return d?ib(h[d],k[d]):h[d]===t?-1:k[d]===t?1:0},e):l},db.matches=function(a,b){return db(a,null,null,b)},db.matchesSelector=function(a,b){if((a.ownerDocument||a)!==l&&k(a),b=b.replace(S,"='$1']"),!(!c.matchesSelector||!n||p&&p.test(b)||o&&o.test(b)))try{var d=q.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return db(b,l,null,[a]).length>0},db.contains=function(a,b){return(a.ownerDocument||a)!==l&&k(a),r(a,b)},db.attr=function(a,b){(a.ownerDocument||a)!==l&&k(a);var e=d.attrHandle[b.toLowerCase()],f=e&&C.call(d.attrHandle,b.toLowerCase())?e(a,b,!n):void 0;return void 0!==f?f:c.attributes||!n?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},db.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},db.uniqueSort=function(a){var b,d=[],e=0,f=0;if(j=!c.detectDuplicates,i=!c.sortStable&&a.slice(0),a.sort(z),j){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return i=null,a},e=db.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=db.selectors={cacheLength:50,createPseudo:fb,match:V,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(ab,bb),a[3]=(a[4]||a[5]||"").replace(ab,bb),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||db.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&db.error(a[0]),a},PSEUDO:function(a){var b,c=!a[5]&&a[2];return V.CHILD.test(a[0])?null:(a[3]&&void 0!==a[4]?a[2]=a[4]:c&&T.test(c)&&(b=ob(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(ab,bb).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=w[a+" "];return b||(b=new RegExp("(^|"+K+")"+a+"("+K+"|$)"))&&w(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==A&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=db.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),t=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&t){k=q[s]||(q[s]={}),j=k[a]||[],n=j[0]===u&&j[1],m=j[0]===u&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[u,n,m];break}}else if(t&&(j=(b[s]||(b[s]={}))[a])&&j[0]===u)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(t&&((l[s]||(l[s]={}))[a]=[u,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||db.error("unsupported pseudo: "+a);return e[s]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?fb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=I.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:fb(function(a){var b=[],c=[],d=g(a.replace(P,"$1"));return d[s]?fb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:fb(function(a){return function(b){return db(a,b).length>0}}),contains:fb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:fb(function(a){return U.test(a||"")||db.error("unsupported lang: "+a),a=a.replace(ab,bb).toLowerCase(),function(b){var c;do if(c=n?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===m},focus:function(a){return a===l.activeElement&&(!l.hasFocus||l.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return X.test(a.nodeName)},input:function(a){return W.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:lb(function(){return[0]}),last:lb(function(a,b){return[b-1]}),eq:lb(function(a,b,c){return[0>c?c+b:c]}),even:lb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:lb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:lb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:lb(function(a,b,c){for(var d=0>c?c+b:c;++db;b++)d+=a[b].value;return d}function qb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=v++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[u,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[s]||(b[s]={}),(h=i[d])&&h[0]===u&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function rb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function sb(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function tb(a,b,c,d,e,f){return d&&!d[s]&&(d=tb(d)),e&&!e[s]&&(e=tb(e,f)),fb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||wb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:sb(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=sb(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?I.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=sb(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):G.apply(g,r)})}function ub(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],i=g||d.relative[" "],j=g?1:0,k=qb(function(a){return a===b},i,!0),l=qb(function(a){return I.call(b,a)>-1},i,!0),m=[function(a,c,d){return!g&&(d||c!==h)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>j;j++)if(c=d.relative[a[j].type])m=[qb(rb(m),c)];else{if(c=d.filter[a[j].type].apply(null,a[j].matches),c[s]){for(e=++j;f>e;e++)if(d.relative[a[e].type])break;return tb(j>1&&rb(m),j>1&&pb(a.slice(0,j-1).concat({value:" "===a[j-2].type?"*":""})).replace(P,"$1"),c,e>j&&ub(a.slice(j,e)),f>e&&ub(a=a.slice(e)),f>e&&pb(a))}m.push(c)}return rb(m)}function vb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,i,j,k){var m,n,o,p=0,q="0",r=f&&[],s=[],t=h,v=f||e&&d.find.TAG("*",k),w=u+=null==t?1:Math.random()||.1,x=v.length;for(k&&(h=g!==l&&g);q!==x&&null!=(m=v[q]);q++){if(e&&m){n=0;while(o=a[n++])if(o(m,g,i)){j.push(m);break}k&&(u=w)}c&&((m=!o&&m)&&p--,f&&r.push(m))}if(p+=q,c&&q!==p){n=0;while(o=b[n++])o(r,s,g,i);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=E.call(j));s=sb(s)}G.apply(j,s),k&&!f&&s.length>0&&p+b.length>1&&db.uniqueSort(j)}return k&&(u=w,h=t),r};return c?fb(f):f}g=db.compile=function(a,b){var c,d=[],e=[],f=y[a+" "];if(!f){b||(b=ob(a)),c=b.length;while(c--)f=ub(b[c]),f[s]?d.push(f):e.push(f);f=y(a,vb(e,d))}return f};function wb(a,b,c){for(var d=0,e=b.length;e>d;d++)db(a,b[d],c);return c}function xb(a,b,e,f){var h,i,j,k,l,m=ob(a);if(!f&&1===m.length){if(i=m[0]=m[0].slice(0),i.length>2&&"ID"===(j=i[0]).type&&c.getById&&9===b.nodeType&&n&&d.relative[i[1].type]){if(b=(d.find.ID(j.matches[0].replace(ab,bb),b)||[])[0],!b)return e;a=a.slice(i.shift().value.length)}h=V.needsContext.test(a)?0:i.length;while(h--){if(j=i[h],d.relative[k=j.type])break;if((l=d.find[k])&&(f=l(j.matches[0].replace(ab,bb),$.test(i[0].type)&&mb(b.parentNode)||b))){if(i.splice(h,1),a=f.length&&pb(i),!a)return G.apply(e,f),e;break}}}return g(a,m)(f,b,!n,e,$.test(a)&&mb(b.parentNode)||b),e}return c.sortStable=s.split("").sort(z).join("")===s,c.detectDuplicates=!!j,k(),c.sortDetached=gb(function(a){return 1&a.compareDocumentPosition(l.createElement("div"))}),gb(function(a){return a.innerHTML="","#"===a.firstChild.getAttribute("href")})||hb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&gb(function(a){return a.innerHTML="",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||hb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),gb(function(a){return null==a.getAttribute("disabled")})||hb(J,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),db}(a);n.find=t,n.expr=t.selectors,n.expr[":"]=n.expr.pseudos,n.unique=t.uniqueSort,n.text=t.getText,n.isXMLDoc=t.isXML,n.contains=t.contains;var u=n.expr.match.needsContext,v=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,w=/^.[^:#\[\.,]*$/;function x(a,b,c){if(n.isFunction(b))return n.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return n.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(w.test(b))return n.filter(b,a,c);b=n.filter(b,a)}return n.grep(a,function(a){return n.inArray(a,b)>=0!==c})}n.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?n.find.matchesSelector(d,a)?[d]:[]:n.find.matches(a,n.grep(b,function(a){return 1===a.nodeType}))},n.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(n(a).filter(function(){for(b=0;e>b;b++)if(n.contains(d[b],this))return!0}));for(b=0;e>b;b++)n.find(a,d[b],c);return c=this.pushStack(e>1?n.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(x(this,a||[],!1))},not:function(a){return this.pushStack(x(this,a||[],!0))},is:function(a){return!!x(this,"string"==typeof a&&u.test(a)?n(a):a||[],!1).length}});var y,z=a.document,A=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,B=n.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:A.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||y).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof n?b[0]:b,n.merge(this,n.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:z,!0)),v.test(c[1])&&n.isPlainObject(b))for(c in b)n.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=z.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return y.find(a);this.length=1,this[0]=d}return this.context=z,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):n.isFunction(a)?"undefined"!=typeof y.ready?y.ready(a):a(n):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),n.makeArray(a,this))};B.prototype=n.fn,y=n(z);var C=/^(?:parents|prev(?:Until|All))/,D={children:!0,contents:!0,next:!0,prev:!0};n.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!n(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),n.fn.extend({has:function(a){var b,c=n(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(n.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=u.test(a)||"string"!=typeof a?n(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&n.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?n.unique(f):f)},index:function(a){return a?"string"==typeof a?n.inArray(this[0],n(a)):n.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(n.unique(n.merge(this.get(),n(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function E(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}n.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return n.dir(a,"parentNode")},parentsUntil:function(a,b,c){return n.dir(a,"parentNode",c)},next:function(a){return E(a,"nextSibling")},prev:function(a){return E(a,"previousSibling")},nextAll:function(a){return n.dir(a,"nextSibling")},prevAll:function(a){return n.dir(a,"previousSibling")},nextUntil:function(a,b,c){return n.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return n.dir(a,"previousSibling",c)},siblings:function(a){return n.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return n.sibling(a.firstChild)},contents:function(a){return n.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:n.merge([],a.childNodes)}},function(a,b){n.fn[a]=function(c,d){var e=n.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=n.filter(d,e)),this.length>1&&(D[a]||(e=n.unique(e)),C.test(a)&&(e=e.reverse())),this.pushStack(e)}});var F=/\S+/g,G={};function H(a){var b=G[a]={};return n.each(a.match(F)||[],function(a,c){b[c]=!0}),b}n.Callbacks=function(a){a="string"==typeof a?G[a]||H(a):n.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){n.each(b,function(b,c){var d=n.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&n.each(arguments,function(a,c){var d;while((d=n.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?n.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},n.extend({Deferred:function(a){var b=[["resolve","done",n.Callbacks("once memory"),"resolved"],["reject","fail",n.Callbacks("once memory"),"rejected"],["notify","progress",n.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return n.Deferred(function(c){n.each(b,function(b,f){var g=n.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&n.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?n.extend(a,d):d}},e={};return d.pipe=d.then,n.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&n.isFunction(a.promise)?e:0,g=1===f?a:n.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&n.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var I;n.fn.ready=function(a){return n.ready.promise().done(a),this},n.extend({isReady:!1,readyWait:1,holdReady:function(a){a?n.readyWait++:n.ready(!0)},ready:function(a){if(a===!0?!--n.readyWait:!n.isReady){if(!z.body)return setTimeout(n.ready);n.isReady=!0,a!==!0&&--n.readyWait>0||(I.resolveWith(z,[n]),n.fn.trigger&&n(z).trigger("ready").off("ready"))}}});function J(){z.addEventListener?(z.removeEventListener("DOMContentLoaded",K,!1),a.removeEventListener("load",K,!1)):(z.detachEvent("onreadystatechange",K),a.detachEvent("onload",K))}function K(){(z.addEventListener||"load"===event.type||"complete"===z.readyState)&&(J(),n.ready())}n.ready.promise=function(b){if(!I)if(I=n.Deferred(),"complete"===z.readyState)setTimeout(n.ready);else if(z.addEventListener)z.addEventListener("DOMContentLoaded",K,!1),a.addEventListener("load",K,!1);else{z.attachEvent("onreadystatechange",K),a.attachEvent("onload",K);var c=!1;try{c=null==a.frameElement&&z.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!n.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}J(),n.ready()}}()}return I.promise(b)};var L="undefined",M;for(M in n(l))break;l.ownLast="0"!==M,l.inlineBlockNeedsLayout=!1,n(function(){var a,b,c=z.getElementsByTagName("body")[0];c&&(a=z.createElement("div"),a.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",b=z.createElement("div"),c.appendChild(a).appendChild(b),typeof b.style.zoom!==L&&(b.style.cssText="border:0;margin:0;width:1px;padding:1px;display:inline;zoom:1",(l.inlineBlockNeedsLayout=3===b.offsetWidth)&&(c.style.zoom=1)),c.removeChild(a),a=b=null)}),function(){var a=z.createElement("div");if(null==l.deleteExpando){l.deleteExpando=!0;try{delete a.test}catch(b){l.deleteExpando=!1}}a=null}(),n.acceptData=function(a){var b=n.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var N=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,O=/([A-Z])/g;function P(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(O,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:N.test(c)?n.parseJSON(c):c}catch(e){}n.data(a,b,c)}else c=void 0}return c}function Q(a){var b;for(b in a)if(("data"!==b||!n.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function R(a,b,d,e){if(n.acceptData(a)){var f,g,h=n.expando,i=a.nodeType,j=i?n.cache:a,k=i?a[h]:a[h]&&h;if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||n.guid++:h),j[k]||(j[k]=i?{}:{toJSON:n.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=n.extend(j[k],b):j[k].data=n.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[n.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[n.camelCase(b)])):f=g,f +}}function S(a,b,c){if(n.acceptData(a)){var d,e,f=a.nodeType,g=f?n.cache:a,h=f?a[n.expando]:n.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){n.isArray(b)?b=b.concat(n.map(b,n.camelCase)):b in d?b=[b]:(b=n.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!Q(d):!n.isEmptyObject(d))return}(c||(delete g[h].data,Q(g[h])))&&(f?n.cleanData([a],!0):l.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}n.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?n.cache[a[n.expando]]:a[n.expando],!!a&&!Q(a)},data:function(a,b,c){return R(a,b,c)},removeData:function(a,b){return S(a,b)},_data:function(a,b,c){return R(a,b,c,!0)},_removeData:function(a,b){return S(a,b,!0)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=n.data(f),1===f.nodeType&&!n._data(f,"parsedAttrs"))){c=g.length;while(c--)d=g[c].name,0===d.indexOf("data-")&&(d=n.camelCase(d.slice(5)),P(f,d,e[d]));n._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){n.data(this,a)}):arguments.length>1?this.each(function(){n.data(this,a,b)}):f?P(f,a,n.data(f,a)):void 0},removeData:function(a){return this.each(function(){n.removeData(this,a)})}}),n.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=n._data(a,b),c&&(!d||n.isArray(c)?d=n._data(a,b,n.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=n.queue(a,b),d=c.length,e=c.shift(),f=n._queueHooks(a,b),g=function(){n.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return n._data(a,c)||n._data(a,c,{empty:n.Callbacks("once memory").add(function(){n._removeData(a,b+"queue"),n._removeData(a,c)})})}}),n.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.lengthh;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},X=/^(?:checkbox|radio)$/i;!function(){var a=z.createDocumentFragment(),b=z.createElement("div"),c=z.createElement("input");if(b.setAttribute("className","t"),b.innerHTML="
a",l.leadingWhitespace=3===b.firstChild.nodeType,l.tbody=!b.getElementsByTagName("tbody").length,l.htmlSerialize=!!b.getElementsByTagName("link").length,l.html5Clone="<:nav>"!==z.createElement("nav").cloneNode(!0).outerHTML,c.type="checkbox",c.checked=!0,a.appendChild(c),l.appendChecked=c.checked,b.innerHTML="",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,a.appendChild(b),b.innerHTML="",l.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,l.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){l.noCloneEvent=!1}),b.cloneNode(!0).click()),null==l.deleteExpando){l.deleteExpando=!0;try{delete b.test}catch(d){l.deleteExpando=!1}}a=b=c=null}(),function(){var b,c,d=z.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(l[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),l[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var Y=/^(?:input|select|textarea)$/i,Z=/^key/,$=/^(?:mouse|contextmenu)|click/,_=/^(?:focusinfocus|focusoutblur)$/,ab=/^([^.]*)(?:\.(.+)|)$/;function bb(){return!0}function cb(){return!1}function db(){try{return z.activeElement}catch(a){}}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=n.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof n===L||a&&n.event.triggered===a.type?void 0:n.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(F)||[""],h=b.length;while(h--)f=ab.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=n.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=n.event.special[o]||{},l=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},i),(m=g[o])||(m=g[o]=[],m.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,l):m.push(l),n.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=n.hasData(a)&&n._data(a);if(r&&(k=r.events)){b=(b||"").match(F)||[""],j=b.length;while(j--)if(h=ab.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=m.length;while(f--)g=m[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(m.splice(f,1),g.selector&&m.delegateCount--,l.remove&&l.remove.call(a,g));i&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(k)&&(delete r.handle,n._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,m,o=[d||z],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||z,3!==d.nodeType&&8!==d.nodeType&&!_.test(p+n.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[n.expando]?b:new n.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:n.makeArray(c,[b]),k=n.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!n.isWindow(d)){for(i=k.delegateType||p,_.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||z)&&o.push(l.defaultView||l.parentWindow||a)}m=0;while((h=o[m++])&&!b.isPropagationStopped())b.type=m>1?i:k.bindType||p,f=(n._data(h,"events")||{})[b.type]&&n._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&n.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&n.acceptData(d)&&g&&d[p]&&!n.isWindow(d)){l=d[g],l&&(d[g]=null),n.event.triggered=p;try{d[p]()}catch(r){}n.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=n.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(n._data(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((n.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?n(c,this).index(i)>=0:n.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h]","i"),ib=/^\s+/,jb=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,kb=/<([\w:]+)/,lb=/
","
"],tr:[2,"","
"],col:[2,"","
"],td:[3,"","
"],_default:l.htmlSerialize?[0,"",""]:[1,"X
","
"]},tb=eb(z),ub=tb.appendChild(z.createElement("div"));sb.optgroup=sb.option,sb.tbody=sb.tfoot=sb.colgroup=sb.caption=sb.thead,sb.th=sb.td;function vb(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==L?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==L?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||n.nodeName(d,b)?f.push(d):n.merge(f,vb(d,b));return void 0===b||b&&n.nodeName(a,b)?n.merge([a],f):f}function wb(a){X.test(a.type)&&(a.defaultChecked=a.checked)}function xb(a,b){return n.nodeName(a,"table")&&n.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function yb(a){return a.type=(null!==n.find.attr(a,"type"))+"/"+a.type,a}function zb(a){var b=qb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function Ab(a,b){for(var c,d=0;null!=(c=a[d]);d++)n._data(c,"globalEval",!b||n._data(b[d],"globalEval"))}function Bb(a,b){if(1===b.nodeType&&n.hasData(a)){var c,d,e,f=n._data(a),g=n._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)n.event.add(b,c,h[c][d])}g.data&&(g.data=n.extend({},g.data))}}function Cb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!l.noCloneEvent&&b[n.expando]){e=n._data(b);for(d in e.events)n.removeEvent(b,d,e.handle);b.removeAttribute(n.expando)}"script"===c&&b.text!==a.text?(yb(b).text=a.text,zb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),l.html5Clone&&a.innerHTML&&!n.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&X.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}n.extend({clone:function(a,b,c){var d,e,f,g,h,i=n.contains(a.ownerDocument,a);if(l.html5Clone||n.isXMLDoc(a)||!hb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(ub.innerHTML=a.outerHTML,ub.removeChild(f=ub.firstChild)),!(l.noCloneEvent&&l.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||n.isXMLDoc(a)))for(d=vb(f),h=vb(a),g=0;null!=(e=h[g]);++g)d[g]&&Cb(e,d[g]);if(b)if(c)for(h=h||vb(a),d=d||vb(f),g=0;null!=(e=h[g]);g++)Bb(e,d[g]);else Bb(a,f);return d=vb(f,"script"),d.length>0&&Ab(d,!i&&vb(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,k,m=a.length,o=eb(b),p=[],q=0;m>q;q++)if(f=a[q],f||0===f)if("object"===n.type(f))n.merge(p,f.nodeType?[f]:f);else if(mb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(kb.exec(f)||["",""])[1].toLowerCase(),k=sb[i]||sb._default,h.innerHTML=k[1]+f.replace(jb,"<$1>")+k[2],e=k[0];while(e--)h=h.lastChild;if(!l.leadingWhitespace&&ib.test(f)&&p.push(b.createTextNode(ib.exec(f)[0])),!l.tbody){f="table"!==i||lb.test(f)?""!==k[1]||lb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)n.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}n.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),l.appendChecked||n.grep(vb(p,"input"),wb),q=0;while(f=p[q++])if((!d||-1===n.inArray(f,d))&&(g=n.contains(f.ownerDocument,f),h=vb(o.appendChild(f),"script"),g&&Ab(h),c)){e=0;while(f=h[e++])pb.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=n.expando,j=n.cache,k=l.deleteExpando,m=n.event.special;null!=(d=a[h]);h++)if((b||n.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)m[e]?n.event.remove(d,e):n.removeEvent(d,e,g.handle);j[f]&&(delete j[f],k?delete d[i]:typeof d.removeAttribute!==L?d.removeAttribute(i):d[i]=null,c.push(f))}}}),n.fn.extend({text:function(a){return W(this,function(a){return void 0===a?n.text(this):this.empty().append((this[0]&&this[0].ownerDocument||z).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=xb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=xb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?n.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||n.cleanData(vb(c)),c.parentNode&&(b&&n.contains(c.ownerDocument,c)&&Ab(vb(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&n.cleanData(vb(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&n.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return n.clone(this,a,b)})},html:function(a){return W(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(gb,""):void 0;if(!("string"!=typeof a||nb.test(a)||!l.htmlSerialize&&hb.test(a)||!l.leadingWhitespace&&ib.test(a)||sb[(kb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(jb,"<$1>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(n.cleanData(vb(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,n.cleanData(vb(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,k=this.length,m=this,o=k-1,p=a[0],q=n.isFunction(p);if(q||k>1&&"string"==typeof p&&!l.checkClone&&ob.test(p))return this.each(function(c){var d=m.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(k&&(i=n.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=n.map(vb(i,"script"),yb),f=g.length;k>j;j++)d=i,j!==o&&(d=n.clone(d,!0,!0),f&&n.merge(g,vb(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,n.map(g,zb),j=0;f>j;j++)d=g[j],pb.test(d.type||"")&&!n._data(d,"globalEval")&&n.contains(h,d)&&(d.src?n._evalUrl&&n._evalUrl(d.src):n.globalEval((d.text||d.textContent||d.innerHTML||"").replace(rb,"")));i=c=null}return this}}),n.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){n.fn[a]=function(a){for(var c,d=0,e=[],g=n(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),n(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Db,Eb={};function Fb(b,c){var d=n(c.createElement(b)).appendTo(c.body),e=a.getDefaultComputedStyle?a.getDefaultComputedStyle(d[0]).display:n.css(d[0],"display");return d.detach(),e}function Gb(a){var b=z,c=Eb[a];return c||(c=Fb(a,b),"none"!==c&&c||(Db=(Db||n(" + + + + + + + + + '; + } + else { + $cc_fields = ' + + + + + + + + + + + '; + } + if (MODULE_PAYMENT_NOVALNET_CC_SHOP_TYPE == 'ONECLICK' && + $sqlQuerySet = parent::getPaymentRefDetails($_SESSION['customer_id'], $this->code)) { + $cvc = ''; + $masked_acc_details = unserialize($sqlQuerySet['masked_acc_details']); + $masked_acc_details['cc_holder'] = html_entity_decode($masked_acc_details['cc_holder'], ENT_QUOTES, 'UTF-8'); + $form_show = isset($_SESSION['novalnet'][$this->code]['novalnet_ccchange_account']) ? $_SESSION['novalnet'][$this->code]['novalnet_ccchange_account'] : 1; + if (MODULE_PAYMENT_NOVALNET_CC_CVC_ON_ONE_CLICK_ACCEPT == 'True') { + $cvc = ' + + '; + } + $selection['fields'][] = array('title' => '', + 'field' => '' . MODULE_PAYMENT_NOVALNET_CC_NEW_ACCOUNT . ' +
+
' . MODULE_PAYMENT_NOVALNET_CC_FORM_CARD_CVC . ':'.tep_draw_input_field($this->code.'_cvc_ref', '', 'id="' . $this->code . '_cvc_ref" autocomplete=off onkeypress="return isNumberKey(event, false)" style="width:30px;"'). + '  CCV/CVC? + + +
+ + + + + + + + + '.$cvc + .' +
'.MODULE_PAYMENT_NOVALNET_CC_FORM_CARD_HOLDER.':'. $masked_acc_details['cc_holder'] . '
'.MODULE_PAYMENT_NOVALNET_CC_FORM_CARD_NO.':'.$masked_acc_details['cc_no'] .'
'.MODULE_PAYMENT_NOVALNET_CC_FORM_CARD_VALID_DATE.':'.$masked_acc_details['cc_exp_month'] . ' / ' . $masked_acc_details['cc_exp_year'] .' + +
'); + if (MODULE_PAYMENT_NOVALNET_CC_FORM_TYPE == 'Iframe') { + $selection['fields'][] = array('title' => '', + 'field' => '' ); + } else { + $selection['fields'][] = array('title' => '', + 'field' => '' + ); + } + } elseif(MODULE_PAYMENT_NOVALNET_CC_SHOP_TYPE != 'ONECLICK' || empty($sqlQuerySet) || MODULE_PAYMENT_NOVALNET_CC_FORM_TYPE != 'Redirect' || (MODULE_PAYMENT_NOVALNET_CC_FORM_TYPE == 'Redirect' && MODULE_PAYMENT_NOVALNET_CC_3D_SECURE != 'True')) { + if (MODULE_PAYMENT_NOVALNET_CC_FORM_TYPE == 'Iframe') { + $selection['fields'][] = array('title' => '', + 'field' => '' . $iframe . '
' . $pin_by_callback . '
' ); + } + else { + $selection['fields'][] = array('title' => MODULE_PAYMENT_NOVALNET_CC_FORM_CARD_HOLDER.' * ', + 'field' => tep_draw_input_field($this->code.'_holder', parent::customerName($order->customer), 'id="' . $this->code . '_holder" autocomplete=off onkeypress="return splCharValidate(event)" ') + ); + $selection['fields'][] = array('title' => MODULE_PAYMENT_NOVALNET_CC_FORM_CARD_NO.' * ', + 'field' => tep_draw_input_field($this->code . '_no', '', 'id="' . $this->code . '_no" autocomplete=off onkeypress="return isNumberKey(event, true);" ') + ); + $selection['fields'][] = array('title' => MODULE_PAYMENT_NOVALNET_CC_FORM_CARD_VALID_DATE.' * ', + 'field' => tep_draw_pull_down_menu($this->code.'_exp_month', parent::creditCardValidMonth(), '', 'id="' . $this->code . '_exp_month"').' '. + tep_draw_pull_down_menu($this->code . '_exp_year', parent::creditCardValidYear() , '', 'id="' . $this->code . '_exp_year"') + ); + + $selection['fields'][] = array('title' => MODULE_PAYMENT_NOVALNET_CC_FORM_CARD_CVC .' * ', + 'field' => tep_draw_input_field($this->code.'_cvc', '', 'id="' . $this->code . '_cvc" autocomplete=off onkeypress="return isNumberKey(event, false)" style="width:30px;"'). + '  CCV/CVC?'. $cc_fields + ); + if ( $this->fraud_module && $this->fraud_module_status ) { + $selection['fields'][] = NovalnetInterface::buildCallbackInputFields($this->fraud_module, $this->code); + } + } + } + } + return $selection; + } + + function pre_confirmation_check() { + global $order; + $post = $_POST; + if ( !empty($_SESSION['novalnet'][$this->code]['secondcall']) ) { + NovalnetValidation::validateUserInputsOnCallback($this->fraud_module, $this->code, $post); + } else { + $_SESSION['novalnet'][$this->code]['novalnet_ccchange_account'] = isset($post['novalnet_ccchange_account']) ? $post['novalnet_ccchange_account'] : ''; + if (isset($post['nn_payment_ref_tid']) && $post['novalnet_ccchange_account'] == 1) { + $_SESSION['novalnet'][$this->code]['cc_fldvalidator'] = isset($post['cc_fldvalidator']) ? $post['cc_fldvalidator'] : ''; + $_SESSION['novalnet'][$this->code]['nn_cc_hash'] = isset($post['nn_cc_hash']) ? $post['nn_cc_hash'] : ''; + if (MODULE_PAYMENT_NOVALNET_CC_CVC_ON_ONE_CLICK_ACCEPT == 'True' && trim($post['novalnet_cc_cvc_ref']) == '') { + $payment_error_return = 'error_message=Your credit card CVC/CVV/CID detail invalid'; + tep_redirect(tep_href_link(FILENAME_CHECKOUT_PAYMENT, $payment_error_return, 'SSL', true, false)); + } + $_SESSION['novalnet'][$this->code]['nn_payment_ref_enable'] = TRUE; + $_SESSION['novalnet'][$this->code]['nn_payment_ref_tid'] = $post['nn_payment_ref_tid']; + return true; + } + if (MODULE_PAYMENT_NOVALNET_CC_FORM_TYPE == 'Redirect' && MODULE_PAYMENT_NOVALNET_CC_3D_SECURE != 'True') { + return true; + } + $this->fraud_module_status = NovalnetInterface::setFraudModuleStatus($this->code, (array)$order, $this->fraud_module); + NovalnetValidation::validateUserInputs($this->fraud_module, $this->fraud_module_status, $this->code, $post); + } + return false; + } + + function confirmation() { + global $order; + if ( !empty($_SESSION['novalnet'][$this->code]['secondcall']) ) { + NovalnetValidation::validateAmountOnCallback($this->code, $this->fraud_module); + } + $_SESSION['novalnet'][$this->code]['payment_amount'] = NovalnetInterface::getPaymentAmount((array)$order, $this->code); + return false; + } + + function process_button() { + global $order; + $post = $_REQUEST; + if(MODULE_PAYMENT_NOVALNET_CC_3D_SECURE == 'True' || (MODULE_PAYMENT_NOVALNET_CC_FORM_TYPE == 'Redirect' && MODULE_PAYMENT_NOVALNET_CC_3D_SECURE != 'True')) { + if ( isset($_SESSION['novalnet'][$this->code]['payment_amount']) ) { + $_SESSION['novalnet'][$this->code]['order_obj'] = array_merge((array)$order, $post, array('payment_amount' => $_SESSION['novalnet'][$this->code]['payment_amount'])); + $before_process_response = parent::novalnet_before_process($_SESSION['novalnet'][$this->code]['order_obj']); // Perform real time 3d secure payment transaction + $before_process_response .= NovalnetValidation::confirmButtonDisableActivate(); + return $before_process_response; + } else { + $payment_error_return = 'payment_error=' . $this->code . '&error=' . MODULE_PAYMENT_NOVALNET_PLEASE_SPECIFY_AMOUNT_ERROR_MESSAGE; + tep_redirect(self::setUTFText(tep_href_link(FILENAME_CHECKOUT_PAYMENT, $payment_error_return, 'SSL', true, false))); + } + } else { + if ( !empty($post[$this->code . '_new_pin']) ) { + $new_pin_response = NovalnetInterface::doCallbackRequest('TRANSMIT_PIN_AGAIN', $this->code); + NovalnetValidation::validateNewPinResponse($new_pin_response, 'TRANSMIT_PIN_AGAIN', $this->code); + } elseif ( isset($_SESSION['novalnet'][$this->code]['payment_amount']) ) { + $novalnet_order_details = isset($_SESSION['novalnet'][$this->code]) ? $_SESSION['novalnet'][$this->code] : array(); + $_SESSION['novalnet'][$this->code] = array_merge($novalnet_order_details, $post, array('payment_amount' => $_SESSION['novalnet'][$this->code]['payment_amount'])); + } else { + $payment_error_return = 'payment_error=' . $this->code . '&error=' . MODULE_PAYMENT_NOVALNET_PLEASE_SPECIFY_AMOUNT_ERROR_MESSAGE; + tep_redirect(self::setUTFText(tep_href_link(FILENAME_CHECKOUT_PAYMENT, $payment_error_return, 'SSL', true, false))); + } + } + return NovalnetValidation::confirmButtonDisableActivate(); + } + + function before_process() { + global $order; + $post = $_REQUEST; + if (MODULE_PAYMENT_NOVALNET_CC_3D_SECURE == 'True' || MODULE_PAYMENT_NOVALNET_CC_FORM_TYPE == 'Redirect') { + if ( isset($post['tid']) ) { // 3D Secure response validation + $before_process_response = parent::validateRedirectResponse((array)$order, $this->code, $post); + $order->info['comments'] = $before_process_response['comments']; + } else { + $payment_error_return = 'error_message=' . utf8_decode($post['status_desc']); + tep_redirect(self::setUTFText(tep_href_link(FILENAME_CHECKOUT_PAYMENT, $payment_error_return, 'SSL', true, false))); + } + } else{ + $this->fraud_module_status = NovalnetInterface::setFraudModuleStatus($this->code, (array)$order, $this->fraud_module); + $this->fraud_module_status = isset($_SESSION['novalnet'][$this->code]['nn_payment_ref_enable']) ? FALSE:$this->fraud_module_status; + $param_inputs = array_merge($_SESSION['novalnet'][$this->code], (array)$order, array('fraud_module' => $this->fraud_module,'fraud_module_status' => $this->fraud_module_status)); + if (!empty($param_inputs['secondcall']) ) { + NovalnetInterface::doConfirmPayment($this->code, $this->fraud_module); + } else { + $before_process_response = parent::novalnet_before_process($param_inputs); // Perform real time normal cc payment transaction + NovalnetInterface::gotoPaymentOnCallback($this->code, $this->fraud_module, $this->fraud_module_status); + } + $order->info['comments'] = $_SESSION['novalnet'][$this->code]['nntrxncomments']; + } + } + + function after_process() { + global $insert_id; + parent::updateOrderStatus($insert_id, $this->code); + // Perform paygate second call for transaction confirmations / order_no update + parent::doSecondCallProcess(array( 'payment' => $this->code, + 'order_no' => $insert_id + )); + } + + function javascript_validation() { + return false; + } + + function check() { + return parent::checkInstalledStatus($this->code); + } + + function install() { + parent::installModule($this->code); + } + + function remove() { + parent::uninstallModule($this->code); + } + + function keys() { + return parent::novalnetKeys($this->code); + } + + function get_error() { + global $HTTP_GET_VARS; + $error = array('title' => '', + 'error' => ((isset($HTTP_GET_VARS['error'])) ? stripslashes(urldecode($HTTP_GET_VARS['error'])) : '')); + return $error; + } +} +?> diff --git a/includes/modules/payment/novalnet_config.php b/includes/modules/payment/novalnet_config.php new file mode 100644 index 0000000..ef77877 --- /dev/null +++ b/includes/modules/payment/novalnet_config.php @@ -0,0 +1,50 @@ +code = 'novalnet_config'; + $this->title = MODULE_PAYMENT_NOVALNET_CONFIG_TITLE; + $this->description = MODULE_PAYMENT_NOVALNET_CONFIG_DESC; + $this->sort_order = 0; + $this->enabled = false; + } + + function check() { + return parent::checkInstalledStatus($this->code); + } + + function install() { + parent::installModule($this->code); + } + + function remove() { + parent::uninstallModule($this->code); + } + + function keys() { + $language = $_SESSION['language'] == 'german' ? 'DE' : 'EN'; + echo ''; + echo ''; + echo ''; + echo ''; + return parent::novalnetKeys($this->code); + } +} +?> diff --git a/includes/modules/payment/novalnet_eps.php b/includes/modules/payment/novalnet_eps.php new file mode 100644 index 0000000..7dcc0de --- /dev/null +++ b/includes/modules/payment/novalnet_eps.php @@ -0,0 +1,129 @@ +code = 'novalnet_eps'; + $this->form_action_url = NovalnetInterface::getPaygateURL($this->code); + $this->title = $this->public_title = MODULE_PAYMENT_NOVALNET_EPS_TEXT_TITLE; + $this->description = MODULE_PAYMENT_NOVALNET_REDIRECT_DESC; + $this->sort_order = defined('MODULE_PAYMENT_NOVALNET_EPS_SORT_ORDER') && MODULE_PAYMENT_NOVALNET_EPS_SORT_ORDER != '' ? MODULE_PAYMENT_NOVALNET_EPS_SORT_ORDER : 0; + if ( strpos(MODULE_PAYMENT_INSTALLED,$this->code) !== false ) { + $this->enabled = (MODULE_PAYMENT_NOVALNET_EPS_ENABLE_MODULE == 'True'); + } + } + + function selection() { + global $order, $payment; + parent::validatecallbacksession(); + if ( !parent::validateMerchantAPIConf((array)$order, $this->code, $this->enabled) ) { + return false; + } + if ( empty($payment) && MODULE_PAYMENT_NOVALNET_LAST_SUCCESSFULL_PAYMENT_SELECTION == 'True' ) { + if ( parent::getLastSuccessTransPayment($order->customer['email_address'], $this->code) ) { + $payment = $this->code; + } + } + $endcustomerinfo = trim(strip_tags(MODULE_PAYMENT_NOVALNET_EPS_ENDCUSTOMER_INFO)); + $test_mode = NovalnetInterface::getPaymentTestModeStatus($this->code); + $description = '
'. $this->description; + $description .= ($endcustomerinfo != '') ? '
'.$endcustomerinfo : ''; + $description .= ($test_mode == 1) ? '
' . utf8_encode(MODULE_PAYMENT_NOVALNET_TEST_MODE_MSG) : ''; + + $selection['id'] = $this->code; + $selection['module'] = MODULE_PAYMENT_NOVALNET_EPS_PUBLIC_TITLE . $description; + return $selection; + } + + function pre_confirmation_check() { + return false; + } + + function confirmation() { + global $order; + + $_SESSION['novalnet'][$this->code]['payment_amount'] = NovalnetInterface::getPaymentAmount((array)$order, $this->code); + return false; + } + + function process_button() { + global $order; + + if ( isset($_SESSION['novalnet'][$this->code]['payment_amount']) ) { + $_SESSION['novalnet'][$this->code]['order_obj'] = array_merge((array)$order, array('payment' => $this->code), array('payment_amount' => $_SESSION['novalnet'][$this->code]['payment_amount'])); + $before_process_response = parent::novalnet_before_process($_SESSION['novalnet'][$this->code]['order_obj']); // Perform real time payment transaction + $before_process_response .= NovalnetValidation::confirmButtonDisableActivate(); + return $before_process_response; + } + else { + $payment_error_return = 'payment_error=' . $this->code . '&error=' . MODULE_PAYMENT_NOVALNET_PLEASE_SPECIFY_AMOUNT_ERROR_MESSAGE; + tep_redirect(self::setUTFText(tep_href_link(FILENAME_CHECKOUT_PAYMENT, $payment_error_return, 'SSL', true, false))); + } + } + + function before_process() { + global $order; + $post = $_REQUEST; + if (isset($post['tid'])) { // Response validation + $before_process_response = parent::validateRedirectResponse((array)$order, $this->code, $post); + $order->info['comments'] = $before_process_response['comments']; + } + } + + function after_process() { + global $insert_id; + + parent::updateOrderStatus($insert_id, $this->code); + // Perform paygate second call for transaction confirmations / order_no update + parent::doSecondCallProcess(array( 'payment' => $this->code, + 'order_no' => $insert_id + )); + } + + function javascript_validation() { + return false; + } + + function check() { + return parent::checkInstalledStatus($this->code); + } + + function install() { + parent::installModule($this->code); + } + + function remove() { + parent::uninstallModule($this->code); + } + + function keys() { + return parent::novalnetKeys($this->code); + } + + function get_error() { + global $HTTP_GET_VARS; + $error = array('title' => '', + 'error' => ((isset($HTTP_GET_VARS['error'])) ? stripslashes(urldecode($HTTP_GET_VARS['error'])) : '')); + return $error; + } +} +?> diff --git a/includes/modules/payment/novalnet_ideal.php b/includes/modules/payment/novalnet_ideal.php new file mode 100644 index 0000000..03a792d --- /dev/null +++ b/includes/modules/payment/novalnet_ideal.php @@ -0,0 +1,125 @@ +code = 'novalnet_ideal'; + $this->form_action_url = NovalnetInterface::getPaygateURL($this->code); + $this->title = $this->public_title = MODULE_PAYMENT_NOVALNET_IDEAL_TEXT_TITLE; + $this->description = MODULE_PAYMENT_NOVALNET_REDIRECT_DESC; + $this->sort_order = defined('MODULE_PAYMENT_NOVALNET_IDEAL_SORT_ORDER') && MODULE_PAYMENT_NOVALNET_IDEAL_SORT_ORDER != '' ? MODULE_PAYMENT_NOVALNET_IDEAL_SORT_ORDER : 0; + if ( strpos(MODULE_PAYMENT_INSTALLED,$this->code) !== false ) { + $this->enabled = (MODULE_PAYMENT_NOVALNET_IDEAL_ENABLE_MODULE == 'True'); + } + } + + function selection() { + global $order, $payment; + parent::validatecallbacksession(); + if ( !parent::validateMerchantAPIConf((array)$order, $this->code, $this->enabled) ) { + return false; + } + if ( empty($payment) && MODULE_PAYMENT_NOVALNET_LAST_SUCCESSFULL_PAYMENT_SELECTION == 'True' ) { + if ( parent::getLastSuccessTransPayment($order->customer['email_address'], $this->code) ) { + $payment = $this->code; + } + } + $endcustomerinfo = trim(strip_tags(MODULE_PAYMENT_NOVALNET_IDEAL_ENDCUSTOMER_INFO)); + $test_mode = NovalnetInterface::getPaymentTestModeStatus($this->code); + $description = '
'. $this->description; + $description .= ($endcustomerinfo != '') ? '
'.$endcustomerinfo : ''; + $description .= ($test_mode == 1) ? '
' . utf8_encode(MODULE_PAYMENT_NOVALNET_TEST_MODE_MSG) : ''; + + $selection['id'] = $this->code; + $selection['module'] = MODULE_PAYMENT_NOVALNET_IDEAL_PUBLIC_TITLE . $description; + return $selection; + } + + function pre_confirmation_check() { + return false; + } + + function confirmation() { + global $order; + $_SESSION['novalnet'][$this->code]['payment_amount'] = NovalnetInterface::getPaymentAmount((array)$order, $this->code); + return false; + } + + function process_button() { + global $order; + if ( isset($_SESSION['novalnet'][$this->code]['payment_amount']) ) { + $_SESSION['novalnet'][$this->code]['order_obj'] = array_merge((array)$order, array('payment' => $this->code), array('payment_amount' => $_SESSION['novalnet'][$this->code]['payment_amount'])); + $before_process_response = parent::novalnet_before_process($_SESSION['novalnet'][$this->code]['order_obj']); // Perform real time payment transaction + $before_process_response .= NovalnetValidation::confirmButtonDisableActivate(); + return $before_process_response; + } else { + $payment_error_return = 'payment_error=' . $this->code . '&error=' . MODULE_PAYMENT_NOVALNET_PLEASE_SPECIFY_AMOUNT_ERROR_MESSAGE; + tep_redirect(self::setUTFText(tep_href_link(FILENAME_CHECKOUT_PAYMENT, $payment_error_return, 'SSL', true, false))); + } + } + + function before_process() { + global $order; + $post = $_REQUEST; + if (isset($post['tid'])) { // Response validation + $before_process_response = parent::validateRedirectResponse((array)$order, $this->code, $post); + $order->info['comments'] = $before_process_response['comments']; + } + } + + function after_process() { + global $insert_id; + parent::updateOrderStatus($insert_id, $this->code); + // Perform paygate second call for transaction confirmations / order_no update + parent::doSecondCallProcess(array( 'payment' => $this->code, + 'order_no' => $insert_id + )); + } + + function javascript_validation() { + return false; + } + + function check() { + return parent::checkInstalledStatus($this->code); + } + + function install() { + parent::installModule($this->code); + } + + function remove() { + parent::uninstallModule($this->code); + } + + function keys() { + return parent::novalnetKeys($this->code); + } + + function get_error() { + global $HTTP_GET_VARS; + $error = array('title' => '', + 'error' => ((isset($HTTP_GET_VARS['error'])) ? stripslashes(urldecode($HTTP_GET_VARS['error'])) : '')); + return $error; + } +} +?> diff --git a/includes/modules/payment/novalnet_invoice.php b/includes/modules/payment/novalnet_invoice.php new file mode 100644 index 0000000..15f8c94 --- /dev/null +++ b/includes/modules/payment/novalnet_invoice.php @@ -0,0 +1,160 @@ +code = 'novalnet_invoice'; + $this->title = $this->public_title = MODULE_PAYMENT_NOVALNET_INVOICE_TEXT_TITLE; + $this->description = MODULE_PAYMENT_NOVALNET_INVOICE_DESC; + $this->sort_order = defined('MODULE_PAYMENT_NOVALNET_INVOICE_SORT_ORDER') && MODULE_PAYMENT_NOVALNET_INVOICE_SORT_ORDER != '' ? MODULE_PAYMENT_NOVALNET_INVOICE_SORT_ORDER : 0; + if ( strpos(MODULE_PAYMENT_INSTALLED,$this->code) !== false ) { + $this->enabled = (MODULE_PAYMENT_NOVALNET_INVOICE_ENABLE_MODULE == 'True'); + $this->fraud_module = ((MODULE_PAYMENT_NOVALNET_INVOICE_ENABLE_FRAUDMODULE == 'False') ? false : MODULE_PAYMENT_NOVALNET_INVOICE_ENABLE_FRAUDMODULE); + } + } + + function selection() { + global $order, $payment; + parent::validatecallbacksession(); + if ( !parent::validateMerchantAPIConf((array)$order, $this->code, $this->enabled) || !parent::validateCallbackStatus($this->code, $this->fraud_module) ) { + return false; + } + if ( !parent::validateMerchantAPIConf((array)$order, $this->code, $this->enabled) || !parent::validateCallbackStatus($this->code, $this->fraud_module) ) { + return false; + } + $this->fraud_module_status = NovalnetInterface::setFraudModuleStatus($this->code, (array)$order, $this->fraud_module); + if ( empty($payment) && MODULE_PAYMENT_NOVALNET_LAST_SUCCESSFULL_PAYMENT_SELECTION == 'True' ) { + if ( parent::getLastSuccessTransPayment($order->customer['email_address'], $this->code) ) { + $payment = $this->code; + } + } + if(isset($_SESSION['payment']) && $_SESSION['payment'] != $this->code && isset($_SESSION['novalnet'][$this->code])) { unset($_SESSION['novalnet'][$this->code]); } + $endcustomerinfo = trim(strip_tags(MODULE_PAYMENT_NOVALNET_INVOICE_ENDCUSTOMER_INFO)); + $test_mode = NovalnetInterface::getPaymentTestModeStatus($this->code); + $description = '
'. $this->description; + $description .= ($endcustomerinfo != '') ? '
'.$endcustomerinfo : ''; + $description .= ($test_mode == 1) ? '
' . utf8_encode(MODULE_PAYMENT_NOVALNET_TEST_MODE_MSG) : ''; + + $selection['id'] = $this->code; + $selection['module'] = MODULE_PAYMENT_NOVALNET_INVOICE_PUBLIC_TITLE . $description; + if ( $this->fraud_module && $this->fraud_module_status ) { + if ( isset($_SESSION['novalnet'][$this->code]['tid'])) { + $selection['fields'] = NovalnetInterface::buildCallbackFieldsAfterResponse($this->fraud_module,$this->code); + } + else { + $selection['fields'][] = NovalnetInterface::buildCallbackInputFields($this->fraud_module, $this->code); + } + } + return $selection; + } + + function pre_confirmation_check() { + global $order; + $post = $_POST; + $this->fraud_module_status = NovalnetInterface::setFraudModuleStatus($this->code, (array)$order, $this->fraud_module); + if ( !empty($_SESSION['novalnet'][$this->code]['secondcall']) ) { + NovalnetValidation::validateUserInputsOnCallback($this->fraud_module, $this->code, $post); + } else { + NovalnetValidation::validateUserInputs($this->fraud_module, $this->fraud_module_status, $this->code, $post); + } + return false; + } + + function confirmation() { + global $order; + + if ( !empty($_SESSION['novalnet'][$this->code]['secondcall']) ) { + NovalnetValidation::validateAmountOnCallback($this->code, $this->fraud_module); + } + $_SESSION['novalnet'][$this->code]['payment_amount'] = NovalnetInterface::getPaymentAmount((array)$order, $this->code); + return false; + } + + function process_button() { + $post = $_POST; + + if ( !empty($post[$this->code . '_new_pin']) ) { + $new_pin_response = NovalnetInterface::doCallbackRequest('TRANSMIT_PIN_AGAIN', $this->code); + NovalnetValidation::validateNewPinResponse($new_pin_response, 'TRANSMIT_PIN_AGAIN', $this->code); + } elseif ( isset($_SESSION['novalnet'][$this->code]['payment_amount']) ) { + $novalnet_order_details = isset($_SESSION['novalnet'][$this->code]) ? $_SESSION['novalnet'][$this->code] : array(); + $_SESSION['novalnet'][$this->code] = array_merge($novalnet_order_details, $post, array('payment' => $this->code), array('payment_amount' => $_SESSION['novalnet'][$this->code]['payment_amount'])); + } else { + $payment_error_return = 'payment_error=' . $this->code . '&error=' . MODULE_PAYMENT_NOVALNET_PLEASE_SPECIFY_AMOUNT_ERROR_MESSAGE; + tep_redirect(self::setUTFText(tep_href_link(FILENAME_CHECKOUT_PAYMENT, $payment_error_return, 'SSL', true, false))); + } + return NovalnetValidation::confirmButtonDisableActivate(); + } + + function before_process() { + global $order; + + $this->fraud_module_status = NovalnetInterface::setFraudModuleStatus($this->code, (array)$order, $this->fraud_module); + $param_inputs = array_merge((array)$order, $_SESSION['novalnet'][$this->code], array('fraud_module' => $this->fraud_module, 'fraud_module_status' => $this->fraud_module_status)); + if (!empty($param_inputs['secondcall'])) { + NovalnetInterface::doConfirmPayment($this->code ,$this->fraud_module); + } else { + parent::novalnet_before_process($param_inputs); + NovalnetInterface::gotoPaymentOnCallback($this->code, $this->fraud_module, $this->fraud_module_status); + } // Perform real time payment transaction + + $order->info['comments'] = $_SESSION['novalnet'][$this->code]['nntrxncomments']; + } + + function after_process() { + global $insert_id; + + parent::updateOrderStatus($insert_id, $this->code); + // Perform paygate second call for transaction confirmations / order_no update + parent::doSecondCallProcess(array( 'payment' => $this->code, + 'order_no' => $insert_id + )); + } + + function javascript_validation() { + return false; + } + + function check() { + return parent::checkInstalledStatus($this->code); + } + + function install() { + parent::installModule($this->code); + } + + function remove() { + parent::uninstallModule($this->code); + } + + function keys() { + return parent::novalnetKeys($this->code); + } + + function get_error() { + global $HTTP_GET_VARS; + $error = array('title' => '', + 'error' => ((isset($HTTP_GET_VARS['error'])) ? stripslashes(urldecode($HTTP_GET_VARS['error'])) : '')); + return $error; + } +} +?> diff --git a/includes/modules/payment/novalnet_paypal.php b/includes/modules/payment/novalnet_paypal.php new file mode 100644 index 0000000..092c604 --- /dev/null +++ b/includes/modules/payment/novalnet_paypal.php @@ -0,0 +1,128 @@ +code = 'novalnet_paypal'; + $this->form_action_url = NovalnetInterface::getPaygateURL($this->code); + $this->title = $this->public_title = MODULE_PAYMENT_NOVALNET_PAYPAL_TEXT_TITLE; + $this->description = MODULE_PAYMENT_NOVALNET_REDIRECT_DESC; + $this->sort_order = defined('MODULE_PAYMENT_NOVALNET_PAYPAL_SORT_ORDER') && MODULE_PAYMENT_NOVALNET_PAYPAL_SORT_ORDER != '' ? MODULE_PAYMENT_NOVALNET_PAYPAL_SORT_ORDER : 0; + if ( strpos(MODULE_PAYMENT_INSTALLED,$this->code) !== false ) { + $this->enabled = (MODULE_PAYMENT_NOVALNET_PAYPAL_ENABLE_MODULE == 'True'); + } + } + + function selection() { + global $order, $payment; + parent::validatecallbacksession(); + if ( !parent::validateMerchantAPIConf((array)$order, $this->code, $this->enabled) ) { + return false; + } + if ( empty($payment) && MODULE_PAYMENT_NOVALNET_LAST_SUCCESSFULL_PAYMENT_SELECTION == 'True' ) { + if ( parent::getLastSuccessTransPayment($order->customer['email_address'], $this->code) ) { + $payment = $this->code; + } + } + + $endcustomerinfo = trim(strip_tags(MODULE_PAYMENT_NOVALNET_PAYPAL_ENDCUSTOMER_INFO)); + $test_mode = NovalnetInterface::getPaymentTestModeStatus($this->code); + $description = '
'. $this->description; + $description .= ($endcustomerinfo != '') ? '
'.$endcustomerinfo : ''; + $description .= ($test_mode == 1) ? '
' . utf8_encode(MODULE_PAYMENT_NOVALNET_TEST_MODE_MSG) : ''; + + $selection['id'] = $this->code; + $selection['module'] = MODULE_PAYMENT_NOVALNET_PAYPAL_PUBLIC_TITLE . $description; + return $selection; + } + + function pre_confirmation_check() { + return false; + } + + function confirmation() { + global $order; + $_SESSION['novalnet'][$this->code]['payment_amount'] = NovalnetInterface::getPaymentAmount((array)$order, $this->code); + return false; + } + + function process_button() { + global $order; + + if ( isset($_SESSION['novalnet'][$this->code]['payment_amount']) ) { + $_SESSION['novalnet'][$this->code]['order_obj'] = array_merge((array)$order, array('payment' => $this->code), array('payment_amount' => $_SESSION['novalnet'][$this->code]['payment_amount'])); + $before_process_response = parent::novalnet_before_process($_SESSION['novalnet'][$this->code]['order_obj']); // Perform real time payment transaction + $before_process_response .= NovalnetValidation::confirmButtonDisableActivate(); + return $before_process_response; + } else { + $payment_error_return = 'payment_error=' . $this->code . '&error=' . MODULE_PAYMENT_NOVALNET_PLEASE_SPECIFY_AMOUNT_ERROR_MESSAGE; + tep_redirect(self::setUTFText(tep_href_link(FILENAME_CHECKOUT_PAYMENT, $payment_error_return, 'SSL', true, false))); + } + } + + function before_process() { + global $order; + $post = $_REQUEST; + if ( isset($post['tid']) ) { // Response validation + $before_process_response = parent::validateRedirectResponse((array)$order, $this->code, $post); + $order->info['comments'] = $before_process_response['comments']; + } + } + + function after_process() { + global $insert_id; + + parent::updateOrderStatus($insert_id, $this->code); + // Perform paygate second call for transaction confirmations / order_no update + parent::doSecondCallProcess(array( 'payment' => $this->code, + 'order_no' => $insert_id + )); + } + + function javascript_validation() { + return false; + } + + function check() { + return parent::checkInstalledStatus($this->code); + } + + function install() { + parent::installModule($this->code); + } + + function remove() { + parent::uninstallModule($this->code); + } + + function keys() { + return parent::novalnetKeys($this->code); + } + + function get_error() { + global $HTTP_GET_VARS; + $error = array('title' => '', + 'error' => ((isset($HTTP_GET_VARS['error'])) ? stripslashes(urldecode($HTTP_GET_VARS['error'])) : '')); + return $error; + } +} +?> diff --git a/includes/modules/payment/novalnet_prepayment.php b/includes/modules/payment/novalnet_prepayment.php new file mode 100644 index 0000000..53d93df --- /dev/null +++ b/includes/modules/payment/novalnet_prepayment.php @@ -0,0 +1,123 @@ +code = 'novalnet_prepayment'; + $this->title = $this->public_title = MODULE_PAYMENT_NOVALNET_PREPAYMENT_TEXT_TITLE; + $this->description = MODULE_PAYMENT_NOVALNET_PREPAYMENT_DESC; + $this->sort_order = defined('MODULE_PAYMENT_NOVALNET_PREPAYMENT_SORT_ORDER') && MODULE_PAYMENT_NOVALNET_PREPAYMENT_SORT_ORDER != '' ? MODULE_PAYMENT_NOVALNET_PREPAYMENT_SORT_ORDER : 0; + if ( strpos(MODULE_PAYMENT_INSTALLED,$this->code) !== false ) { + $this->enabled = (MODULE_PAYMENT_NOVALNET_PREPAYMENT_ENABLE_MODULE == 'True'); + } + } + + function selection() { + global $order, $payment; + parent::validatecallbacksession(); + if (!parent::validateMerchantAPIConf((array)$order, $this->code, $this->enabled)) + return false; + + if ( empty($payment) && MODULE_PAYMENT_NOVALNET_LAST_SUCCESSFULL_PAYMENT_SELECTION == 'True' ) { + if ( parent::getLastSuccessTransPayment($order->customer['email_address'], $this->code) ) { + $payment = $this->code; + } + } + $endcustomerinfo = trim(strip_tags(MODULE_PAYMENT_NOVALNET_PREPAYMENT_ENDCUSTOMER_INFO)); + $test_mode = NovalnetInterface::getPaymentTestModeStatus($this->code); + $description = '
'. $this->description; + $description .= ($endcustomerinfo != '') ? '
'.$endcustomerinfo : ''; + $description .= ($test_mode == 1) ? '
' . utf8_encode(MODULE_PAYMENT_NOVALNET_TEST_MODE_MSG) : ''; + + $selection['id'] = $this->code; + $selection['module'] = MODULE_PAYMENT_NOVALNET_PREPAYMENT_PUBLIC_TITLE . $description; + return $selection; + } + + function pre_confirmation_check() { + return false; + } + + function confirmation() { + global $order; + $_SESSION['novalnet'][$this->code]['payment_amount'] = NovalnetInterface::getPaymentAmount((array)$order, $this->code, $this->code); + return false; + } + + function process_button() { + $post = $_POST; + if ( isset($_SESSION['novalnet'][$this->code]['payment_amount']) ) { + $_SESSION['novalnet'][$this->code] = array_merge($post, array('payment_amount' => $_SESSION['novalnet'][$this->code]['payment_amount'])); + } else { + $payment_error_return = 'payment_error=' . $this->code . '&error=' . MODULE_PAYMENT_NOVALNET_PLEASE_SPECIFY_AMOUNT_ERROR_MESSAGE; + tep_redirect(self::setUTFText(tep_href_link(FILENAME_CHECKOUT_PAYMENT, $payment_error_return, 'SSL', true, false))); + } + return NovalnetValidation::confirmButtonDisableActivate(); + } + + function before_process() { + global $order; + if ( isset($_SESSION['novalnet'][$this->code]['payment_amount']) ) { + $before_process_response = parent::novalnet_before_process(array_merge((array)$order, $_SESSION['novalnet'][$this->code])); // Perform real time payment transaction + } else { + $before_process_response = parent::novalnet_before_process((array)$order); // Perform real time payment transaction + } + $order->info['comments'] = $before_process_response['comments']; + } + + function after_process() { + global $insert_id; + parent::updateOrderStatus($insert_id, $this->code); + // Perform paygate second call for transaction confirmations / order_no update + parent::doSecondCallProcess(array( 'payment' => $this->code, + 'order_no' => $insert_id + )); + } + + function javascript_validation() { + return false; + } + + function check() { + return parent::checkInstalledStatus($this->code); + } + + function install() { + parent::installModule($this->code); + } + + function remove() { + parent::uninstallModule($this->code); + } + + function keys() { + return parent::novalnetKeys($this->code); + } + + function get_error() { + global $HTTP_GET_VARS; + $error = array('title' => '', + 'error' => ((isset($HTTP_GET_VARS['error'])) ? stripslashes(urldecode($HTTP_GET_VARS['error'])) : '')); + return $error; + } +} +?> diff --git a/includes/modules/payment/novalnet_sepa.php b/includes/modules/payment/novalnet_sepa.php new file mode 100644 index 0000000..9e4c27b --- /dev/null +++ b/includes/modules/payment/novalnet_sepa.php @@ -0,0 +1,292 @@ +code = 'novalnet_sepa'; + $this->title = $this->public_title = MODULE_PAYMENT_NOVALNET_SEPA_TEXT_TITLE; + $this->description = MODULE_PAYMENT_NOVALNET_SEPA_DESC; + $this->sort_order = defined('MODULE_PAYMENT_NOVALNET_SEPA_SORT_ORDER') && MODULE_PAYMENT_NOVALNET_SEPA_SORT_ORDER != '' ? MODULE_PAYMENT_NOVALNET_SEPA_SORT_ORDER : 0; + if ( strpos(MODULE_PAYMENT_INSTALLED,$this->code) !== false ) { + $this->enabled = (MODULE_PAYMENT_NOVALNET_SEPA_ENABLE_MODULE == 'True'); + $this->fraud_module = ((MODULE_PAYMENT_NOVALNET_SEPA_ENABLE_FRAUDMODULE == 'False') ? false : MODULE_PAYMENT_NOVALNET_SEPA_ENABLE_FRAUDMODULE); + } + } + + function selection() { + global $order, $payment; + parent::validatecallbacksession(); + if ( !parent::validateMerchantAPIConf((array)$order, $this->code, $this->enabled) || !parent::validateCallbackStatus($this->code, $this->fraud_module) ) { + return false; + } + if ( empty($payment) && (MODULE_PAYMENT_NOVALNET_LAST_SUCCESSFULL_PAYMENT_SELECTION == 'True' || MODULE_PAYMENT_NOVALNET_REFILL_BY_SUCCESSFUL_ORDER == 'True') ) { + if ( parent::getLastSuccessTransPayment($order->customer['email_address'], $this->code) ) { + $payment = $this->code; + } + } + if ( isset($_SESSION['payment']) && $_SESSION['payment'] != $this->code && isset($_SESSION['novalnet'][$this->code]) ) { + unset($_SESSION['novalnet'][$this->code]); + } + + $this->fraud_module_status = NovalnetInterface::setFraudModuleStatus($this->code, (array)$order, $this->fraud_module); + + $endcustomerinfo = trim(strip_tags(MODULE_PAYMENT_NOVALNET_SEPA_ENDCUSTOMER_INFO)); + $test_mode = NovalnetInterface::getPaymentTestModeStatus($this->code); + $description = '
'. $this->description. ''; + $description .= ($endcustomerinfo != '') ? '
'.$endcustomerinfo : ''; + $description .= ($test_mode == 1) ? '
' . utf8_encode(MODULE_PAYMENT_NOVALNET_TEST_MODE_MSG) : ''; + + $selection['id'] = $this->code; + $selection['module'] = MODULE_PAYMENT_NOVALNET_SEPA_PUBLIC_TITLE . $description; + $company = ((!empty($order->billing['company'])) ? $order->billing['company'] : $order->customer['company']); + if ( isset($_SESSION['novalnet'][$this->code]['tid']) && $this->fraud_module && $this->fraud_module_status ) { + $selection['fields'] = NovalnetInterface::buildCallbackFieldsAfterResponse($this->fraud_module,$this->code); + } else { + $data = array(); + $data['vendor'] = parent::getVendorID(); + $data['auth_code'] = parent::getVendorAuthCode(); + NovalnetCore::getAffDetails($data); + $pin_by_callback = ''; + if (in_array($this->fraud_module ,array('EMAIL', 'CALLBACK', 'SMS'))) { + $fraud_module_value = array('EMAIL' => array('name' =>'_fraud_email', 'value' => 'email_address'), 'CALLBACK' => array('name' =>'_fraud_tel', 'value' => 'telephone'), 'SMS' => array('name' =>'_fraud_mobile', 'value' => 'mobile')); + $pin_by_callback = constant('MODULE_PAYMENT_NOVALNET_FRAUDMODULE_'. $this->fraud_module.'_INPUT_TITLE').' * + '. tep_draw_input_field($this->code.$fraud_module_value[$this->fraud_module]['name'], (isset($order->customer[$fraud_module_value[$this->fraud_module]['value']]) ?$order->customer[$fraud_module_value[$this->fraud_module]['value']] : ''), 'id=' . $this->code . '-'. strtolower($this->fraud_module).' autocomplete=off" '); + } + if (MODULE_PAYMENT_NOVALNET_SEPA_FORM_TYPE == 'Iframe') { + $iframe = ''; + list($original_sepa_customstyle_css, $original_sepa_customstyle_cssval, $params) = NovalnetInterface::setSepaIframe($order); + $iframe = ' + + + + + + + +
Novalnet AG
+ + + + + + + '; + } + elseif (MODULE_PAYMENT_NOVALNET_SEPA_FORM_TYPE == 'Local') { + $sepa_fields = ' + + + + + + + + + + + + + + + + '; + } + if (MODULE_PAYMENT_NOVALNET_SEPA_SHOP_TYPE == 'ONECLICK' && + $sqlQuerySet = parent::getPaymentRefDetails($_SESSION['customer_id'], $this->code)) { + $form_show = isset($_SESSION['novalnet'][$this->code]['novalnet_sepachange_account']) ? $_SESSION['novalnet'][$this->code]['novalnet_sepachange_account'] : 1; + $masked_acc_details = unserialize($sqlQuerySet['masked_acc_details']); + $selection['fields'][] = array( + 'title' => '', + 'field' => '' . MODULE_PAYMENT_NOVALNET_SEPA_NEW_ACCOUNT . ' + '); + if (MODULE_PAYMENT_NOVALNET_SEPA_FORM_TYPE == 'Iframe') { + $selection['fields'][] = array('title' => '', + 'field' => '' ); + } elseif (MODULE_PAYMENT_NOVALNET_SEPA_FORM_TYPE == 'Local') { + $selection['fields'][] = array( + 'title' => '', + 'field' => '' + ); + } + } else { + if (MODULE_PAYMENT_NOVALNET_SEPA_FORM_TYPE == 'Iframe') { + $selection['fields'][] = array('title' => '', + 'field' => ' + ' . $iframe . '
' . $pin_by_callback . '
' ); + } + elseif (MODULE_PAYMENT_NOVALNET_SEPA_FORM_TYPE == 'Local') { + $selection['fields'][] = array('title' => MODULE_PAYMENT_NOVALNET_ACCOUNT_HOLDER." * ", + 'field' => tep_draw_input_field($this->code.'_account_holder', parent::customerName($order->customer), 'id="' . $this->code . '_account_holder" AUTOCOMPLETE="off" onkeypress="return ibanbic_validate(event, true);"') + ); + $selection['fields'][] = array('title' => MODULE_PAYMENT_NOVALNET_BANK_COUNTRY."* ", + 'field' => tep_draw_pull_down_menu($this->code . '_bank_country', parent::sepaBankCountry(), $order->billing['country']['iso_code_2'], 'id="' . $this->code . '_bank_country"') + ); + $selection['fields'][] = array('title' => '' . MODULE_PAYMENT_NOVALNET_ACCOUNT_OR_IBAN." * ", + 'field' => tep_draw_input_field($this->code . '_iban', '', 'id="' . $this->code . '_iban" AUTOCOMPLETE="off" onkeypress="return ibanbic_validate(event, false);"').'' + ); + $selection['fields'][] = array('title' => MODULE_PAYMENT_NOVALNET_BANKCODE_OR_BIC." * ", + 'field' => tep_draw_input_field($this->code . '_bic', '', 'id="' . $this->code . '_bic" AUTOCOMPLETE="off" onkeypress="return ibanbic_validate(event, false);"').'' + ); + $selection['fields'][] = array('title' => '', + 'field' => '
'.tep_draw_checkbox_field($this->code . '_mandate_confirm', 1, false, 'id="' . $this->code . '_mandate_confirm"').MODULE_PAYMENT_NOVALNET_SEPA_FORM_MANDATE_CONFIRM_TEXT .$sepa_fields + ); + if ( $this->fraud_module && $this->fraud_module_status ) { + $selection['fields'][] = NovalnetInterface::buildCallbackInputFields($this->fraud_module, $this->code); + } + } + } + } + return $selection; + } + + function pre_confirmation_check() { + global $order; + $post = $_REQUEST; + if ( !empty($_SESSION['novalnet'][$this->code]['secondcall']) ) { + NovalnetValidation::validateUserInputsOnCallback($this->fraud_module, $this->code, $post); + } else { + $_SESSION['novalnet'][$this->code]['novalnet_sepachange_account'] = isset($post['novalnet_sepachange_account']) ? $post['novalnet_sepachange_account'] : ''; + if (empty($post['novalnet_sepa_mandate_confirm_ref']) && isset($post['novalnet_sepachange_account']) && $post['novalnet_sepachange_account'] == 1) { + $payment_error_return = 'error_message=' . MODULE_PAYMENT_NOVALNET_SEPA_MANDATE_CONFIRM_ERROR; + tep_redirect(tep_href_link(FILENAME_CHECKOUT_PAYMENT, $payment_error_return, 'SSL', true, false)); + } + if (isset($post['nn_payment_ref_tid_sepa']) && $post['novalnet_sepachange_account'] == 1) { + $_SESSION['novalnet'][$this->code]['nn_payment_ref_enable']= TRUE; + $_SESSION['novalnet'][$this->code]['nn_payment_ref_tid_sepa'] = $post['nn_payment_ref_tid_sepa']; + return true; + } + $this->fraud_module_status = NovalnetInterface::setFraudModuleStatus($this->code, (array)$order, $this->fraud_module); + NovalnetValidation::validateUserInputs($this->fraud_module, $this->fraud_module_status, $this->code, $post); + } + return false; + } + + function confirmation() { + global $order; + if ( !empty($_SESSION['novalnet'][$this->code]['secondcall']) ) { + NovalnetValidation::validateAmountOnCallback($this->code, $this->fraud_module); + } + $_SESSION['novalnet'][$this->code]['payment_amount'] = NovalnetInterface::getPaymentAmount((array)$order, $this->code); + return false; + } + + function process_button() { + $post = $_REQUEST; + if ( !empty($post[$this->code . '_new_pin']) ) { + $new_pin_response = NovalnetInterface::doCallbackRequest('TRANSMIT_PIN_AGAIN', $this->code); + NovalnetValidation::validateNewPinResponse($new_pin_response, 'TRANSMIT_PIN_AGAIN', $this->code); + } + elseif ( isset($_SESSION['novalnet'][$this->code]['payment_amount']) ) { + $novalnet_order_details = isset($_SESSION['novalnet'][$this->code]) ? $_SESSION['novalnet'][$this->code] : array(); + $_SESSION['novalnet'][$this->code] = array_merge($novalnet_order_details, $post, array('payment_amount' => $_SESSION['novalnet'][$this->code]['payment_amount'])); + } + else { + $payment_error_return = 'payment_error=' . $this->code . '&error=' . MODULE_PAYMENT_NOVALNET_PLEASE_SPECIFY_AMOUNT_ERROR_MESSAGE; + tep_redirect(self::setUTFText(tep_href_link(FILENAME_CHECKOUT_PAYMENT, $payment_error_return, 'SSL', true, false))); + } + return NovalnetValidation::confirmButtonDisableActivate(); + } + + function before_process() { + global $order; + $this->fraud_module_status = NovalnetInterface::setFraudModuleStatus($this->code, (array)$order, $this->fraud_module); + $this->fraud_module_status = isset($_SESSION['novalnet'][$this->code]['nn_payment_ref_enable']) ? FALSE:$this->fraud_module_status; + $param_inputs = array_merge((array)$order, $_SESSION['novalnet'][$this->code],array('fraud_module' => $this->fraud_module,'fraud_module_status' => $this->fraud_module_status)); + if ( !empty($param_inputs['secondcall']) ) { + NovalnetInterface::doConfirmPayment($this->code, $this->fraud_module); + } else { + parent::novalnet_before_process($param_inputs); // Perform real time payment transaction + NovalnetInterface::gotoPaymentOnCallback($this->code, $this->fraud_module, $this->fraud_module_status); + } + + $order->info['comments'] = $_SESSION['novalnet'][$this->code]['nntrxncomments']; + } + + function after_process() { + global $insert_id; + parent::updateOrderStatus($insert_id, $this->code); + // Perform paygate second call for transaction confirmations / order_no update + parent::doSecondCallProcess(array( 'payment' => $this->code, + 'order_no' => $insert_id + )); + } + + function javascript_validation() { + return false; + } + + function check() { + return parent::checkInstalledStatus($this->code); + } + + function install() { + parent::installModule($this->code); + } + + function remove() { + parent::uninstallModule($this->code); + } + + function keys() { + return parent::novalnetKeys($this->code); + } + + function get_error() { + global $HTTP_GET_VARS; + $error = array('title' => '', + 'error' => ((isset($HTTP_GET_VARS['error'])) ? stripslashes(urldecode($HTTP_GET_VARS['error'])) : '')); + return $error; + } +} +?> diff --git a/includes/modules/payment/novalnet_sofortbank.php b/includes/modules/payment/novalnet_sofortbank.php new file mode 100644 index 0000000..0fda612 --- /dev/null +++ b/includes/modules/payment/novalnet_sofortbank.php @@ -0,0 +1,128 @@ +code = 'novalnet_sofortbank'; + $this->form_action_url = NovalnetInterface::getPaygateURL($this->code); + $this->title = $this->public_title = MODULE_PAYMENT_NOVALNET_SOFORTBANK_TEXT_TITLE; + $this->description = MODULE_PAYMENT_NOVALNET_REDIRECT_DESC; + $this->sort_order = defined('MODULE_PAYMENT_NOVALNET_SOFORTBANK_SORT_ORDER') && MODULE_PAYMENT_NOVALNET_SOFORTBANK_SORT_ORDER != '' ? MODULE_PAYMENT_NOVALNET_SOFORTBANK_SORT_ORDER : 0; + if ( strpos(MODULE_PAYMENT_INSTALLED,$this->code) !== false ) { + $this->enabled = (MODULE_PAYMENT_NOVALNET_SOFORTBANK_ENABLE_MODULE == 'True'); + } + } + + function selection() { + global $order, $payment; + parent::validatecallbacksession(); + if ( !parent::validateMerchantAPIConf((array)$order, $this->code, $this->enabled) ) { + return false; + } + if ( empty($payment) && MODULE_PAYMENT_NOVALNET_LAST_SUCCESSFULL_PAYMENT_SELECTION == 'True' ) { + if ( parent::getLastSuccessTransPayment($order->customer['email_address'], $this->code) ) { + $payment = $this->code; + } + } + $endcustomerinfo = trim(strip_tags(MODULE_PAYMENT_NOVALNET_SOFORTBANK_ENDCUSTOMER_INFO)); + $test_mode = NovalnetInterface::getPaymentTestModeStatus($this->code); + $description = '
'. $this->description; + $description .= ($endcustomerinfo != '') ? '
'.$endcustomerinfo : ''; + $description .= ($test_mode == 1) ? '
' . utf8_encode(MODULE_PAYMENT_NOVALNET_TEST_MODE_MSG) : ''; + + $selection['id'] = $this->code; + $selection['module'] = MODULE_PAYMENT_NOVALNET_SOFORTBANK_PUBLIC_TITLE . $description; + return $selection; + } + + function pre_confirmation_check() { + return false; + } + + function confirmation() { + global $order; + + $_SESSION['novalnet'][$this->code]['payment_amount'] = NovalnetInterface::getPaymentAmount((array)$order, $this->code); + return false; + } + + function process_button() { + global $order; + + if ( isset($_SESSION['novalnet'][$this->code]['payment_amount']) ) { + $_SESSION['novalnet'][$this->code]['order_obj'] = array_merge((array)$order, array('payment' => $this->code), array('payment_amount' => $_SESSION['novalnet'][$this->code]['payment_amount'])); + $before_process_response = parent::novalnet_before_process($_SESSION['novalnet'][$this->code]['order_obj']); // Perform real time payment transaction + $before_process_response .= NovalnetValidation::confirmButtonDisableActivate(); + return $before_process_response; + } else { + $payment_error_return = 'payment_error=' . $this->code . '&error=' . MODULE_PAYMENT_NOVALNET_PLEASE_SPECIFY_AMOUNT_ERROR_MESSAGE; + tep_redirect(self::setUTFText(tep_href_link(FILENAME_CHECKOUT_PAYMENT, $payment_error_return, 'SSL', true, false))); + } + } + + function before_process() { + global $order; + $post = $_REQUEST; + if (isset($post['tid'])) { // Response validation + $before_process_response = parent::validateRedirectResponse((array)$order, $this->code, $post); + $order->info['comments'] = $before_process_response['comments']; + } + } + + function after_process() { + global $insert_id; + + parent::updateOrderStatus($insert_id, $this->code); + // Perform paygate second call for transaction confirmations / order_no update + parent::doSecondCallProcess(array( 'payment' => $this->code, + 'order_no' => $insert_id + )); + } + + function javascript_validation() { + return false; + } + + function check() { + return parent::checkInstalledStatus($this->code); + } + + function install() { + parent::installModule($this->code); + } + + function remove() { + parent::uninstallModule($this->code); + } + + function keys() { + return parent::novalnetKeys($this->code); + } + + function get_error() { + global $HTTP_GET_VARS; + $error = array('title' => '', + 'error' => ((isset($HTTP_GET_VARS['error'])) ? stripslashes(urldecode($HTTP_GET_VARS['error'])) : '')); + return $error; + } +} +?> diff --git a/novalnet_css_link.php b/novalnet_css_link.php new file mode 100644 index 0000000..cef3cab --- /dev/null +++ b/novalnet_css_link.php @@ -0,0 +1,22 @@ + diff --git a/novalnet_subscription_stop.php b/novalnet_subscription_stop.php new file mode 100644 index 0000000..2b6b44e --- /dev/null +++ b/novalnet_subscription_stop.php @@ -0,0 +1,72 @@ + $local_nn_trans_info['tid'], + 'payment_id' => $local_nn_trans_info['payment_id'], + 'termination_reason' => $inputs['novalnet_subscribe_termination_reason'], + 'order_id' => $inputs['order_id'], + 'vendor' => $local_nn_trans_info['vendor'], + 'product' => $local_nn_trans_info['product'], + 'tariff' => $local_nn_trans_info['tariff'], + 'auth_code' => $local_nn_trans_info['auth_code'] + )); + } + header('Location: '.$inputs['current_request_url']); + exit; +} + +/** + * To process the supscription stop + * @param $order_no + * + * @return string + */ +function NovalnetSubscriptionStop($order_no) { + $local_nn_trans_info = NovalnetCore::getNovalnetTransDetails($order_no); + $local_subscription_info = NovalnetCore::getNovalnetSubscriptionTransDetails($order_no); + $func_output = ''; + if ( isset($local_nn_trans_info) && $local_nn_trans_info['subs_id'] != 0 && isset($local_subscription_info) && $local_subscription_info['termination_reason'] == '' && $local_nn_trans_info['gateway_status'] != 103 ) { + $subs_termination_reason = array(MODULE_PAYMENT_NOVALNET_SUBS_OFFER_TOO_EXPENSIVE,MODULE_PAYMENT_NOVALNET_SUBS_FRAUD, MODULE_PAYMENT_NOVALNET_SUBS_PARTNER_HAS_INTERVENED,MODULE_PAYMENT_NOVALNET_SUBS_FINANCIAL_DIFFICULTIES, MODULE_PAYMENT_NOVALNET_SUBS_CONTENT_DIDNOT_MEET_EXPECT, MODULE_PAYMENT_NOVALNET_SUBS_CONTENT_NOT_SUFFICIENT, MODULE_PAYMENT_NOVALNET_SUBS_INTEREST_ONLY_TEST_ACCESS, MODULE_PAYMENT_NOVALNET_SUBS_PAGE_TOO_SLOW, MODULE_PAYMENT_NOVALNET_SUBS_SATISFIED_CUSTOMER,MODULE_PAYMENT_NOVALNET_SUBS_ACCESS_PROBLEMS,MODULE_PAYMENT_NOVALNET_SUBS_OTHER); + $func_output = "
".MODULE_PAYMENT_NOVALNET_SUBS_CANCEL_TEXT.":
"; + if(isset($_SESSION['novalneterror'])) { + unset($_SESSION['novalneterror']); + $func_output .= ""; + } + $func_output .= "

" . MODULE_PAYMENT_NOVALNET_PLEASE_SELECT_TER_REASON_MESSAGE . "

"; + $func_output .=" + + +
"; + $func_output .= "

"; + } + return $func_output; +} +?>