From 53b2f79f98ca06bb1fd1d3081461309b522a92af Mon Sep 17 00:00:00 2001 From: Novalnet-Technic Date: Fri, 17 Feb 2023 20:32:13 +0530 Subject: [PATCH] first commit --- README.md | 71 ++ admin/novalnet_extension_helper.php | 231 +++++ extras/novalnet_callback.php | 669 ++++++++++++++ .../modules/payment/novalnet_payments.php | 149 ++++ .../modules/payment/novalnet_payments.php | 147 ++++ .../payment/novalnet/NovalnetHelper.class.php | 820 ++++++++++++++++++ .../payment/novalnet/novalnet_auto_config.js | 129 +++ .../payment/novalnet/novalnet_extension.js | 103 +++ .../payment/novalnet/novalnet_extension.php | 188 ++++ .../payment/novalnet/novalnet_payment_form.js | 85 ++ .../payment/novalnet/sql/db_13_0_0.sql | 30 + .../modules/payment/novalnet_payments.php | 339 ++++++++ novalnet_auto_config.php | 71 ++ 13 files changed, 3032 insertions(+) create mode 100644 README.md create mode 100644 admin/novalnet_extension_helper.php create mode 100755 extras/novalnet_callback.php create mode 100644 includes/languages/english/modules/payment/novalnet_payments.php create mode 100644 includes/languages/german/modules/payment/novalnet_payments.php create mode 100755 includes/modules/payment/novalnet/NovalnetHelper.class.php create mode 100755 includes/modules/payment/novalnet/novalnet_auto_config.js create mode 100755 includes/modules/payment/novalnet/novalnet_extension.js create mode 100644 includes/modules/payment/novalnet/novalnet_extension.php create mode 100755 includes/modules/payment/novalnet/novalnet_payment_form.js create mode 100755 includes/modules/payment/novalnet/sql/db_13_0_0.sql create mode 100644 includes/modules/payment/novalnet_payments.php create mode 100644 novalnet_auto_config.php diff --git a/README.md b/README.md new file mode 100644 index 0000000..cf01079 --- /dev/null +++ b/README.md @@ -0,0 +1,71 @@ +# ZENCART PAYMENT INTEGRATION BY NOVALNET +Zen Cart payment module by Novalnet enables secure integration of payments and payment services for all Zen Cart shops. Novalnet payment module for Zen Cart shop helps merchants to automate payment processing from checkout till collection. + +## Integration requirements for Zen Cart +Novalnet merchant account is required for processing all international and local payments through this ZenCart Payment Gateway. The module is available for the ZenCart versions 1.5.5 to 1.5.8 in the following languages: EN & DE + +## Key features of ZenCart payment integration +- Easy configuration of all international & local payment methods +- One PCI DSS certified payment platform for all payment services from checkout to collection +- Complete automation of all payment processes +- 60+ risk & payment fraud detection modules to prevent defaults in real time +- Clear overview of payment status from checkout to receivables +- Multilevel claims management with integrated handover to collection and various export functions for the accounting +- Comprehensive fraud prevention solution with more than 60 modules (Machine learning) +- Reporting & analytics dashboards with multiple export options +- Automated e-mail notifications for staying up to date on the payment status +- Automated bookkeeping report in XML, SOAP, CSV, MT940 +- Simple seamless integration of the payment module +- Secure SSL-encoded gateways +- Seamless checkout Iframe integration +- One-click shopping enabled for commonly used payment types +- Easy confirmation/cancellation of on-hold transactions for selected payment types +- Refund option for moat of the payment types +- Responsive templates + +For detailed documentation and other technical inquiries, please send us an email at sales@novalnet.de + +## Integrated payment methods +- Direct Debit SEPA +- Credit/Debit Cards +- Apple Pay +- Google Pay +- Invoice +- Prepayment +- Invoice with payment guarantee +- Direct Debit SEPA with payment guarantee +- iDEAL +- Sofort +- giropay +- Barzahlen/viacash +- Przelewy24 +- eps +- Instalment by Invoice +- Instalment by Direct Debit SEPA +- PayPal +- PostFinance Card +- PostFinance E-Finance +- Bancontact +- Multibanco +- Online bank transfer +- Alipay +- WeChat Pay +- Trustly + +## License +See our License Agreement at: https://www.novalnet.com/payment-plugins-free-license/ + +## Documentation & Support +For more information about the Zen Cart Payment Integration by Novalnet, please get in touch with us: sales@novalnet.de or +49 89 9230683-20
+ +Novalnet AG
+Zahlungsinstitut (ZAG)
+Feringastr. 4
+85774 Unterföhring
+Deutschland
+Website: www.novalnet.de + +## Who is Novalnet AG? +

Novalnet AG is a leading financial service institution offering payment gateways for processing online payments. Operating in the market as a full payment service provider Novalnet AG provides online merchants user-friendly payment integration with all major shop systems and self-programmed sites.

+

Accept, manage and monitor payments all on one platform with one single contract!

+

Our SaaS engine is PCI DSS certified and designed to enable real-time risk management, secured payments via escrow accounts, efficient receivables management, dynamic member and subscription management, customized payment solutions for various business models (e.g. marketplaces, affiliate programs etc.) etc.

diff --git a/admin/novalnet_extension_helper.php b/admin/novalnet_extension_helper.php new file mode 100644 index 0000000..ffdb916 --- /dev/null +++ b/admin/novalnet_extension_helper.php @@ -0,0 +1,231 @@ +RecordCount()) { + if (!empty($txn_details->fields['payment_details'])) { + $payment_details = json_decode($txn_details->fields['payment_details'], true); + } + $order = new order($_REQUEST['oID']); + $current_order_status = $db->Execute("SELECT orders_status from " . TABLE_ORDERS . " where orders_id = " . zen_db_input($request['oID'])); + // On-hold transaction prcoess + if (isset($request['nn_manage_confirm']) && !empty($request['trans_status'])) { + $order_status = ''; + $comments = ''; + $data['transaction'] = [ + 'tid' => $txn_details->fields['tid'] + ]; + $data['custom'] = [ + 'lang' => (isset($_SESSION['languages_code'])) ? strtoupper($_SESSION['languages_code']) : 'DE', + ]; + $endpoint = (!empty($request['trans_status']) && $request['trans_status'] == 'CONFIRM') ? 'transaction_capture' : 'transaction_cancel'; + $response = NovalnetHelper::sendRequest($data, NovalnetHelper::getActionEndpoint($endpoint)); + $update_data = [ + 'status' => $response['transaction']['status'], + ]; + if ($response['result']['status'] == 'SUCCESS') { // Success + $order_status = NovalnetHelper::getOrderStatus ($update_data['status'], $response['transaction']['payment_type']); + $order_status = ($request['trans_status'] == 'CONFIRM') ? $order_status : 99; + if ($request['trans_status'] == 'CONFIRM') { + $comments .= PHP_EOL . sprintf(MODULE_PAYMENT_NOVALNET_TRANS_CONFIRM_SUCCESSFUL_MESSAGE_TEXT, date('d.m.Y', strtotime(date('d.m.Y'))), date('H:i:s')) . PHP_EOL; + $comments .= NovalnetHelper::getTransactionDetails($response); + if (in_array($response['transaction']['payment_type'], array( 'INSTALMENT_INVOICE','GUARANTEED_INVOICE', 'INVOICE', 'PREPAYMENT'))) { + if (empty($response['transaction']['bank_details'])) { + $response['transaction']['bank_details'] = $payment_details; + } + $comments .= NovalnetHelper::getBankDetails($response); + } + if (in_array($response['transaction']['payment_type'], array( 'INSTALMENT_INVOICE','INSTALMENT_DIRECT_DEBIT_SEPA'))) { + $comments .= NovalnetHelper::getInstalmentDetails($response); + if (in_array($response['transaction']['status'],array('CONFIRMED', 'PENDING'))) { + $total_amount = ($txn_details->fields['amount'] < $response['transaction']['amount']) ? $response['transaction']['amount'] : $txn_details->fields['amount']; + $instalment_details = NovalnetHelper::storeInstalmentdetails($response, $total_amount); + $update_data['instalment_cycle_details'] = $instalment_details; + } + } + } elseif ($request['trans_status'] == 'CANCEL') { + $comments .= PHP_EOL.sprintf(MODULE_PAYMENT_NOVALNET_TRANS_DEACTIVATED_MESSAGE, date('d.m.Y', strtotime(date('d.m.Y'))), date('H:i:s')); + } + updateOrderStatus($request['oID'], $comments, $order_status); + $messageStack->add_session($response['result']['status_text'], 'success'); + } else { // Failure + $messageStack->add_session($response['result']['status_text'], 'error'); + } + if (!empty($request['oID'])) { + zen_db_perform('novalnet_transaction_detail', $update_data, 'update', 'order_no='.$request['oID']); + } + zen_redirect(zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(['action']) . 'action=edit' . '&oID=' . (int)$request['oID'])); + } elseif ((!empty($request['nn_refund_confirm']) && ($request['refund_trans_amount'] != '' ) && $txn_details->fields['status'] != 'Canceled')) { // To process refund process + $refunded_amount = 0; + $data['transaction'] = [ + 'tid' => (!empty($request['refund_tid'])) ? $request['refund_tid'] : $txn_details->fields['tid'], + 'amount' => $request['refund_trans_amount'], + ]; + $data['custom'] = [ + 'lang' => (isset($_SESSION['languages_code'])) ? strtoupper($_SESSION['languages_code']) : 'DE', + ]; + if (!empty($request['refund_reason'])){ + $data['transaction']['reason'] = $request['refund_reason']; + } + $response = NovalnetHelper::sendRequest($data, NovalnetHelper::getActionEndpoint('transaction_refund')); + if ($response['result']['status'] == 'SUCCESS') { + $refunded_amount = $response['transaction']['refund']['amount']; + if (in_array($response['transaction']['payment_type'], array('INSTALMENT_INVOICE','INSTALMENT_DIRECT_DEBIT_SEPA'))) { + $instalment_details = (!empty($txn_details->fields['instalment_cycle_details'])) ? json_decode($txn_details->fields['instalment_cycle_details'], true) : unserialize($txn_details->fields['payment_details']); + if(!empty($instalment_details)) { + $cycle = $request['instalment_cycle']; + $instalment_amount = (strpos((string)$instalment_details[$cycle]['instalment_cycle_amount'], '.')) ? $instalment_details[$cycle]['instalment_cycle_amount']*100 : $instalment_details[$cycle]['instalment_cycle_amount']; + $instalment_amount = $instalment_amount - $refunded_amount; + $instalment_details[$cycle]['instalment_cycle_amount'] = $instalment_amount; + if($instalment_details[$cycle]['instalment_cycle_amount'] <= 0) { + $instalment_details[$cycle]['status'] = 'Refunded'; + } + $update_data = [ + 'instalment_cycle_details' => json_encode($instalment_details), + ]; + } + } + $update_data['refund_amount'] = (!empty($txn_details->fields['refund_amount'])) ? ($refunded_amount + $txn_details->fields['refund_amount']) : $refunded_amount; + $message = PHP_EOL. sprintf((MODULE_PAYMENT_NOVALNET_REFUND_PARENT_TID_MSG), $txn_details->fields['tid'], $currencies->format(($refunded_amount/100), 1, $txn_details->fields['currency'])); + // Check for refund TID + if (!empty($response['transaction']['refund']['tid'])) { + $message .= PHP_EOL. sprintf((MODULE_PAYMENT_NOVALNET_REFUND_CHILD_TID_MSG), $response['transaction']['refund']['tid']); + } + if (!empty($request['oID'])) { + zen_db_perform('novalnet_transaction_detail', $update_data, 'update', 'order_no='.$request['oID']); + } + updateOrderStatus($request['oID'], $message, $current_order_status->fields['orders_status']); + $messageStack->add_session($response['result']['status_text'], 'success'); + } else { + $messageStack->add_session($response['result']['status_text'], 'error'); + } + zen_redirect(zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(['action']) . 'action=edit' . '&oID=' . (int)$request['oID'])); + } else if (!empty($request['nn_book_confirm']) && !empty($request['book_amount'])) { // Zero amount booking transaction process + $merchant_data = NovalnetHelper::getMerchantData(); + $customer_data = NovalnetHelper::getCustomerData(); + $transaction_data = NovalnetHelper::getTransactionData(); + $custom_data = NovalnetHelper::getCustomData(); + $customer_data['customer']['billing']['country_code'] = $order->billing['country']['iso_code_2']; + if (empty($customer_data['customer']['shipping']['same_as_billing'])) { + $customer_data['customer']['shipping']['country_code'] = $order->delivery['country']['iso_code_2']; + } + $transaction_data['transaction']['payment_type'] = $txn_details->fields['payment_type']; + $data = array_merge($merchant_data, $customer_data, $transaction_data, $custom_data); + $data['transaction']['amount'] = $request['book_amount']; + $data['transaction']['payment_data']['token'] = $payment_details['token']; + $response = NovalnetHelper::sendRequest($data, NovalnetHelper::getActionEndpoint('payment')); + if ($response['result']['status'] == 'SUCCESS' ) { + $order_status_value = $db->Execute("SELECT orders_status from " . TABLE_ORDERS . " where orders_id = " . zen_db_input($request['oID'])); + $message = PHP_EOL .PHP_EOL. sprintf(MODULE_PAYMENT_NOVALNET_TRANS_BOOKED_MESSAGE, $currencies->format(($request['book_amount'] / 100), 1, $response['transaction']['currency']), $response['transaction']['tid']) . PHP_EOL; + $update_data = [ + 'amount' => $response['transaction']['amount'], + 'tid' => $response['transaction']['tid'], + ]; + if (!empty($request['oID'])) { + zen_db_perform('novalnet_transaction_detail', $update_data, 'update', 'order_no='.$request['oID']); + } + updateOrderStatus($request['oID'], $message, $current_order_status->fields['orders_status']); + $messageStack->add_session($response['result']['status_text'], 'success'); + } else { + $messageStack->add_session($response['result']['status_text'], 'error'); + } + zen_redirect(zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(['action']) . 'action=edit' . '&oID=' . (int)$request['oID'])); + } else if (!empty($request['nn_instacancel_allcycles']) || !empty($request['nn_instacancel_remaincycles'])) { // Instalment cancel process + $data['instalment']['tid'] = $txn_details->fields['tid']; + $data['custom'] = [ + 'lang' => (isset($_SESSION['languages_code'])) ? strtoupper($_SESSION['languages_code']) : 'DE', + ]; + if (isset($request['nn_instacancel_allcycles'])) { + $data['instalment']['cancel_type'] = 'CANCEL_ALL_CYCLES'; + } else if (isset($request['nn_instacancel_remaincycles'])){ + $data['instalment']['cancel_type'] = 'CANCEL_REMAINING_CYCLES'; + } + $response = NovalnetHelper::sendRequest($data, NovalnetHelper::getActionEndpoint('instalment_cancel')); + if ($response['result']['status'] == 'SUCCESS') { + if (!empty($request['nn_instacancel_remaincycles'])) { + $instalment_details = json_decode($txn_details->fields['instalment_cycle_details'], true); + if(!empty($instalment_details)) { + foreach($instalment_details as $key => $instalment_details_data) { + if (empty($instalment_details_data['reference_tid']) && ($instalment_details_data['status'] == 'Pending')) { + $instalment_details[$key]['status'] = constant('MODULE_PAYMENT_NOVALNET_INSTALMENT_STATUS_CANCELED'); + } + if ($instalment_details_data['status'] == 'Paid') { + $instalment_details[$key]['status'] = constant('MODULE_PAYMENT_NOVALNET_INSTALMENT_STATUS_REFUNDED'); + } + } + $update_data = [ + 'instalment_cycle_details' => json_encode($instalment_details), + ]; + } + $update_data['status'] = 'CONFIRMED'; + $message = PHP_EOL. sprintf((MODULE_PAYMENT_NOVALNET_INSTALMENT_CANCEL_REMAINING_CYCLES_TEXT), $txn_details->fields['tid'], date('Y-m-d H:i:s')); + } else if (!empty($request['nn_instacancel_allcycles'])) { + $instalment_details = json_decode($txn_details->fields['instalment_cycle_details'], true); + if(!empty($instalment_details)) { + foreach($instalment_details as $key => $instalment_details_data) { + if (!empty($instalment_details_data['reference_tid']) && ($instalment_details_data['status'] == 'Paid')) { + $instalment_details[$key]['status'] = constant('MODULE_PAYMENT_NOVALNET_INSTALMENT_STATUS_REFUNDED'); + } else { + $instalment_details[$key]['status'] = constant('MODULE_PAYMENT_NOVALNET_INSTALMENT_STATUS_CANCELED'); + } + } + $update_data = [ + 'instalment_cycle_details' => json_encode($instalment_details), + ]; + } + $update_data['status'] = 'CANCELED'; + $message = PHP_EOL. sprintf((MODULE_PAYMENT_NOVALNET_INSTALMENT_CANCEL_ALLCYCLES_TEXT), $txn_details->fields['tid'], date('Y-m-d H:i:s'), $currencies->format(($response['transaction']['refund']['amount']/100), 1, $txn_details->fields['currency'])); + } + + if (!empty($request['oID'])) { + zen_db_perform('novalnet_transaction_detail', $update_data, 'update', 'order_no='.$request['oID']); + } + updateOrderStatus($request['oID'], $message, $current_order_status->fields['orders_status']); + $messageStack->add_session($response['result']['status_text'], 'success'); + } else { + $messageStack->add_session($response['result']['status_text'], 'error'); + } + zen_redirect(zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(['action']) . 'action=edit' . '&oID=' . (int)$request['oID'])); + } else { + zen_redirect(zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(['action']) . 'action=edit' . '&oID=' . (int)$request['oID'])); + } +} + +/** +* Update order status in the shop +* +* @param integer $order_id +* @param string $order_status +* @param string $message +*/ +function updateOrderStatus($order_id, $message, $order_status = '') { + global $db; + zen_db_perform(TABLE_ORDERS, array( + 'orders_status' => $order_status, + ), "update", "orders_id='$order_id'"); + + $db->Execute("insert into " . TABLE_ORDERS_STATUS_HISTORY . " (orders_id, orders_status_id, date_added, customer_notified, comments) values ('".zen_db_input($order_id)."', '".zen_db_input($order_status)."', '" .date('Y-m-d H:i:s') . "', '1', '".zen_db_input($message)."')"); +} +?> diff --git a/extras/novalnet_callback.php b/extras/novalnet_callback.php new file mode 100755 index 0000000..ca8e732 --- /dev/null +++ b/extras/novalnet_callback.php @@ -0,0 +1,669 @@ + [ + 'type', + 'checksum', + 'tid', + ], + 'merchant' => [ + 'vendor', + 'project', + ], + 'result' => [ + 'status', + ], + 'transaction' => [ + 'tid', + 'payment_type', + 'status', + ], + ]; + + /** + * Request parameters. + * + * @var array + */ + protected $event_data = []; + + /** + * Order reference values. + * + * @var array + */ + protected $order_details = []; + + /** + * Recived Event type. + * + * @var string + */ + protected $event_type; + + /** + * Recived Event TID. + * + * @var int + */ + protected $event_tid; + + /** + * Recived Event parent TID. + * + * @var int + */ + protected $parent_tid; + + /** + * Order language details. + * + * @var array + */ + protected $order_lang; + + /** + * Core Function : Constructor() + * + */ + function __construct() { + try { + $this->event_data = json_decode(file_get_contents('php://input'), true); + } catch (Exception $e) { + $this->displayMessage([ 'message' => 'Received data is not in the JSON format' . $e]); + } + $this->authenticateEventData(); + $this->event_tid = !empty($this->event_data ['event'] ['tid']) ? $this->event_data ['event'] ['tid'] : ''; + $this->event_type = $this->event_data['event']['type']; + $this->parent_tid = (!empty($this->event_data['event']['parent_tid'])) ? $this->event_data['event']['parent_tid'] :$this->event_data['event']['tid']; + $this->order_details = $this->getOrderDetails(); + // If the order in the Novalnet server to the order number in Novalnet database doesn't match, then there is an issue + if (!empty($this->event_data['transaction']['order_no']) && !empty($this->order_details['shop_order']) + && (($this->event_data['transaction']['order_no']) != $this->order_details['shop_order'])) { + $this->displayMessage(['message' => 'Order reference not matching for the order number ' . $this->order_details['shop_order']]); + } + // If both the order number from Novalnet and in shop is missing, then something is wrong + if (!empty($this->event_data['transaction']['order_no']) && empty($this->order_details['shop_order'])) { + $this->displayMessage(['message' => 'Order reference not found for the TID ' . $this->parent_tid]); + } + + if (NovalnetHelper::is_success_status($this->event_data)) { + switch($this->event_type) { + case 'PAYMENT': + $this->displayMessage(['message' => "The webhook notification received ('".$this->event_data['transaction']['payment_type']."') for the TID: '".$this->event_tid."'"]); + break; + case 'TRANSACTION_CAPTURE': + $this->handleTransactionCapture(); + break; + case 'TRANSACTION_CANCEL': + $this->handleTransactionCancel(); + break; + case 'TRANSACTION_REFUND': + $this->handleTransactionRefund(); + break; + case 'CREDIT': + $this->handleTransactionCredit(); + break; + case 'CHARGEBACK': + $this->handleChargeback(); + break; + case 'INSTALMENT': + $this->handleInstalment(); + break; + case 'INSTALMENT_CANCEL': + $this->handleInstalmentCancel(); + break; + case 'TRANSACTION_UPDATE': + $this->handleTransactionUpdate(); + break; + case 'PAYMENT_REMINDER_1': + case 'PAYMENT_REMINDER_2': + $this->handlePaymentReminder(); + break; + case 'SUBMISSION_TO_COLLECTION_AGENCY': + $this->handleCollectionSubmission(); + break; + default: + $message = "The webhook notification has been received for the unhandled EVENT type('".$this->event_type."')"; + $this->displayMessage(['message' => $message]); + } + } + } + + /** + * Authenticate server request + * + */ + function authenticateEventData() { + $request_received_ip = zen_get_ip_address(); + $novalnet_host_ip = gethostbyname($this->novalnet_host_name); + if (!empty($novalnet_host_ip) && !empty($request_received_ip)) { + if ($novalnet_host_ip !== $request_received_ip && MODULE_PAYMENT_NOVALNET_CALLBACK_TEST_MODE == 'false') { + $this->displayMessage(['message' => 'Unauthorised access from the IP ' . $request_received_ip]); + } + } else { + $this->displayMessage([ 'message' => 'Unauthorised access from the IP. Host/recieved IP is empty' ]); + } + $this->validateEventData(); + $this->validateCheckSum(); + } + + /** + * Validate event_data + * + */ + function validateEventData() { + foreach ($this->mandatory as $category => $parameters) { + if (empty($this->event_data[ $category ])) { + $this->displayMessage([ 'message' => "Required parameter category($category) not received" ]); + } elseif (!empty($parameters)) { + foreach ($parameters as $parameter) { + if (empty($this->event_data [ $category ] [ $parameter ])) { + $this->displayMessage([ 'message' => "Required parameter($parameter) in the category($category) not received" ]); + } elseif (in_array($parameter, [ 'tid', 'parent_tid' ], true) && ! preg_match('/^\d{17}$/', $this->event_data [ $category ] [ $parameter ])) { + $this->displayMessage([ 'message' => "Invalid TID received in the category($category) not received $parameter" ]); + } + } + } + } + } + + /** + * Validate checksum + * + */ + function validateCheckSum() { + if (!empty($this->event_data['event']['checksum']) && ! empty($this->event_data['event']['tid']) && ! empty($this->event_data['event']['type']) + && !empty($this->event_data['result']['status'])) { + $token_string = $this->event_data['event']['tid'] . $this->event_data['event']['type'] . $this->event_data['result']['status']; + if (isset($this->event_data['transaction']['amount'])) { + $token_string .= $this->event_data['transaction']['amount']; + } + if (isset($this->event_data['transaction']['currency'])) { + $token_string .= $this->event_data['transaction']['currency']; + } + if (!empty(MODULE_PAYMENT_NOVALNET_PAYMENT_ACCESS_KEY)) { + $token_string .= strrev(MODULE_PAYMENT_NOVALNET_PAYMENT_ACCESS_KEY); + } + $generated_checksum = hash('sha256', $token_string); + if ($generated_checksum != $this->event_data['event']['checksum']) { + $this->displayMessage([ 'message' =>'While notifying some data has been changed. The hash check failed']); + } + } + } + + function getOrderDetails(){ + global $db; + $order_details = []; + $novalnet_order_details = $db->Execute("SELECT * FROM novalnet_transaction_detail WHERE tid = '".$this->parent_tid."'"); + $orderNumber = !empty($novalnet_order_details->fields['order_no']) ? $novalnet_order_details->fields['order_no'] : $this->event_data['transaction']['order_no']; + if(empty($orderNumber)) { + $this->displayMessage(array( 'message' => 'Order reference not found in the shop' )); + } + $shop_order_details = $db->Execute("SELECT payment_method,orders_id, customers_id,orders_status,language_code FROM ".TABLE_ORDERS." WHERE orders_id = '".$orderNumber."'"); + $this->order_lang = $db->Execute("SELECT * FROM " . TABLE_LANGUAGES . " WHERE directory = '" . $shop_order_details->fields['language_code'] ."'"); + $this->include_required_files($this->order_lang->fields); + + $order_details['nn_trans_details'] = $novalnet_order_details->fields; + $order_details['shop_order'] = $orderNumber; + $order_details['shop_order_details'] = $shop_order_details->fields; + return $order_details; + } + + /** + * Handle transaction capture + * + */ + function handleTransactionCapture() { + if ($this->order_details['nn_trans_details']['status'] != $this->event_data['transaction']['status']) { + $novalnet_update_data = [ + 'status' => $this->event_data['transaction']['status'], + ]; + + $order_status = NovalnetHelper::getOrderStatus ($this->event_data['transaction']['status'], $this->order_details['nn_trans_details']['payment_type']); + if (in_array($this->order_details['nn_trans_details']['payment_type'], array('INVOICE', 'GUARANTEED_INVOICE', 'INSTALMENT_INVOICE'))) { + $comments = PHP_EOL.sprintf(MODULE_PAYMENT_NOVALNET_TRANS_CONFIRM_SUCCESSFUL_MESSAGE, $this->event_data['transaction']['tid'], gmdate('d-m-Y')).PHP_EOL.PHP_EOL; + } else { + $comments = PHP_EOL.sprintf(MODULE_PAYMENT_NOVALNET_TRANS_CONFIRM_SUCCESSFUL_MESSAGE_TEXT, gmdate('d-m-Y')).PHP_EOL.PHP_EOL; + } + if (in_array($this->order_details['nn_trans_details']['payment_type'], array('INSTALMENT_DIRECT_DEBIT_SEPA', 'INSTALMENT_INVOICE'))) { + $total_amount = ($this->order_details['nn_trans_details']['amount'] < $this->event_data['transaction']['amount']) ? $this->event_data['transaction']['amount'] : $this->order_details['nn_trans_details']['amount']; + $novalnet_update_data['instalment_cycle_details'] = NovalnetHelper::storeInstalmentdetails($this->event_data, $total_amount); + } + $order_comment = $comments; + $order_comment .= NovalnetHelper::getTransactionDetails($this->event_data); + if (in_array($this->order_details['nn_trans_details']['payment_type'], array('INVOICE', 'GUARANTEED_INVOICE', 'INSTALMENT_INVOICE'))) { + if (empty($this->event_data ['transaction']['bank_details'])) { + if(!empty($this->order_details['nn_trans_details']['payment_details'])) { + $bank_data = json_decode($this->order_details['nn_trans_details']['payment_details']); + $bank_details = array( + 'account_holder' => $bank_data->account_holder, + 'iban' => $bank_data->iban, + 'bic' => $bank_data->bic, + 'bank_name' => $bank_data->bank_name, + 'bank_place' => $bank_data->bank_city, + ); + } else { + $bank_details = json_decode($this->order_details['nn_trans_details']['payment_details'], true); + } + $this->event_data ['transaction']['bank_details'] = $bank_details; + } + $order_comment .= NovalnetHelper::getBankDetails($this->event_data); + } + if (in_array($this->order_details['nn_trans_details']['payment_type'], array('INSTALMENT_DIRECT_DEBIT_SEPA', 'INSTALMENT_INVOICE'))) { + $order_comment .= NovalnetHelper::getInstalmentDetails($this->event_data); + } + $this->updateOrderStatusHistory($this->event_data['transaction']['order_no'], $order_status, $order_comment); + + $this->updateNovalnetTransaction($novalnet_update_data, "tid='{$this->parent_tid}'"); + $this->sendWebhookMail($comments); + $this->displayMessage([ 'message' => $comments]); + } + } + + /** + * Handle transaction cancel + * + */ + function handleTransactionCancel() { + if ($this->order_details['nn_trans_details']['status'] != $this->event_data['transaction']['status']) { + $comments = sprintf(MODULE_PAYMENT_NOVALNET_TRANS_DEACTIVATED_MESSAGE, gmdate('d-m-Y'), gmdate('H:i:s')); + $novalnet_update_data = [ + 'status' => $this->event_data['transaction']['status'], + ]; + $this->updateNovalnetTransaction($novalnet_update_data, "tid='{$this->parent_tid}'"); + $this->updateOrderStatusHistory($this->event_data['transaction']['order_no'], '', $comments); + $this->sendWebhookMail($comments); + $this->displayMessage([ 'message' => $comments]); + } + } + + + /** + * Handle transaction refund + * + */ + function handleTransactionRefund() { + global $currencies; + if (!empty($this->event_data['transaction']['refund']['amount'])) { + $comments = PHP_EOL . sprintf(MODULE_PAYMENT_NOVALNET_REFUND_PARENT_TID_MSG, $this->parent_tid, $currencies->format(($this->event_data['transaction']['refund']['amount']/100), 1, $this->event_data['transaction']['currency'])); + if (!empty($this->event_data['transaction']['refund']['tid'])) { + $comments .= sprintf(MODULE_PAYMENT_NOVALNET_REFUND_CHILD_TID_MSG, $this->event_data['transaction']['refund']['tid']); + } + $refund_amount = $this->event_data['transaction']['refund']['amount']; + $refunded_amount = $this->order_details['nn_trans_details']['refund_amount'] + $refund_amount; + $novalnet_update_data = array( + 'refund_amount' => $refunded_amount, + 'status' => $this->event_data['transaction']['status'], + ); + if (in_array($this->event_data['transaction']['payment_type'], array('INSTALMENT_INVOICE','INSTALMENT_DIRECT_DEBIT_SEPA'))) { + $instalment_details = (!empty($this->order_details['nn_trans_details']['instalment_cycle_details'])) ? json_decode($this->order_details['nn_trans_details']['instalment_cycle_details'], true) : unserialize($this->order_details['nn_trans_details']['payment_details']); + if(!empty($instalment_details)) { + foreach($instalment_details as $cycle => $cycle_details){ + if(!empty($cycle_details['reference_tid']) && ($cycle_details['reference_tid'] == $this->parent_tid)) { + $instalment_amount = (strpos((string)$instalment_details[$cycle]['instalment_cycle_amount'], '.')) ? $instalment_details[$cycle]['instalment_cycle_amount']*100 : $instalment_details[$cycle]['instalment_cycle_amount']; + $instalment_amount = $instalment_amount - $refund_amount; + $instalment_details[$cycle]['instalment_cycle_amount'] = $instalment_amount; + if($instalment_details[$cycle]['instalment_cycle_amount'] <= 0) { + $instalment_details[$cycle]['status'] = 'Refunded'; + } + } + $novalnet_update_data['instalment_cycle_details'] =json_encode($instalment_details); + } + } + $novalnet_update_data['instalment_cycle_details'] =json_encode($instalment_details); + } + + $this->updateNovalnetTransaction($novalnet_update_data, "tid='{$this->parent_tid}'"); + $this->updateOrderStatusHistory($this->order_details['shop_order'], '', $comments); + $this->sendWebhookMail($comments); + $this->displayMessage([ 'message' => $comments]); + } + } + + /** + * Handle chargeback + * + */ + function handleTransactionCredit() { + global $currencies; + $update_comments = true; + $order_status = ''; + $comments = sprintf(NOVALNET_WEBHOOK_CREDIT_NOTE, $this->parent_tid, $currencies->format(($this->event_data['transaction']['amount']/100), 1, $this->event_data['transaction']['currency']), gmdate('d-m-Y H:i:s'), $this->event_tid); + if (in_array($this->event_data['transaction']['payment_type'], ['INVOICE_CREDIT', 'CASHPAYMENT_CREDIT', 'MULTIBANCO_CREDIT'])) { + $paid_amount = (!empty($this->order_details['nn_trans_details']['refund_amount'])) ? ((int)$this->order_details['nn_trans_details']['refund_amount'] + (int)$this->order_details['nn_trans_details']['callback_amount']) : $this->order_details['nn_trans_details']['callback_amount']; + if ($paid_amount < $this->order_details['nn_trans_details']['amount']) { + $total_paid_amount = $paid_amount + $this->event_data['transaction']['amount']; + $update_data = array( + 'callback_amount' => $total_paid_amount + ); + if ($total_paid_amount >= $this->order_details['nn_trans_details']['amount']) { // Full amount paid + if ($this->order_details['nn_trans_details']['payment_type'] == 'INVOICE') { // Invoice payment type + $order_status = 3; + } else { // Other than Invoice payment + $order_status = 2; + } + } else { // Partial paid + if ($this->order_details['nn_trans_details']['payment_type'] == 'INVOICE') { // Invoice payment type + $order_status = 2; + } else { // Other than Invoice payment + $order_status = 1; + } + } + $update_data['status'] = $this->event_data['transaction']['status']; + $this->updateNovalnetTransaction($update_data, "tid='{$this->parent_tid}'"); + } else { + $update_comments = false; + $comments = sprintf(('Callback script executed already'), gmdate('d-m-Y'), gmdate('H:i:s')); + } + } + if($update_comments) { + $this->updateOrderStatusHistory($this->event_data['transaction']['order_no'], $order_status, $comments, 1); + $this->sendWebhookMail($comments); + } + $this->displayMessage([ 'message' => $comments]); + } + + /** + * Handle chargeback + * + */ + function handleChargeback() { + global $currencies; + if (($this->order_details['nn_trans_details']['status'] == 'CONFIRMED') && !empty($this->event_data ['transaction'] ['amount'])) { + $comments =sprintf(NOVALNET_WEBHOOK_CHARGEBACK_NOTE , $this->parent_tid, $currencies->format(($this->event_data['transaction']['amount']/100), 1, $this->event_data['transaction']['currency']), gmdate('d.m.Y'), gmdate('H:i:s'), $this->event_tid); + $this->updateOrderStatusHistory($this->event_data['transaction']['order_no'], '', $comments); + $this->sendWebhookMail($comments); + $this->displayMessage([ 'message' => $comments]); + } + } + + /** + * Handle instalment + * + */ + function handleInstalment() { + global $currencies; + $comment = ''; + if ($this->event_data['transaction']['status'] == 'CONFIRMED' && !empty($this->event_data['instalment']['cycles_executed']) + && in_array($this->event_data['transaction']['payment_type'], array('INSTALMENT_INVOICE','INSTALMENT_DIRECT_DEBIT_SEPA'))) { + $instalment_details = (!empty($this->order_details['nn_trans_details']['instalment_cycle_details'])) ? json_decode($this->order_details['nn_trans_details']['instalment_cycle_details'], true) : unserialize($this->order_details['nn_trans_details']['payment_details']); + $instalment = $this->event_data['instalment']; + $cycle_index = $instalment['cycles_executed'] - 1; + if (!empty($instalment)) { + $instalment_details[$cycle_index]['next_instalment_date'] = (!empty($instalment['next_cycle_date'])) ? $instalment['next_cycle_date'] : '-'; + if (!empty($this->event_data['transaction']['tid'])) { + $instalment_details[$cycle_index]['reference_tid'] = $this->event_data['transaction']['tid']; + $instalment_details[$cycle_index]['status'] = 'Paid'; + $instalment_details[$cycle_index]['paid_date'] = date('Y-m-d H:i:s'); + } + } + if ($this->event_data['transaction']['payment_type'] == 'INSTALMENT_INVOICE' && empty($this->event_data ['transaction']['bank_details'])) { + $this->event_data ['transaction']['bank_details'] = json_decode($this->order_details['nn_trans_details']['payment_details'], true); + } + $comment = sprintf(NOVALNET_WEBHOOK_NEW_INSTALMENT_NOTE, $this->parent_tid, $currencies->format(($this->event_data['instalment']['cycle_amount']/100), 1, $this->event_data['transaction']['currency']), gmdate('d-m-Y'), $this->event_tid); + $this->updateNovalnetTransaction(array('instalment_cycle_details' => json_encode($instalment_details)), "tid='{$this->parent_tid}'"); + $transaction_comment .= NovalnetHelper::insertTransactionDetails($this->event_data, false, $this->order_details['shop_order']); + $this->updateOrderStatusHistory($this->event_data['transaction']['order_no'], '', $comment, 1); + $this->sendWebhookMail($comment); + $this->displayMessage([ 'message' => $comment]); + } + } + + /** + * Handle instalment cancel + * + */ + function handleInstalmentCancel() { + $comments = ''; + if ($this->event_data['transaction']['status'] == 'CONFIRMED') { + $novalnet_update_data = [ + 'status' => 'DEACTIVATED', + ]; + $comments .= sprintf(NOVALNET_WEBHOOK_INSTALMENT_CANCEL_NOTE, $this->parent_tid, gmdate('d.m.Y')); + } + $this->updateNovalnetTransaction($novalnet_update_data, "tid='{$this->parent_tid}'"); + $this->updateOrderStatusHistory($this->event_data['transaction']['order_no'], '', $comments); + $this->sendWebhookMail($comments); + $this->displayMessage(['message' => $comments]); + } + + /** + * Handle transaction update + * + */ + function handleTransactionUpdate() { + global $currencies; + if (in_array( $this->event_data['transaction']['status'], array('PENDING', 'ON_HOLD', 'CONFIRMED', 'DEACTIVATED'))) { + $novalnet_update_data = [ + 'status' => $this->event_data ['transaction']['status'], + ]; + $order_status = ''; + if ($this->event_data['transaction']['status'] == 'DEACTIVATED') { + $transaction_comments = sprintf(MODULE_PAYMENT_NOVALNET_TRANS_DEACTIVATED_MESSAGE, gmdate('d.m.Y'), gmdate('H:i:s')); + } else { + if (in_array($this->order_details['nn_trans_details']['status'], array('PENDING', 'ON_HOLD' ), true)) { + if (empty($this->event_data['instalment']['cycle_amount'])) { + $amount = $this->event_data['transaction']['amount']; + } else { + $amount = $this->event_data['instalment']['cycle_amount']; + } + + if ($this->order_details['nn_trans_details']['status'] == 'PENDING') { + if ($this->event_data['transaction']['status'] == 'ON_HOLD'){ + $order_status = 99; + $transaction_comments = sprintf(NOVALNET_PAYMENT_STATUS_PENDING_TO_ONHOLD_TEXT, $this->event_tid, gmdate('d.m.Y'), gmdate('H:i:s')); + } else if ($this->event_data['transaction']['status'] == 'CONFIRMED') { + $order_status = 2; + if (in_array($this->event_data['transaction']['payment_type'], array('INVOICE', 'GUARANTEED_INVOICE','INSTALMENT_INVOICE'))) { + $transaction_comments = PHP_EOL.sprintf(NOVALNET_WEBHOOK_TRANSACTION_UPDATE_NOTE_DUE_DATE, $this->event_data['transaction']['tid'], $currencies->format(($this->event_data['transaction']['amount']/100), 1, $this->event_data['transaction']['currency']), $this->event_data['transaction']['due_date']).PHP_EOL.PHP_EOL; + } else { + $transaction_comments = PHP_EOL.sprintf(NOVALNET_WEBHOOK_TRANSACTION_UPDATE_NOTE, $this->event_data['transaction']['tid'], $currencies->format(($amount/100), 1, $this->event_data['transaction']['currency']),gmdate('d.m.Y')).PHP_EOL.PHP_EOL; + } + + } + } + + if ($this->order_details['nn_trans_details']['status'] == 'ON_HOLD') { + if($this->event_data['transaction']['status'] == 'CONFIRMED') { + $order_status = 2; + if (in_array($this->event_data['transaction']['payment_type'], array('INVOICE', 'GUARANTEED_INVOICE','INSTALMENT_INVOICE'))) { + $transaction_comments = PHP_EOL.sprintf(MODULE_PAYMENT_NOVALNET_TRANS_CONFIRM_SUCCESSFUL_MESSAGE, $this->event_data['transaction']['tid'], $this->event_data['transaction']['due_date']).PHP_EOL.PHP_EOL; + } else { + $transaction_comments = PHP_EOL.sprintf(MODULE_PAYMENT_NOVALNET_TRANS_CONFIRM_SUCCESSFUL_MESSAGE_TEXT, $this->event_data['transaction']['tid'], gmdate('d.m.Y')).PHP_EOL.PHP_EOL; + } + } + } + + if ($this->event_data['transaction']['status'] == 'CONFIRMED') { + if (in_array( $this->event_data['transaction']['payment_type'], array('INSTALMENT_INVOICE','INSTALMENT_DIRECT_DEBIT_SEPA'))) { + if (empty($this->order_details['nn_trans_details']['instalment_cycle_details'])) { + $total_amount = ($this->order_details['nn_trans_details']['amount'] < $this->event_data['transaction']['amount']) ? $this->event_data['transaction']['amount'] : $this->order_details['nn_trans_details']['amount']; + $novalnet_update_data['instalment_cycle_details'] = NovalnetHelper::storeInstalmentdetails($this->event_data, $total_amount); + } + } + $order_status = 2; + $novalnet_update_data['callback_amount'] = $this->order_details['nn_trans_details']['amount']; + } + + // Reform the transaction comments. + $transaction_comments .= NovalnetHelper::getTransactionDetails($this->event_data); + if (in_array($this->event_data['transaction']['payment_type'], array( 'INSTALMENT_INVOICE','GUARANTEED_INVOICE', 'INVOICE', 'PREPAYMENT'))) { + if (empty($this->event_data ['transaction']['bank_details'])) { + if(!empty($this->order_details['nn_trans_details']['payment_details'])) { + $bank_data = json_decode($this->order_details['nn_trans_details']['payment_details']); + $this->event_data ['transaction']['bank_details'] = array( + 'account_holder' => $bank_data->account_holder, + 'iban' => $bank_data->iban, + 'bic' => $bank_data->bic, + 'bank_name' => $bank_data->bank_name, + 'bank_place' => $bank_data->bank_city, + ); + } else { + $this->event_data ['transaction']['bank_details'] = json_decode($this->order_details['nn_trans_details']['payment_details'], true); + } + } + $transaction_comments .= NovalnetHelper::getBankDetails($this->event_data); + + } + if ('CASHPAYMENT' === $this->event_data ['transaction']['payment_type']) { + $this->event_data ['transaction']['nearest_stores'] = json_decode($this->order_details['nn_trans_details']['payment_details'], true); + $transaction_comments .= NovalnetHelper::getBankDetails($this->event_data); + } + if (in_array($this->event_data['transaction']['payment_type'], array( 'INSTALMENT_INVOICE','INSTALMENT_DIRECT_DEBIT_SEPA'))) { + $transaction_comments .= NovalnetHelper::getInstalmentDetails($this->event_data); + } else { + if ((int)$this->event_data['transaction']['amount'] != (int)$this->order_details['nn_trans_details']['amount']) { + $novalnet_update_data['amount'] = $this->event_data['transaction']['amount']; + if('CONFIRMED' === $this->event_data['transaction']['status']) { + $novalnet_update_data['callback_amount'] = $this->event_data['transaction']['amount']; + } + } + } + } + } + $this->updateNovalnetTransaction($novalnet_update_data, "tid='{$this->parent_tid}'"); + $this->updateOrderStatusHistory($this->order_details['shop_order'], $order_status, $transaction_comments); + $this->sendWebhookMail($comments); + $this->displayMessage([ 'message' => $transaction_comments]); + } + } + + /** + * Handle Payment Reminder + * + */ + function handlePaymentReminder() { + $comments =sprintf(NOVALNET_PAYMENT_REMINDER_NOTE , explode('_', $this->event_type)[2]); + $this->updateOrderStatusHistory($this->event_data['transaction']['order_no'], '', $comments, 0); + $this->sendWebhookMail($comments); + $this->displayMessage([ 'message' => $comments]); + } + + /** + * Handle Collection Agency Submission + * + */ + function handleCollectionSubmission() { + $comments =sprintf(NOVALNET_COLLECTION_SUBMISSION_NOTE , $this->event_data['collection']['reference']); + $this->updateOrderStatusHistory($this->event_data['transaction']['order_no'], '', $comments, 0); + $this->sendWebhookMail($comments); + $this->displayMessage([ 'message' => $comments]); + } + + /** + * Print the Webhook messages. + * + * @param $message + * + * @return void + */ + function displayMessage($message) { + echo json_encode($message); + exit; + } + + /** + * Update the details in Shop order status table. + * + * @param $order_id + * @param $order_status_id + * @param $comments + * @param $customer_notified + */ + function updateOrderStatusHistory($order_id, $order_status_id = '', $comments = '', $customer_notified = 1) { + + $datas_need_to_update = []; + if ($order_status_id == '') { + $order_status_id = $this->order_details['shop_order_details']['orders_status']; + } + $datas_need_to_update['orders_status'] = $order_status_id; + zen_db_perform(TABLE_ORDERS, $datas_need_to_update, "update", "orders_id='$order_id'"); + + + $data_array = array( + 'orders_id' => $order_id, + 'orders_status_id' => $order_status_id, + 'date_added' => date('Y-m-d H:i:s'), + 'customer_notified' => $customer_notified, + 'comments' => zen_db_prepare_input($comments . PHP_EOL) + ); + zen_db_perform(TABLE_ORDERS_STATUS_HISTORY,$data_array, 'insert'); + } + + /* + * Update the transaction details in Novalnet table + * + * @param $data + * @param $parameters + * @param $action + */ + function updateNovalnetTransaction($data, $parameters = '', $action = 'update') { + if ($action != 'insert' && $parameters == '') { + return false; + } + zen_db_perform('novalnet_transaction_detail', $data, $action, $parameters); + } + + /** + * Send notification mail to Merchant + * + * @param $comments + */ + function sendWebhookMail($comments) { + $email = NovalnetHelper::validateEmail(MODULE_PAYMENT_NOVALNET_CALLBACK_MAIL_TO); + // Assign email to address + $email_to = !empty($email) ? $email : STORE_OWNER_EMAIL_ADDRESS; + $order_subject = 'Novalnet Callback Script Access Report - '.STORE_NAME; + // Send mail + zen_mail($email ,$email_to, $order_subject, $comments , STORE_NAME, EMAIL_FROM); + } + + /** + * Include language file and helper file. + */ + function include_required_files($lang_data) { + // include language + require_once (DIR_WS_CLASSES.'language.php'); + $lang = new language($lang_data['code']); + include_once(DIR_FS_CATALOG . DIR_WS_LANGUAGES. $lang->language['directory']."/modules/payment/novalnet_payments.php"); + // include helper file after language files. + require_once(DIR_FS_CATALOG . DIR_WS_MODULES. 'payment/novalnet/NovalnetHelper.class.php'); + return; + } +} +new NovalnetWebhooks(); +?> diff --git a/includes/languages/english/modules/payment/novalnet_payments.php b/includes/languages/english/modules/payment/novalnet_payments.php new file mode 100644 index 0000000..5ce2c06 --- /dev/null +++ b/includes/languages/english/modules/payment/novalnet_payments.php @@ -0,0 +1,149 @@ +Please read the Installation Guide before you start and login to the Novalnet Admin Portal using your merchant account. To get a merchant account, mail to sales@novalnet.de or call +49 (089) 923068320

Payment plugin configurations are now available in the Novalnet Admin Portal.Navigate to the Account -> Payment plugin configuration of your projects to configure them.

Our platform offers a test mode for all requests; You can control the behaviour of the payment methods by using the Novalnet test payment data'); +define('MODULE_PAYMENT_NOVALNET_PUBLIC_KEY_TITLE', 'Product activation key'); +define('MODULE_PAYMENT_NOVALNET_PUBLIC_KEY_DESCRIPTION', 'Get your Product activation key from the Novalnet Admin Portal Projects > Choose your project > API credentials > API Signature (Product activation key)'); +define('MODULE_PAYMENT_NOVALNET_PAYMENT_ACCESS_KEY_TITLE', 'Payment access key'); +define('MODULE_PAYMENT_NOVALNET_PAYMENT_ACCESS_KEY_DESCRIPTION', 'Get your Payment access key from the Novalnet Admin Portal Projects > Choose your project > API credentials > Payment access key'); +define('MODULE_PAYMENT_NOVALNET_TARIFF_ID_TITLE', 'Select Tariff ID'); +define('MODULE_PAYMENT_NOVALNET_TARIFF_ID_DESCRIPTION', 'Select a Tariff ID to match the preferred tariff plan you created at the Novalnet Admin Portal for this project'); + +define('MODULE_PAYMENT_NOVALNET_CALLBACK_TEST_MODE_TITLE', '

Notification / Webhook URL Setup

Allow manual testing of the Notification / Webhook URL'); +define('MODULE_PAYMENT_NOVALNET_CALLBACK_TEST_MODE_DESC', 'Enable this to test the Novalnet Notification / Webhook URL manually. Disable this before setting your shop live to block unauthorized calls from external parties'); +define('MODULE_PAYMENT_NOVALNET_CALLBACK_MAIL_SEND_TITLE', 'Enable e-mail notification'); +define('MODULE_PAYMENT_NOVALNET_CALLBACK_MAIL_SEND_DESC', 'Enable this option to notify the given e-mail address when the Notification / Webhook URL is executed successfully'); +define('MODULE_PAYMENT_NOVALNET_CALLBACK_MAIL_TO_TITLE', '
Send e-mail to'); +define('MODULE_PAYMENT_NOVALNET_CALLBACK_MAIL_TO_DESC', 'Notification / Webhook URL execution messages will be sent to this e-mail'); +define('MODULE_PAYMENT_NOVALNET_CALLBACK_URL_TITLE', 'Notification / Webhook URL'); +define('MODULE_PAYMENT_NOVALNET_CALLBACK_URL_DESC', 'Notification / Webhook URL is required to keep the merchant’s database/system synchronized with the Novalnet account (e.g. delivery status). Refer the Installation Guide for more information'); + +define('MODULE_PAYMENT_NOVALNET_CREDENTIALS_ERROR', 'Please enter a valid Product Activation Key and Payment Access key'); +define('MODULE_PAYMENT_NOVALNET_WEBHOOKURL_ERROR', 'Please enter the valid Webhook URL'); +define('MODULE_PAYMENT_NOVALNET_WEBHOOKURL_CONFIGURE_SUCCESS_TEXT', 'Notification / Webhook URL is configured successfully in Novalnet Admin Portal'); +define('MODULE_PAYMENT_NOVALNET_WEBHOOKURL_CONFIGURE_ALERT_TEXT', 'Are you sure you want to configure the Webhook URL in Novalnet Admin Portal?'); + +define('MODULE_PAYMENT_NOVALNET_AMOUNT_TRANSFER_NOTE_DUE_DATE', 'Please transfer the amount of %1$s to the following account on or before %2$s'); +define('MODULE_PAYMENT_NOVALNET_AMOUNT_TRANSFER_NOTE', 'Please transfer the amount of %s to the following account.'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_AMOUNT_TRANSFER_NOTE_DUE_DATE', 'Please transfer the instalment cycle amount of %1$s to the following account on or before %2$s'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_AMOUNT_TRANSFER_NOTE', 'Please transfer the instalment cycle amount of %1$s to the following account.'); +define('MODULE_PAYMENT_NOVALNET_MULTIBANCO_NOTE', 'Please use the following payment reference details to pay the amount of %s at a Multibanco ATM or through your internet banking.'); +define('MODULE_PAYMENT_NOVALNET_BANK_NAME', ' Bank: '); +define('MODULE_PAYMENT_NOVALNET_IBAN','IBAN: '); +define('MODULE_PAYMENT_NOVALNET_BIC', ' BIC: '); +define('MODULE_PAYMENT_NOVALNET_ACCOUNT_HOLDER','Account holder: '); +define('MODULE_PAYMENT_NOVALNET_AMOUNT', ' Amount: '); +define('MODULE_PAYMENT_NOVALNET_PAYMENT_MODE', 'Test order'); +define('MODULE_PAYMENT_NOVALNET_BANK_PLACE', 'Place: '); +define('MODULE_PAYMENT_NOVALNET_VALID_ACCOUNT_CREDENTIALS_ERROR', 'Your account details are invalid'); +define('MODULE_PAYMENT_NOVALNET_TRANSACTION_ID', 'Novalnet transaction ID: '); +define('MODULE_PAYMENT_NOVALNET_TRANS_SLIP_EXPIRY_DATE', 'Slip expiry date : '); +define('MODULE_PAYMENT_NOVALNET_NEAREST_STORE_DETAILS', 'Store(s) near to you: '); +define('MODULE_PAYMENT_NOVALNET_PAYMENT_REFERENCE_TEXT', 'Please use any of the following payment references when transferring the amount. This is necessary to match it with your corresponding order'); +define('MODULE_PAYMENT_NOVALNET_CONFIRM_TEXT','Confirm'); +define('MODULE_PAYMENT_NOVALNET_REFUND_TEXT','Refund'); +define('MODULE_PAYMENT_NOVALNET_CANCEL_TEXT','Cancel'); +define('MODULE_PAYMENT_NOVALNET_TRANSACTION_ERROR', 'Payment was not successful. An error occured.'); +define('MODULE_PAYMENT_NOVALNET_SELECT_STATUS_OPTION', '--Select--'); +define('MODULE_PAYMENT_NOVALNET_TRANS_CONFIRM_SUCCESSFUL_MESSAGE', 'The transaction has been confirmed successfully for the TID %1$s and the due date updated as %2$s'); +define('MODULE_PAYMENT_NOVALNET_TRANS_CONFIRM_SUCCESSFUL_MESSAGE_TEXT', 'The transaction has been confirmed on %1$s'); +define('MODULE_PAYMENT_NOVALNET_TRANS_DEACTIVATED_MESSAGE', 'The transaction has been cancelled on %1$s'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_CANCELED_MESSAGE', 'The transaction has been cancelled for the %1$s on %2$s %3$s'); +define('MODULE_PAYMENT_NOVALNET_AMOUNT_EX', ' (in minimum unit of currency. E.g. enter 100 which is equal to 1.00)'); +define('MODULE_PAYMENT_NOVALNET_REFUND_PARENT_TID_MSG', 'Refund has been initiated for the TID: %1$s with the amount of %2$s.'); +define('MODULE_PAYMENT_NOVALNET_REFUND_CHILD_TID_MSG', 'New TID:%s for the refunded amount'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_TEXT', ' (Net loan amount: )'); +define('MODULE_PAYMENT_NOVALNET_INSTALLMENT_CYCLES_FRONTEND', 'INSTALMENT CYCLES  '); +define('MODULE_PAYMENT_NOVALNET_INSTALLMENT_AMOUNT_FRONTEND', 'INSTALMENT AMOUNT'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_SUMMARY_BACKEND', 'Instalment summary'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_CANCEL_ADMIN_TEXT','Instalment cancel'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_AMOUNT_BACKEND', 'Amount'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_DATE_BACKEND', 'Date'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_STATUS_BACKEND', 'Status'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_REFERENCE_BACKEND', 'Novalnet Transaction ID'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_CANCEL_TEXT', 'Cancel'); +define('MODULE_PAYMENT_NOVALNET_MENTION_GUARANTEE_PAYMENT_PENDING_TEXT', 'Your order is under verification and we will soon update you with the order status. Please note that this may take upto 24 hours.'); +define('MODULE_PAYMENT_NOVALNET_VALID_MERCHANT_CREDENTIALS_ERROR','Please fill in the required fields'); +define('MODULE_PAYMENT_NOVALNET_GLOBAL_CONFIG_TEXT_TITLE','Novalnet API Configuration (V_13.0.0)'); +define('MODULE_PAYMENT_NOVALNET_TESTMODE','Test mode'); +define('MODULE_PAYMENT_NOVALNET_PAYMENT_REFERENCE', 'Payment Reference : %1$s'); +define('NOVALNET_WEBHOOK_CREDIT_NOTE','Credit has been successfully received for the TID: %1$s with amount %2$s on %3$s. Please refer PAID order details in our Novalnet Admin Portal for the TID: %4$s'); +define('NOVALNET_WEBHOOK_CHARGEBACK_NOTE','Chargeback executed successfully for the TID: %1$s amount: %2$s on %3$s %4$s . The subsequent TID: %5$s'); +define('NOVALNET_WEBHOOK_NEW_INSTALMENT_NOTE','A new instalment has been received for the Transaction ID: %1$s with amount %2$s on %3$s. The new instalment transaction ID is: %4$s'); +define('NOVALNET_WEBHOOK_INSTALMENT_CANCEL_NOTE','Instalment has been cancelled for the TID: %1$s on %2$s'); +define('NOVALNET_WEBHOOK_TRANSACTION_UPDATE_NOTE_DUE_DATE','Transaction updated successfully for the TID: %1$s with amount %2$s and the due date updated as %3$s.'); +define('NOVALNET_WEBHOOK_TRANSACTION_UPDATE_NOTE','Transaction updated successfully for the TID: %1$s with amount %2$s on %3$s'); +define('NOVALNET_PAYMENT_REMINDER_NOTE','Payment Reminder %1$s has been sent to the customer.'); +define('NOVALNET_COLLECTION_SUBMISSION_NOTE','The transaction has been submitted to the collection agency. Collection Reference: %1$s'); + +define('NOVALNET_PAYMENT_STATUS_PENDING_TO_ONHOLD_TEXT','The transaction status has been changed from pending to on-hold for the TID: %1$s on %2$s'); + +define('MODULE_PAYMENT_NOVALNET_PARTNER_PAYMENT_REFERENCE', 'Partner Payment Reference: %s'); +define('MODULE_PAYMENT_NOVALNET_ERROR_MSG', 'Check hash failed'); +define('MODULE_PAYMENT_NOVALNET_TRANS_CONFIRM_TITLE','Manage Transaction'); +define('MODULE_PAYMENT_NOVALNET_PAYMENT_CAPTURE_CONFIRM','Are you sure you want to capture the payment?'); +define('MODULE_PAYMENT_NOVALNET_PAYMENT_VOID_CONFIRM','Are you sure you want to cancel the payment?'); +define('MODULE_PAYMENT_NOVALNET_SELECT_STATUS_TEXT', 'Please select status'); +define('MODULE_PAYMENT_NOVALNET_BACK_TEXT', 'Back'); +define('MODULE_PAYMENT_NOVALNET_REFUND_TITLE', 'Refund process'); +define('MODULE_PAYMENT_NOVALNET_PAYMENT_REFUND_CONFIRM', 'Are you sure you want to refund the amount'); +define('MODULE_PAYMENT_NOVALNET_REFUND_REFERENCE_TEXT', 'Refund reference'); +define('MODULE_PAYMENT_NOVALNET_REFUND_AMT_TITLE', 'Please enter the refund amound'); +define('MODULE_PAYMENT_NOVALNET_REFUND_REASON_TITLE', 'Reason for refund (optional)'); +define('MODULE_PAYMENT_NOVALNET_INSTALLMENT_FRONTEND', 'Instalment'); +define('MODULE_PAYMENT_NOVALNET_INSTALLMENT_TEXT', 'Choose your installment plan (Net loan amount: %s )'); + +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_INSTALMENTS_INFO','Instalment information'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_PROCESSED_INSTALMENTS','Processed instalments: '); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_DUE_INSTALMENTS','Due instalments: '); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_NEXT_INSTALMENT_AMOUNT','Next instalment amount: '); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_NEXT_INSTALMENT_DATE','Next instalment date: '); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_PAY_DATE_BACKEND','Paid date'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_NEXT_DATE_BACKEND','Next instalment date'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_PAID_DATE_BACKEND','Paid on'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_STATUS_PAID','Paid'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_STATUS_PENDING','Pending'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_STATUS_REFUNDED','Refunded'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_STATUS_CANCELED','Canceled'); + +define('MODULE_PAYMENT_NOVALNET_GUARANTEE_DOB_ERROR_MSG','Enter valid date of birth'); +define('MODULE_PAYMENT_NOVALNET_ORDER_MAIL_SUBJECT', 'Your Order %s, %s, %s'); +define('MODULE_PAYMENT_NOVALNET_ORDER_CAPTURE_MAIL_SUBJECT', 'Order Confirmation - Your Order %s with Zencart has been confirmed!'); + +define('MODULE_PAYMENT_GUARANTEE_PAYMENT_MAIL_SUBJECT','Order Confirmation - Your Order %s with %s has been confirmed!'); + +define('MODULE_PAYMENT_NOVALNET_SEPA_IBAN', 'IBAN *'); +define('MODULE_PAYMENT_NOVALNET_BOOK_TITLE','Book transaction'); +define('MODULE_PAYMENT_NOVALNET_BOOK_AMT_TITLE','Transaction booking amount'); +define('MODULE_PAYMENT_NOVALNET_TRANS_BOOKED_MESSAGE','Your order has been booked with the amount of %s. Your new TID for the booked amount: %s'); +define('MODULE_PAYMENT_NOVALNET_PAYMENT_ZERO_AMOUNT_BOOK_CONFIRM','Are you sure you want to book the order amount?'); +define('MODULE_PAYMENT_NOVALNET_AMOUNT_ERROR_MESSAGE','The amount is invalid'); +define('MODULE_PAYMENT_NOVALNET_ZEROAMOUNT_BOOKING_MESSAGE','This order processed as a zero amount booking'); +define('MODULE_PAYMENT_NOVALNET_ZEROAMOUNT_BOOKING_TEXT','

This order will be processed as zero amount booking which store your payment data for further online purchases.'); + +define('MODULE_PAYMENT_GUARANTEE_PAYMENT_MAIL_MESSAGE','We are pleased to inform you that your order has been confirmed.'); +define('MODULE_PAYMENT_GUARANTEE_PAYMENT_MAIL_SUBJECT','Order Confirmation - Your Order %s with %s has been confirmed!'); + +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_CANCEL_ALLCYCLES','Cancel All Instalment'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_CANCEL_ALLCYCLES_TEXT','Instalment has been cancelled for the TID: %1$s on %2$s & Refund has been initiated with the amount %3$s'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_CANCEL_REMAINING_CYCLES','Cancel All Remaining Instalments'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_CANCEL_REMAINING_CYCLES_TEXT','Instalment has been stopped for the TID: %1$s on %2$s'); + +define('MODULE_PAYMENT_NOVALNET_ALLCYCLES_ERROR_MESSAGE','Are you sure you want to cancel all cycles?'); +define('MODULE_PAYMENT_NOVALNET_REMAINING_CYCLES_ERROR_MESSAGE','Are you sure you want to cancel remaining cycles?'); + +define('MODULE_PAYMENT_NOVALNET_WALLET_PAYMENT_SUCCESS_TEXT','Your order was successfully processed using Google Pay (Visa **** %s)'); +?> + diff --git a/includes/languages/german/modules/payment/novalnet_payments.php b/includes/languages/german/modules/payment/novalnet_payments.php new file mode 100644 index 0000000..f5585d4 --- /dev/null +++ b/includes/languages/german/modules/payment/novalnet_payments.php @@ -0,0 +1,147 @@ +Bevor Sie beginnen, lesen Sie bitte die Installationsanleitung und melden Sie sich mit Ihrem Händlerkonto im Novalnet Admin-Portal an. Um ein Händlerkonto zu erhalten, senden Sie bitte eine E-Mail an sales@novalnet.de oder rufen Sie uns unter +49 89 923068320 an

Die Konfigurationen der Zahlungsplugins sind jetzt im Novalnet Admin-Portal verfügbar. Navigieren Sie zu Konto -> Konfiguration des Shops Ihrer Projekte, um sie zu konfigurieren.

Novalnet ermöglicht es Ihnen, das Verhalten der Zahlungsmethode zu überprüfen, bevor Sie in den Produktionsmodus gehen, indem Sie Testzahlungsdaten verwenden. Zugang zu den Novalnet-Testzahlungsdaten finden Sie hier '); +define('MODULE_PAYMENT_NOVALNET_PUBLIC_KEY_TITLE', 'Aktivierungsschlüssel des Produkts'); +define('MODULE_PAYMENT_NOVALNET_PUBLIC_KEY_DESCRIPTION', 'Ihren Produktaktivierungsschlüssel finden Sie im Novalnet Admin-Portal Projekte > Wählen Sie Ihr Projekt > API-Anmeldeinformationen > API-Signatur (Produktaktivierungsschlüssel)'); +define('MODULE_PAYMENT_NOVALNET_PAYMENT_ACCESS_KEY_TITLE', 'Zahlungs-Zugriffsschlüssel'); +define('MODULE_PAYMENT_NOVALNET_PAYMENT_ACCESS_KEY_DESCRIPTION', 'Ihren Paymentzugriffsschlüssel finden Sie im Novalnet Admin-Portal Projekte > Wählen Sie Ihr Projekt > API-Anmeldeinformationen > Paymentzugriffsschlüssel'); +define('MODULE_PAYMENT_NOVALNET_TARIFF_ID_TITLE', 'Auswahl der Tarif-ID'); +define('MODULE_PAYMENT_NOVALNET_TARIFF_ID_DESCRIPTION', 'Wählen Sie eine Tarif-ID, die dem bevorzugten Tarifplan entspricht, den Sie im Novalnet Admin-Portal für dieses Projekt erstellt haben'); +define('MODULE_PAYMENT_NOVALNET_CALLBACK_TEST_MODE_TITLE', '

Benachrichtigungs- / Webhook-URL festlegen


Manuelles Testen der Benachrichtigungs / Webhook-URL erlauben'); +define('MODULE_PAYMENT_NOVALNET_CALLBACK_TEST_MODE_DESC', 'Aktivieren Sie diese Option, um die Novalnet-Benachrichtigungs-/Webhook-URL manuell zu testen. Deaktivieren Sie die Option, bevor Sie Ihren Shop liveschalten, um unautorisierte Zugriffe von Dritten zu blockieren'); +define('MODULE_PAYMENT_NOVALNET_CALLBACK_URL_TITLE', 'Benachrichtigung / Webhook-URL im Novalnet-Verwaltungsportal'); +define('MODULE_PAYMENT_NOVALNET_CALLBACK_URL_DESC', 'Sie müssen die folgende Webhook-URL im Novalnet Admin-Portal hinzufügen. Dadurch können Sie Benachrichtigungen über den Transaktionsstatus erhalten'); +define('MODULE_PAYMENT_NOVALNET_AMOUNT_TRANSFER_NOTE_DUE_DATE', 'Bitte überweisen Sie den Betrag von %1$s spätestens bis zum %2$s auf das folgende Konto'); +define('MODULE_PAYMENT_NOVALNET_CALLBACK_MAIL_TO_TITLE', '
E-Mails senden an'); +define('MODULE_PAYMENT_NOVALNET_CALLBACK_MAIL_TO_DESC', 'E-Mail-Benachrichtigungen werden an diese E-Mail-Adresse gesendet'); + +define('MODULE_PAYMENT_NOVALNET_CREDENTIALS_ERROR', 'Bitte geben Sie den gültigen Produktaktivierungsschlüssel und Paymentzugriffsschlüssel ein'); +define('MODULE_PAYMENT_NOVALNET_WEBHOOKURL_ERROR', 'Bitte geben Sie eine gültige Webhook-URL ein'); +define('MODULE_PAYMENT_NOVALNET_WEBHOOKURL_CONFIGURE_SUCCESS_TEXT', 'Callbackskript-/ Webhook-URL wurde erfolgreich im Novalnet Admin Portal konfiguriert'); +define('MODULE_PAYMENT_NOVALNET_WEBHOOKURL_CONFIGURE_ALERT_TEXT', 'Sind Sie sicher, dass Sie die Webhook-URL im Novalnet Admin Portal konfigurieren möchten?'); + + +define('MODULE_PAYMENT_NOVALNET_AMOUNT_TRANSFER_NOTE', 'Bitte überweisen Sie den Betrag %s auf das folgende Konto.'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_AMOUNT_TRANSFER_NOTE_DUE_DATE', 'Bitte überweisen Sie den anzahl der raten von %1$s spätestens bis zum %2$s auf das folgende Konto'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_AMOUNT_TRANSFER_NOTE', 'Bitte überweisen Sie den anzahl der raten %1$s auf das folgende Konto.'); +define('MODULE_PAYMENT_NOVALNET_MULTIBANCO_NOTE', 'Bitte verwenden Sie die folgende Zahlungsreferenz, um den Betrag von %s an einem Multibanco-Geldautomaten oder über Ihr Onlinebanking zu bezahlen.'); +define('MODULE_PAYMENT_NOVALNET_BANK_NAME', 'Bank: '); +define('MODULE_PAYMENT_NOVALNET_IBAN','IBAN: '); +define('MODULE_PAYMENT_NOVALNET_BIC', ' BIC: '); +define('MODULE_PAYMENT_NOVALNET_ACCOUNT_HOLDER','Kontoinhaber: '); +define('MODULE_PAYMENT_NOVALNET_AMOUNT', ' Betrag: '); +define('MODULE_PAYMENT_NOVALNET_PAYMENT_MODE', 'Testbestellung'); +define('MODULE_PAYMENT_NOVALNET_BANK_PLACE', 'Ort: '); +define('MODULE_PAYMENT_NOVALNET_VALID_ACCOUNT_CREDENTIALS_ERROR', 'Ihre Kontodaten sind ungültig.'); +define('MODULE_PAYMENT_NOVALNET_TRANSACTION_ID', 'Novalnet-Transaktions-ID: '); +define('MODULE_PAYMENT_NOVALNET_TRANS_SLIP_EXPIRY_DATE', 'Verfallsdatum des Zahlscheins: '); +define('MODULE_PAYMENT_NOVALNET_NEAREST_STORE_DETAILS', 'Barzahlen-Partnerfilialen in Ihrer Nähe: '); +define('MODULE_PAYMENT_NOVALNET_PAYMENT_REFERENCE_TEXT', 'Bitte verwenden Sie einen der unten angegebenen Verwendungszwecke für die Überweisung. Nur so kann Ihr Geldeingang Ihrer Bestellung zugeordnet werden'); +define('MODULE_PAYMENT_NOVALNET_CONFIRM_TEXT','Bestätigen'); +define('MODULE_PAYMENT_NOVALNET_REFUND_TEXT','Rückerstattung'); +define('MODULE_PAYMENT_NOVALNET_CANCEL_TEXT','Stornieren'); +define('MODULE_PAYMENT_NOVALNET_TRANSACTION_ERROR', 'Die Zahlung war nicht erfolgreich. Ein Fehler ist aufgetreten.'); +define('MODULE_PAYMENT_NOVALNET_SELECT_STATUS_OPTION', '--Auswählen--'); +define('MODULE_PAYMENT_NOVALNET_TRANS_CONFIRM_SUCCESSFUL_MESSAGE','Die Buchung wurde am %1$s Uhr bestätigt'); +define('MODULE_PAYMENT_NOVALNET_TRANS_CONFIRM_SUCCESSFUL_MESSAGE_TEXT', 'Die Buchung wurde am %1$s'); +define('MODULE_PAYMENT_NOVALNET_TRANS_DEACTIVATED_MESSAGE', 'Die Transaktion wurde am %1$s Uhr storniert'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_CANCELED_MESSAGE', 'Die Transaktion wurde storniert für die %1$s auf %2$s %3$s'); +define('MODULE_PAYMENT_NOVALNET_AMOUNT_EX', ' (in der kleinsten Währungseinheit, z.B. 100 Cent = entsprechen 1.00 EUR)'); +define('MODULE_PAYMENT_NOVALNET_REFUND_PARENT_TID_MSG', 'Die Rückerstattung für die TID: %1$s mit dem Betrag %2$s wurde veranlasst.'); +define('MODULE_PAYMENT_NOVALNET_REFUND_CHILD_TID_MSG', ' Die neue TID: %s für den erstatteten Betrag'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_TEXT', ' (Netto-Kreditbetrag : )'); +define('MODULE_PAYMENT_NOVALNET_INSTALLMENT_CYCLES_FRONTEND', 'ANZAHL DER RATEN '); +define('MODULE_PAYMENT_NOVALNET_INSTALLMENT_AMOUNT_FRONTEND', 'RATENBETRAG'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_SUMMARY_BACKEND', 'Zusammenfassung der Ratenzahlung'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_CANCEL_ADMIN_TEXT','Raten stornier'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_AMOUNT_BACKEND', 'Betrag'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_DATE_BACKEND', 'Datum'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_STATUS_BACKEND', 'Status'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_REFERENCE_BACKEND', 'Novalnet-Transaktions-ID'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_CANCEL_TEXT', 'Stornieren'); +define('MODULE_PAYMENT_NOVALNET_MENTION_GUARANTEE_PAYMENT_PENDING_TEXT', 'Ihre Bestellung wird derzeit überprüft. Wir werden Sie in Kürze über den Bestellstatus informieren. Bitte beachten Sie, dass dies bis zu 24 Stunden dauern kann.'); +define('MODULE_PAYMENT_NOVALNET_VALID_MERCHANT_CREDENTIALS_ERROR', 'Bitte füllen Sie die erforderlichen Felder aus'); +define('MODULE_PAYMENT_NOVALNET_GLOBAL_CONFIG_TEXT_TITLE','Novalnet API-Konfiguration (V_13.0.0)'); + +define('MODULE_PAYMENT_NOVALNET_TESTMODE','Testmodus'); +define('MODULE_PAYMENT_NOVALNET_PAYMENT_REFERENCE', 'Verwendungszweck : %1$s'); +define('NOVALNET_WEBHOOK_CREDIT_NOTE','Die Gutschrift für die TID ist erfolgreich eingegangen: %1$s mit Betrag %2$s am %3$s. Bitte entnehmen Sie die TID den Einzelheiten der Bestellung bei BEZAHLT in unserem Novalnet Adminportal: %4$s'); +define('NOVALNET_WEBHOOK_CHARGEBACK_NOTE','Chargeback erfolgreich importiert für die TID: %1$s Betrag: %2$s am %3$s um %4$s Uhr. TID der Folgebuchung: %5$s'); +define('NOVALNET_WEBHOOK_NEW_INSTALMENT_NOTE','Für die Transaktions-ID ist eine neue Rate eingegangen: %1$s mit Betrag %2$s am %3$s. Die Transaktions-ID der neuen Rate lautet: %4$s'); +define('NOVALNET_WEBHOOK_INSTALMENT_CANCEL_NOTE','Die Ratenzahlung für die TID wurde gekündigt: %1$s am %2$s'); + +define('NOVALNET_PAYMENT_STATUS_PENDING_TO_ONHOLD_TEXT','Der Status der Transaktion mit der TID: %1$s wurde am %2$s um von ausstehend auf ausgesetzt geändert '); + +define('NOVALNET_WEBHOOK_TRANSACTION_UPDATE_NOTE_DUE_DATE','Transaktion mit TID %1$s und Betrag %2$s wurde am %3$s um erfolgreich aktualisiert '); +define('NOVALNET_WEBHOOK_TRANSACTION_UPDATE_NOTE','Transaktion mit TID %1$s und Betrag %2$s wurde am um erfolgreich.'); +define('NOVALNET_PAYMENT_REMINDER_NOTE','Zahlungserinnerung %1$s wurde an den Kunden gesendet.'); +define('NOVALNET_COLLECTION_SUBMISSION_NOTE','Die Transaktion wurde an das Inkassobüro übergeben. Inkasso-Referenz: %1$s'); +define('MODULE_PAYMENT_NOVALNET_GUARANTEE_DOB_EMPTY_ERROR_MESSAGE', 'Geben Sie Ihr Geburtsdatum ein'); + +define('MODULE_PAYMENT_NOVALNET_PARTNER_PAYMENT_REFERENCE', 'Partner-Zahlungsreferenz: %s'); +define('MODULE_PAYMENT_NOVALNET_ERROR_MSG', 'Prüfung des Hashes fehlgeschlagen'); +define('MODULE_PAYMENT_NOVALNET_TRANS_CONFIRM_TITLE','Transaktion verwalten'); +define('MODULE_PAYMENT_NOVALNET_PAYMENT_CAPTURE_CONFIRM','Sind Sie sicher, dass Sie die Zahlung erfassen wollen?'); +define('MODULE_PAYMENT_NOVALNET_PAYMENT_VOID_CONFIRM','Sind Sie sicher, dass Sie die Zahlung stornieren möchten?'); +define('MODULE_PAYMENT_NOVALNET_SELECT_STATUS_TEXT', 'Bitte Status auswählen'); +define('MODULE_PAYMENT_NOVALNET_BACK_TEXT', 'Zurück'); +define('MODULE_PAYMENT_NOVALNET_REFUND_TITLE', 'Erstattungsverfahren'); +define('MODULE_PAYMENT_NOVALNET_PAYMENT_REFUND_CONFIRM', 'Sind Sie sicher, dass Sie den Betrag erstatten wollen?'); +define('MODULE_PAYMENT_NOVALNET_REFUND_REFERENCE_TEXT', 'Referenz für die Erstattung'); +define('MODULE_PAYMENT_NOVALNET_REFUND_AMT_TITLE', 'Bitte geben Sie den Erstattungsbetrag ein'); +define('MODULE_PAYMENT_NOVALNET_REFUND_REASON_TITLE', 'Grund für die Rückerstattung (optional)'); +define('MODULE_PAYMENT_NOVALNET_INSTALLMENT_FRONTEND', 'Ratenzahlung'); +define('MODULE_PAYMENT_NOVALNET_INSTALLMENT_TEXT', 'Wählen Sie Ihren Ratenzahlungsplan (Netto-Kreditbetrag: %s )'); + +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_INSTALMENTS_INFO','Informationen zur Ratenzahlung'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_PROCESSED_INSTALMENTS','Bearbeitete Raten: '); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_DUE_INSTALMENTS','Fällige Raten: '); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_NEXT_INSTALMENT_AMOUNT','Nächster Ratenbetrag: '); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_NEXT_INSTALMENT_DATE','Datum der nächsten Ratenzahlung: '); + +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_PAY_DATE_BACKEND', 'Bezahltes Datum'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_NEXT_DATE_BACKEND', 'Nächstes Ratenzahlungsdatum'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_PAID_DATE_BACKEND','Bezahlt am'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_STATUS_PAID','Bezahlt'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_STATUS_PENDING','Ausstehend'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_STATUS_REFUNDED','Rückerstattet'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_STATUS_CANCELED','Abgesagt'); + +define('MODULE_PAYMENT_NOVALNET_ORDER_MAIL_SUBJECT', 'Ihre Bestellung %s, am %s, %s'); +define('MODULE_PAYMENT_NOVALNET_ORDER_CAPTURE_MAIL_SUBJECT', 'Bestellbestätigung – Ihre Bestellung %s bei Zencart wurde bestätigt!'); +define('MODULE_PAYMENT_GUARANTEE_PAYMENT_MAIL_SUBJECT','Bestellbestätigung – Ihre Bestellung %s bei %s wurde bestätigt!'); + +define('MODULE_PAYMENT_NOVALNET_SEPA_IBAN', 'IBAN *'); +define('MODULE_PAYMENT_NOVALNET_BOOK_TITLE','Transaktion durchführen'); +define('MODULE_PAYMENT_NOVALNET_BOOK_AMT_TITLE','Buchungsbetrag der Transaktion'); +define('MODULE_PAYMENT_NOVALNET_TRANS_BOOKED_MESSAGE','Ihre Bestellung wurde mit einem Betrag von %s gebucht. Ihre neue TID für den gebuchten Betrag: %s'); +define('MODULE_PAYMENT_NOVALNET_PAYMENT_ZERO_AMOUNT_BOOK_CONFIRM','Sind Sie sich sicher, dass Sie den Bestellbetrag buchen wollen?'); +define('MODULE_PAYMENT_NOVALNET_AMOUNT_ERROR_MESSAGE','Ungültiger Betrag'); +define('MODULE_PAYMENT_NOVALNET_ZEROAMOUNT_BOOKING_MESSAGE','Diese Transaktion wird mit Nullbuchung bearbeitet'); +define('MODULE_PAYMENT_NOVALNET_ZEROAMOUNT_BOOKING_TEXT','

Diese Bestellung wird als Nullbuchung verarbeitet. Ihre Zahlungsdaten werden für zukünftige Online-Einkäufe gespeichert.'); + +define('MODULE_PAYMENT_NOVALNET_WALLET_PAYMENT_SUCCESS_TEXT','Ihre Bestellung wurde erfolgreich mit Google Pay durchgeführt (Visa **** %1$s)'); + +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_CANCEL_ALLCYCLES','Alle Raten stornieren'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_CANCEL_ALLCYCLES_TEXT','Die Ratenzahlung für die TID wurde gekündigt: %1$s am %2$s und die Rückerstattung wurde mit dem Betrag %3$s +Remaining Cycles'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_CANCEL_REMAINING_CYCLES','Cancel All Remaining Instalments'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_CANCEL_REMAINING_CYCLES_TEXT','Die Ratenzahlung für die TID wurde gestoppt: %1$s um %2$s'); + +define('MODULE_PAYMENT_NOVALNET_ALLCYCLES_ERROR_MESSAGE','Sind Sie sicher, dass Sie alle Zyklen abbrechen wollen?'); +define('MODULE_PAYMENT_NOVALNET_REMAINING_CYCLES_ERROR_MESSAGE','Sind Sie sicher, dass Sie die verbleibenden Zyklen abbrechen wollen?'); +?> + diff --git a/includes/modules/payment/novalnet/NovalnetHelper.class.php b/includes/modules/payment/novalnet/NovalnetHelper.class.php new file mode 100755 index 0000000..44744aa --- /dev/null +++ b/includes/modules/payment/novalnet/NovalnetHelper.class.php @@ -0,0 +1,820 @@ + !empty($order->billing['gender']) ? $order->billing['gender'] : 'u', + 'first_name' => !empty($order->billing['firstname']) ? $order->billing['firstname'] : $order->billing['name'], + 'last_name' => !empty($order->billing['lastname']) ? $order->billing['lastname'] : $order->billing['name'], + 'email' => $order->customer['email_address'], + 'customer_ip' => zen_get_ip_address(), + 'customer_no' => $_SESSION['customer_id'], + 'billing' => [ + 'street' => !empty($order->billing['suburb']) ? $order->billing['street_address'] . ',' . $order->billing['suburb'] : $order->billing['street_address'], + 'city' => $order->billing['city'], + 'state' => $order->billing['state'], + 'zip' => $order->billing['postcode'], + 'country_code' => $order->billing['country']['iso_code_2'], + 'search_in_street' => '1', + ], + ]; + if (!empty($order->customer['telephone'])) { + $data['customer']['tel'] = $order->customer['telephone']; + } + if (!empty($order->billing['company'])) { + $data['customer']['billing']['company'] = $order->billing['company']; + } + if (self::isBillingShippingsame()) { + $data['customer']['shipping']['same_as_billing'] = 1; + } else { + $data['customer']['shipping'] = [ + 'street' => !empty($order->delivery['suburb']) ? $order->delivery['street_address'] . ',' . $order->delivery['suburb'] : $order->delivery['street_address'], + 'city' => $order->delivery['city'], + 'state' => $order->delivery['state'], + 'zip' => $order->delivery['postcode'], + 'country_code' => $order->delivery['country']['iso_code_2'], + ]; + if (!empty($order->delivery['company'])) { + $data['customer']['shipping']['company'] = $order->delivery['company']; + } + } + if (!empty($_SESSION['nn_booking_details']->birth_date) && empty($order->billing['company'])) { + $data['customer']['birth_date'] = date("Y-m-d",strtotime('+'.$_SESSION['nn_booking_details']->birth_date.' days'));; + } + return $data; + } + + /** + * Get transaction data + * + * @return $data + */ + public static function getTransactionData() { + global $order; + $data['transaction'] = [ + 'amount' => self::getOrderAmount($order->info['total']), + 'currency' => $order->info['currency'], + 'system_name' => 'Zen_Cart', + 'system_version' => PROJECT_VERSION_MAJOR . '.' . PROJECT_VERSION_MINOR.'-NN13.0.0', + 'system_url' => ((ENABLE_SSL == true) ? HTTPS_SERVER : HTTP_SERVER . DIR_WS_CATALOG), + 'system_ip' => $_SERVER['SERVER_ADDR'], + ]; + if (isset($_SESSION['nn_booking_details']->test_mode)) { + $data['transaction']['test_mode'] = $_SESSION['nn_booking_details']->test_mode; + } + if (isset($_SESSION['nn_payment_details']->type)) { + $data['transaction']['payment_type'] = $_SESSION['nn_payment_details']->type; + } + if (!empty($_SESSION['nn_booking_details']->due_date)) { + $due_date = date("Y-m-d",strtotime('+'.$_SESSION['nn_booking_details']->due_date.' days')); + $data['transaction']['due_date'] = $due_date; + } + return $data; + } + + /** + * Get Card details like pesudo hash etc., + * + * @return $data + */ + public static function getAccountDetails() { + $data = []; + if ($_SESSION['nn_payment_details']->type == 'CREDITCARD') { + if (!empty($_SESSION['nn_booking_details']->pan_hash) || !empty($_SESSION['nn_booking_details']->unique_id)) + $data['transaction']['payment_data'] = [ + 'pan_hash' => $_SESSION['nn_booking_details']->pan_hash, + 'unique_id' => $_SESSION['nn_booking_details']->unique_id + ]; + } + if (in_array($_SESSION['nn_payment_details']->type, array('DIRECT_DEBIT_SEPA', 'INSTALMENT_DIRECT_DEBIT_SEPA', 'GUARANTEED_DIRECT_DEBIT_SEPA'))) { + if ($_SESSION['nn_booking_details']->iban != '') { + $data['transaction']['payment_data'] ['iban'] = $_SESSION['nn_booking_details']->iban; + if($_SESSION['nn_booking_details']->bic != '') { + $data['transaction']['payment_data'] ['bic'] = $_SESSION['nn_booking_details']->bic; + } + } + } + if(!empty($_SESSION['nn_booking_details']->payment_ref->token) && (empty($_SESSION['nn_booking_details']->pan_hash) || empty($_SESSION['nn_booking_details']->unique_id))) { // Reference transaction + $data['transaction']['payment_data']['token'] = $_SESSION['nn_booking_details']->payment_ref->token; + unset($_SESSION['nn_booking_details']->payment_ref->token); + } elseif(($_SESSION['nn_booking_details']->create_token == '1') && ((!empty($_SESSION['nn_booking_details']->pan_hash) || !empty($_SESSION['nn_booking_details']->unique_id)) || !empty($_SESSION['nn_booking_details']->iban)) ){ // New transaction + $data['transaction']['create_token'] = 1; + unset($_SESSION['nn_booking_details']->create_token); + } + if (in_array($_SESSION['nn_payment_details']->type, array('GOOGLEPAY', 'CREDITCARD')) && (isset($_SESSION['nn_booking_details']->enforce_3d))) { + if ($_SESSION['nn_booking_details']->enforce_3d == 1) { + $data['transaction']['enforce_3d'] = '1'; + } + } + return $data; + } + + /** + * Get request custom data + */ + public static function getCustomData() { + $data = []; + $data['custom'] = [ + 'lang' => (isset($_SESSION['languages_code'])) ? strtoupper($_SESSION['languages_code']) : 'DE', + ]; + return $data; + } + + /** + * Get hosted payment page data + * + * @return $data + */ + public static function getHostedPageData() { + $data = []; + $data['hosted_page'] = [ + 'hide_blocks' => ['ADDRESS_FORM', 'SHOP_INFO', 'LANGUAGE_MENU', 'HEADER', 'TARIFF'], + 'skip_pages' => ['CONFIRMATION_PAGE', 'SUCCESS_PAGE', 'PAYMENT_PAGE'], + 'type' => 'PAYMENTFORM', + ]; + return $data; + } + + /** + * Initial Call to get Redirect URL + * + * @param int $order_no Temp order number. + * @param string $payment_name End customer choosen payment name. + * + * @return $response + */ + public static function getRedirectData(&$params) { + if ($_SESSION['nn_payment_details']->type == 'PAYPAL') { + self::paypal_sheet_details($params); + } + if ($_SESSION['nn_payment_details']->type == 'GOOGLEPAY') { + $params['transaction']['payment_data']['wallet_token'] = $_SESSION['nn_booking_details']->wallet_token; + } + if(!empty($_SESSION['nn_booking_details']->token)) { + $params['transaction'] = array_merge(NovalnetHelper::getTransactionData()['transaction'], NovalnetHelper::getAccountDetails()['transaction']); + } + if ($_SESSION['nn_payment_details']->type == 'CREDITCARD') { + $params['transaction'] = array_merge(NovalnetHelper::getTransactionData()['transaction'], NovalnetHelper::getAccountDetails()['transaction']); + } + $params['transaction']['return_url'] = ((isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on") ? 'https://' : 'http://') . $_SERVER['HTTP_HOST']. $_SERVER['REQUEST_URI']; + $params['transaction']['error_return_url'] = ((isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on") ? 'https://' : 'http://') . $_SERVER['HTTP_HOST']. $_SERVER['REQUEST_URI']; + if ($_SESSION['nn_booking_details']->payment_action == 'authorized') { + $response = self::sendRequest($params, self::getActionEndpoint('authorize')); + } else { + $response = self::sendRequest($params, self::getActionEndpoint('payment')); + } + return $response; + } + + /** + * Check billing and shpping address is same + * + * @return boolean + */ + public static function isBillingShippingsame() { + global $order; + $delivery_address = array( + 'street' => ($order->delivery['street_address']), + 'city' => ( $order->delivery['city']), + 'postcode' => ( $order->delivery['postcode']), + 'country' => ($order->delivery['country']['iso_code_2']), + ); + $billing_address = array( + 'street' => ($order->billing['street_address']), + 'city' => ($order->billing['city']), + 'postcode' => ($order->billing['postcode']), + 'country' => ($order->billing['country']['iso_code_2']), + ); + return ($delivery_address === $billing_address); + } + + /** + * Get the order total amount and convert it into minimum unit amount (cents in Euro) + * @param $order_amount + * + * @return int + */ + public static function getOrderAmount($order_amount) { + return (sprintf('%0.2f', $order_amount) * 100); + } + + /** + * Get parameter for GooglePay process + * + * @return string Hidden fields with GooglePay data. + */ + public static function getWalletParam() { + global $order, $db; + $articleDetails = []; + foreach($order->products as $key => $products) { + if (!empty($order->info['coupon_code'])) { + $coupon_amount = $db->Execute("select coupon_amount from ".TABLE_COUPONS." where coupon_code = '".$order->info['coupon_code']."'"); + if ($coupon_amount->RecordCount()) + $discountTax = zen_calculate_tax($coupon_amount->fields['coupon_amount'], $products['tax']); + } + if (DISPLAY_PRICE_WITH_TAX == 'true') { + $articleDetails[] = array( // To add product details + 'label'=> str_replace("'", "#single_quote", $products['name']). ' x ' .$products['qty'], + 'amount' => (string)(($products['qty'] * (round($products['final_price'] + zen_calculate_tax($products['price'], $products['tax']), 2)))*100), + 'type' => 'SUBTOTAL', + ); + } else { + $articleDetails[] = array( // To add product details + 'label'=> str_replace("'", "#single_quote", $products['name']). ' x ' .$products['qty'], + 'amount' => (string)(($products['qty'] * $products['final_price'])*100), + 'type' => 'SUBTOTAL', + ); + } + if ($order->info['tax'] != 0) { + if(DISPLAY_PRICE_WITH_TAX == 'true') { // Price incl tax + $articleDetails[] = array( + 'label' => 'Incl.Tax', + 'amount' => (string) (round(($order->info['tax']), 2) * 100), + 'type' => 'SUBTOTAL' + ); + } else { // Price excl tax + $articleDetails[] = array( + 'label' => 'Excl.Tax', + 'amount' => (string) (round(($order->info['tax'] ), 2) * 100), + 'type' => 'SUBTOTAL' + ); + } + } + if ($_SESSION['cot_gv'] != 0.00 || !empty($order->info['coupon_code'])) { // To add discount coupon or gift certificate + if (DISPLAY_PRICE_WITH_TAX == 'true'){ // Discount Incl Tax + $deduction = $coupon_amount->fields['coupon_amount'] + $_SESSION['cot_gv']; + } else { // Discount Excl Tax + $deduction = $coupon_amount->fields['coupon_amount'] + $discountTax + $_SESSION['cot_gv']; + } + $articleDetails[] = array( + 'label'=> 'Discount', + 'amount' => (string) (round($deduction, 2) * 100), + 'type' => 'SUBTOTAL' + ); + } + } + $articleDetails[] = array( // To add shipping + 'label'=> 'Shipping', + 'amount' => (string)($order->info['shipping_cost']*100), + 'type' => 'SUBTOTAL' + ); + $wallet_hidden_field = ""; + return $wallet_hidden_field; + } + + /** + * Handle redirect payments success response + * @param $request + * + * @return $response + * */ + public static function handleRedirectSuccessResponse($request) { + $transaction_details = array('transaction' =>array('tid' => $request['tid'])); + $action = self::getActionEndpoint('transaction_details'); + $response = self::sendRequest($transaction_details, $action); + return $response; + } + + /** + * Get Novalnet transaction details from novalnet table + * + * @param array $order_no + * @return integer + */ + public static function getNovalnetTransDetails($order_no) { + global $db; + $txn_details = $db->Execute("SELECT * FROM novalnet_transaction_detail WHERE order_no='" . zen_db_input($order_no) . "'"); + return $txn_details; + } + + /** + * Send request to server + * + * @param array $data + * @param string request url + */ + public static function sendRequest($data, $paygate_url) { + $headers = self::getHeadersParam(); + $json_data = json_encode($data); + $curl = curl_init(); + curl_setopt($curl, CURLOPT_URL, $paygate_url); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_POST, true); + curl_setopt($curl, CURLOPT_POSTFIELDS, $json_data); + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + $result = curl_exec($curl); + if (curl_errno($curl)) { + echo 'Request Error:' . curl_error($curl); + return $result; + } + curl_close($curl); + $result = json_decode($result, true); + return $result; + } + + /** + * Get transaction details + * @param $response + * + * @return $note + */ + public static function getTransactionDetails($response) { + global $currencies; + $txn_details = ''; + if (! empty($response ['transaction']['tid'])) { + if ($response ['transaction']['payment_type'] == 'GOOGLEPAY') { + $txn_details .= PHP_EOL. sprintf(MODULE_PAYMENT_NOVALNET_WALLET_PAYMENT_SUCCESS_TEXT, $response['transaction']['payment_data']['last_four']); + } + $txn_details .= PHP_EOL. MODULE_PAYMENT_NOVALNET_TRANSACTION_ID .$response['transaction']['tid']; + $txn_details .= ($response ['transaction']['test_mode'] == 1) ? PHP_EOL. MODULE_PAYMENT_NOVALNET_PAYMENT_MODE : ''; + } + if ($response ['transaction']['amount'] == 0) { + $txn_details .= PHP_EOL. MODULE_PAYMENT_NOVALNET_ZEROAMOUNT_BOOKING_MESSAGE; + } + // Only for Guarantee and instalment payments + if (in_array($response['transaction']['payment_type'], array('GUARANTEED_INVOICE', 'GUARANTEED_DIRECT_DEBIT_SEPA', 'INSTALMENT_INVOICE', 'INSTALMENT_DIRECT_DEBIT_SEPA')) + && $response['transaction']['status'] == 'PENDING') { + $txn_details .= PHP_EOL . MODULE_PAYMENT_NOVALNET_MENTION_GUARANTEE_PAYMENT_PENDING_TEXT.PHP_EOL; + } + // Only for Multibanco + if ($response['transaction']['payment_type'] == 'MULTIBANCO') { + $amount = $currencies->format($response['transaction']['amount']/100, true, $response['transaction']['currency']); + $txn_details .= PHP_EOL . PHP_EOL . sprintf(MODULE_PAYMENT_NOVALNET_MULTIBANCO_NOTE, $amount); + $txn_details .= PHP_EOL . sprintf(MODULE_PAYMENT_NOVALNET_PARTNER_PAYMENT_REFERENCE, $response['transaction']['partner_payment_reference']) . PHP_EOL; + } + return $txn_details; + } + + /** + * Get Novalnet bank details and its reference + * @param $response + * + * @return $note + */ + public static function getBankDetails($response) { + global $currencies; + $note = ''; + $amount = $currencies->format($response['transaction']['amount']/100, true, $response['transaction']['currency']); + if (!empty($response['instalment']['cycle_amount'])) { + $amount = $currencies->format($response['instalment']['cycle_amount']/100, true, $response['transaction']['currency']); + } + $note = PHP_EOL .PHP_EOL.sprintf(MODULE_PAYMENT_NOVALNET_AMOUNT_TRANSFER_NOTE, $amount) . PHP_EOL .PHP_EOL; + if($response['transaction']['status'] != 'ON_HOLD' && !empty($response['transaction']['due_date'])) { // If due date is not empty + if(!empty($response['instalment']['cycle_amount'])) { // For Instalment payment + $note = PHP_EOL . PHP_EOL.sprintf(MODULE_PAYMENT_NOVALNET_INSTALMENT_AMOUNT_TRANSFER_NOTE_DUE_DATE, $amount, $response ['transaction']['due_date'] ) . PHP_EOL . PHP_EOL; + } else { + $note = PHP_EOL .PHP_EOL.sprintf(MODULE_PAYMENT_NOVALNET_AMOUNT_TRANSFER_NOTE_DUE_DATE, $amount, $response['transaction']['due_date']) . PHP_EOL .PHP_EOL; + } + + } else if(!empty( $response['instalment']['cycle_amount'] )) { // For Instalment payment + $note = PHP_EOL . sprintf(MODULE_PAYMENT_NOVALNET_INSTALMENT_AMOUNT_TRANSFER_NOTE, $amount) . PHP_EOL . PHP_EOL; + } + $bank_details = array( + 'account_holder' => PHP_EOL.MODULE_PAYMENT_NOVALNET_ACCOUNT_HOLDER .$response['transaction']['bank_details']['account_holder'], + 'bank_name' => MODULE_PAYMENT_NOVALNET_BANK_NAME .$response['transaction']['bank_details']['bank_name'], + 'bank_place' => MODULE_PAYMENT_NOVALNET_BANK_PLACE .$response['transaction']['bank_details']['bank_place'] , + 'iban' => MODULE_PAYMENT_NOVALNET_IBAN .$response['transaction']['bank_details']['iban'] , + 'bic' => MODULE_PAYMENT_NOVALNET_BIC .$response['transaction']['bank_details']['bic'] , + ); + foreach ($bank_details as $key => $text) { + if (! empty($response ['transaction']['bank_details'][ $key ])) { + $note .= sprintf($text, $response['transaction']['bank_details'][ $key ]) . PHP_EOL; + } + } + $note .= PHP_EOL. MODULE_PAYMENT_NOVALNET_PAYMENT_REFERENCE_TEXT .PHP_EOL; + $note .= sprintf(MODULE_PAYMENT_NOVALNET_PAYMENT_REFERENCE, ('TID ' . $response['transaction']['tid'])) . PHP_EOL; + return $note; + } + + /** + * Get nearest Cashpayment supported stores + * @param $response + * + * @return $txn_details + */ + public static function getNearestStoreDetails($response) { + global $db; + $txn_details = ''; + $length = count($response['transaction']['nearest_stores']); + if (! empty($response['transaction']['due_date'])) { + $txn_details .= PHP_EOL . PHP_EOL.MODULE_PAYMENT_NOVALNET_TRANS_SLIP_EXPIRY_DATE .date(DATE_FORMAT,strtotime($response['transaction']['due_date'])); + } + $txn_details .= PHP_EOL . PHP_EOL .MODULE_PAYMENT_NOVALNET_NEAREST_STORE_DETAILS . PHP_EOL ; + if (!empty($response['transaction']['nearest_stores'])) { + for($i=1; $i <= $length; $i++) { + $txn_details .= PHP_EOL . $response['transaction']['nearest_stores'][$i]['store_name']; + $txn_details .= PHP_EOL . $response['transaction']['nearest_stores'][$i]['street']; + $txn_details .= PHP_EOL . $response['transaction']['nearest_stores'][$i]['zip'] . ' ' . $response['transaction']['nearest_stores'][$i]['city']; + $country_name = $db->Execute("select countries_name from " . TABLE_COUNTRIES . " where countries_iso_code_2 = '" . $response['transaction']['nearest_stores'][$i]['country_code'] . "'"); + if ($country_name->RecordCount()) + $txn_details .= PHP_EOL . $country_name->fields['countries_name']; + $txn_details .= PHP_EOL . PHP_EOL; + } + } + return $txn_details; + } + + /** + * Add instalment details in end customer comments + * + * @param $response + * + * @return $txn_details + */ + public static function getInstalmentDetails($response) { + global $currencies; + $txn_details = ''; + $amount = $currencies->format($response['instalment']['cycle_amount']/100, true, $response['instalment']['currency']); + if ($response['transaction']['status'] == 'CONFIRMED') { + $txn_details .= PHP_EOL.PHP_EOL.MODULE_PAYMENT_NOVALNET_INSTALMENT_INSTALMENTS_INFO.PHP_EOL.MODULE_PAYMENT_NOVALNET_INSTALMENT_PROCESSED_INSTALMENTS.$response['instalment']['cycles_executed'] . PHP_EOL; + $txn_details .= MODULE_PAYMENT_NOVALNET_INSTALMENT_DUE_INSTALMENTS.$response['instalment']['pending_cycles']. PHP_EOL; + $txn_details .= MODULE_PAYMENT_NOVALNET_INSTALMENT_NEXT_INSTALMENT_AMOUNT.$amount. PHP_EOL; + if(!empty($response['instalment']['next_cycle_date'])) { + $txn_details .= MODULE_PAYMENT_NOVALNET_INSTALMENT_NEXT_INSTALMENT_DATE. date('Y-m-d', strtotime($response['instalment']['next_cycle_date'])). PHP_EOL; + } + } + return $txn_details; + } + + /** + * Get shop order status id + * + * @param $transaction_status + * @param $payment_method + * + * @return $order_status_id + */ + public static function getOrderStatus($transaction_status, $payment_name) { + if ($transaction_status == 'PENDING' && $payment_name == 'INVOICE') { + $order_status_id = 2; + } elseif ($transaction_status == 'PENDING') { + $order_status_id = 1; + } elseif ($transaction_status == 'CONFIRMED') { + $order_status_id = 2; + } elseif ($transaction_status == 'ON_HOLD') { + $order_status_id = 99; + } + return $order_status_id; + } + + /** + * Update order status and insert the transaction details in the database + * @param $order_id + * @param $txn_details + * @param $response + * + * @return mixed + */ + public static function updateOrderStatus($order_id, $txn_details, $response) { + global $order; + $payment_status = []; + $status_update = []; + $payment_status['orders_status'] = $status_update['orders_status_id'] = self::getOrderStatus($response['transaction']['status'], $response['transaction']['payment_type']); + $status_update['comments'] = $order->info['comments'] = zen_db_prepare_input($txn_details); + $novalnet_transaction_details = array( + 'order_no' => $order_id, + 'tid' => $response['transaction']['tid'], + 'amount' => $response['transaction']['amount'], + 'currency' => $response['transaction']['currency'], + 'payment_type' => $response['transaction']['payment_type'], + 'status' => $response['transaction']['status'], + ); + if (in_array($response['transaction']['payment_type'], array('INSTALMENT_INVOICE', 'INSTALMENT_DIRECT_DEBIT_SEPA')) + && ($response['transaction']['status'] == 'CONFIRMED')) { + $order_total = self::getOrderAmount($order->info['total']); + $total_amount = ($response['transaction']['amount'] < $order_total) ? $order_total : $response['transaction']['amount']; + $novalnet_transaction_details['instalment_cycle_details'] = self::storeInstalmentdetails($response, $total_amount); + } + if (in_array($response['transaction']['payment_type'], array('INVOICE', 'PREPAYMENT', 'GUARANTEED_INVOICE', 'INSTALMENT_INVOICE'))) { + $payment_details = $response['transaction']['bank_details']; + $payment_details['novalnet_due_date'] = $response['transaction']['due_date']; + $novalnet_transaction_details['payment_details'] = json_encode($payment_details); + } elseif ($response['transaction']['payment_type'] === 'CASHPAYMENT') { + $payment_details = $response['transaction']['nearest_stores']; + $payment_details['novalnet_due_date'] = $response['transaction']['due_date']; + $novalnet_transaction_details['payment_details'] = json_encode($payment_details); + } elseif (!empty($response['transaction']['payment_data']['token']) && $_SESSION['nn_booking_details']->create_token == '1') { + $payment_data = $response['transaction']['payment_data']; + if ($_SESSION['nn_booking_details']->payment_action == 'zero_amount') { + $payment_data['zero_amount_booking'] = 1; + } + $novalnet_transaction_details['payment_details'] = json_encode($payment_data); + } elseif (!empty($response['transaction']['payment_data']['token']) && $_SESSION['nn_booking_details']->payment_action == 'zero_amount' && $_SESSION['nn_booking_details']->create_token == '0') { + $cardDetails = array( + 'token' => $response['transaction']['payment_data']['token'], + 'zero_amount_booking' => 1 + ); + $novalnet_transaction_details['payment_details'] = json_encode($cardDetails); + } + zen_db_perform('novalnet_transaction_detail', $novalnet_transaction_details, 'insert'); + zen_db_perform(TABLE_ORDERS, $payment_status, "update", "orders_id='$order_id'"); + zen_db_perform(TABLE_ORDERS_STATUS_HISTORY, $status_update, "update", "orders_id='$order_id'"); + } + + /** + * Get instalment details to store in Novalnet Transaction details + * + * @param $response + * @param $total_amount + * + * @return string + */ + public static function storeInstalmentdetails($response, $total_amount) { + if(empty($response['instalment'])) { + return false; + } + $instalment = $response['instalment']; + $total_cycles = count($instalment['cycle_dates']); + $cycle_amount = $instalment['cycle_amount']; + $last_cycle_amount = $total_amount - ($cycle_amount * ($total_cycles - 1)) ; + $cycles = $instalment['cycle_dates']; + $cycle_details = array(); + foreach($cycles as $cycle => $cycle_date) { + $cycle_details[$cycle -1 ]['date'] = $cycle_date; + if(!empty($cycles[$cycle + 1])) { + $cycle_details[$cycle -1 ]['next_instalment_date'] = $cycles[$cycle + 1]; + } + $cycle_details[$cycle -1 ]['status'] = 'Pending'; + if (!empty($instalment['cycles_executed']) && $cycle == $instalment['cycles_executed']) { + if (isset($instalment['tid']) && !empty($instalment['tid'])) { + $cycle_details[$cycle -1 ]['reference_tid'] = (!empty($instalment['tid']))?$instalment['tid'] : ''; + } else if(isset($response['transaction']['tid']) && !empty($response['transaction']['tid'])) { + $cycle_details[$cycle -1 ]['reference_tid'] = (!empty($response['transaction']['tid']))?$response['transaction']['tid'] : ''; + } + $cycle_details[$cycle -1 ]['status'] = 'Paid'; + $cycle_details[$cycle -1 ]['paid_date'] = date('Y-m-d H:i:s'); + } + $cycle_details[$cycle -1 ]['instalment_cycle_amount'] = ($cycle == $total_cycles)?$last_cycle_amount : $instalment['cycle_amount']; + } + return json_encode($cycle_details); + } + + + /** + * Send transaction update call to update order_no in Novalnet + * @param $order_no + * + * @return none + */ + public static function sendTransactionUpdate($order_no) { + $transaction_param = [ + 'transaction' => [ + 'tid' => $_SESSION['response']['transaction']['tid'], + 'order_no' => $order_no, + ], + ]; + $params = array_merge($transaction_param, self::getCustomData()); + self::sendRequest($params, self::getActionEndpoint('transaction_update')); + if (isset($_SESSION['response'])) { + unset($_SESSION['response']); + } + } + + /** + * Hadnle temporary created order for the failure transaction + * + * @param array $response + * @param string $error_text + * + * @return none + */ + public static function processTempOrderFail( $response, $error_text = '') { + global $messageStack; + $status_text = self::getServerResponse($response); + $status_text = (!empty($status_text)) ? $status_text : $error_text; + $messageStack->add_session('checkout_payment', $status_text . '', 'error'); + zen_redirect(zen_href_link(FILENAME_CHECKOUT_PAYMENT, '', 'SSL', true, false)); + } + + /** + * Validate checksum + * + * @param $data + * + * @return boolean + */ + public static function validateCheckSum($data) { + if (!empty($data['checksum']) && !empty($data['tid']) && !empty($data['status']) && !empty($_SESSION['nn_txn_secret']) && !empty(MODULE_PAYMENT_NOVALNET_PAYMENT_ACCESS_KEY)) { + $checksum = hash('sha256', $data['tid'] . $_SESSION['nn_txn_secret'] . $data['status'] . strrev(MODULE_PAYMENT_NOVALNET_PAYMENT_ACCESS_KEY)); + if ($checksum == $data['checksum']) { + return true; + } + } + return false; + } + + /** + * Get payment response text + * + * @param array $response + * @param string + */ + public static function getServerResponse($response) { + if (!empty($response['status_desc'])) { + return $response['status_desc']; + } elseif (!empty($response['status_text'])) { + return $response['status_text']; + } elseif (!empty($response['status_message'])) { + return $response['status_message']; + } elseif (!empty($response['result']['status_text'])) { + return $response['result']['status_text']; + } else { + return MODULE_PAYMENT_NOVALNET_TRANSACTION_ERROR; + } + } + + /** + * Get payment request url + * + * @param string $action + * @return string + */ + public static function getActionEndpoint($action) { + $endpoint = 'https://payport.novalnet.de/v2/'; + return $endpoint . str_replace('_', '/', $action); + } + + /** + * Get merchant data + * + * @return $data + */ + public static function getMerchantData() { + $data = []; + $data['merchant'] = [ + 'signature' => defined('MODULE_PAYMENT_NOVALNET_PUBLIC_KEY') ? MODULE_PAYMENT_NOVALNET_PUBLIC_KEY : '', + 'tariff' => defined('MODULE_PAYMENT_NOVALNET_TARIFF_ID') ? MODULE_PAYMENT_NOVALNET_TARIFF_ID : '', + ]; + return $data; + } + + /** + * Get request header + */ + public static function getHeadersParam() { + $headers = [ + 'Content-Type:application/json', + 'Charset:utf-8', + 'Accept:application/json', + 'X-NN-Access-Key:' . base64_encode(MODULE_PAYMENT_NOVALNET_PAYMENT_ACCESS_KEY) + ]; + return $headers; + } + + /** + * Get tokenization details + * @param $payment_name + * + * @return $data + */ + public static function getToeknizationDetails(&$transaction_data) { + if(!empty($_SESSION['nn_booking_details']->payment_ref_token) && (empty($_SESSION['nn_booking_details']->pan_hash) || empty($_SESSION['nn_booking_details']->unique_id))) { // Reference transaction + $transaction_data['transaction']['payment_data']['token'] = $_SESSION['nn_booking_details']->payment_ref_token; + unset($_SESSION['nn_booking_details']->payment_ref_token); + } elseif(($_SESSION['nn_booking_details']->create_token == '1') && (!empty($_SESSION['nn_booking_details']->pan_hash) || !empty($_SESSION['nn_booking_details']->unique_id))) { // New transaction + $transaction_data['transaction']['create_token'] = 1; + unset($_SESSION['nn_booking_details']->create_token); + } + } + + /** + * Check for the success status of the Novalnet payment call. + * + * @param $data. + * + * @return boolean + */ + public static function is_success_status( $data ) { + return ((!empty($data['result']['status']) && $data['result']['status'] === 'SUCCESS') || (!empty($data['status']) && $data['status'] === 'SUCCESS')); + } + + /** + * Insert transaction, bank and nearest store details in the database + * @param $order_no + * @param $payment_method + * @param $response + * @param $status_update + * + * @return mixed + */ + public static function insertTransactionDetails($response, $status_update = false, $order_no = '') { + if ($response['result']['status'] == 'SUCCESS') { + $txn_details = self::getTransactionDetails($response); + // Invoice payments + if((in_array($response['transaction']['payment_type'], array('INVOICE', 'PREPAYMENT'))) + || (in_array($response['transaction']['payment_type'], array('GUARANTEED_INVOICE', 'INSTALMENT_INVOICE')) + && $response['transaction']['status'] != 'PENDING')) { + $txn_details .= self::getBankDetails($response); + } + // Cashpayment + if ($response['transaction']['payment_type'] == 'CASHPAYMENT') { + $txn_details .= self::getNearestStoreDetails($response); + } + if (in_array($response['transaction']['payment_type'], array('INSTALMENT_INVOICE', 'INSTALMENT_DIRECT_DEBIT_SEPA')) && ($response['transaction']['status'] == 'CONFIRMED')) { + $txn_details .= self::getInstalmentDetails($response); + } + if ($status_update) { + self::updateOrderStatus($order_no, $txn_details, $response , $response['transaction']['payment_type']); + } else { + return $txn_details; + } + } + } + + /** + * Validate customer email + * + * @param $emails + * + * @return boolean + */ + public static function validateEmail($emails) { + $email = explode(',', $emails); + foreach ($email as $value) { + // Validate E-mail. + if (!zen_validate_email($value)) { + return false; + } + } + return $value; + } + + /** + * Paypal sheet details + * + * @return $params + */ + public static function paypal_sheet_details(&$params) { + global $order, $db; + foreach ($order->products as $products){ + if (isset($products['attributes'])) { + foreach ($products['attributes'] as $attr => $value) { + $attributes[] = ', ' . $value['option'] . ':' . $value['value']; + } + } + if ($products['products_weight'] != 0) { + $product_type = 'physical'; + } else { + $product_type = 'digital'; + } + $productId = str_split($products['id']); + $product_desc = $db->Execute("select products_description from " . TABLE_PRODUCTS_DESCRIPTION . " where language_id = '" . $_SESSION['languages_id'] . "' and products_id = '" . $productId[0] . "'"); + $params['cart_info']['line_items'][] = array( + 'name' => $products['name']. ' x ' .$products['qty'] . $attributes, + 'price' => (string) (round((float) $products['price'] * 100)), + 'quantity' => $products['qty'], + 'description' => !empty($product_desc->products_description) ? $product_desc->products_description : '', + 'category' => $product_type, + ); + + } + + if (!empty($order->info['coupon_code'])) { + $discount_amount = (string) (round((float) $order->info['coupon_amount'] * 100)); + $params['cart_info']['line_items'][] = array( + 'name' => 'Discount', + 'price' => $discount_amount, + 'quantity' => 1, + 'description' => '', + 'category' => '', + ); + } + $params['cart_info']['items_tax_price'] = (string) (round((float) $order->info['tax'] * 100)); + $params['cart_info']['items_shipping_price'] = (string) (round((float) $order->info['shipping_cost'] * 100)); + } +} +?> diff --git a/includes/modules/payment/novalnet/novalnet_auto_config.js b/includes/modules/payment/novalnet/novalnet_auto_config.js new file mode 100755 index 0000000..69adf3d --- /dev/null +++ b/includes/modules/payment/novalnet/novalnet_auto_config.js @@ -0,0 +1,129 @@ +/** + * Novalnet payment module + * This script is used for auto configuring the merchant details + * + * @author Novalnet AG + * @copyright Copyright (c) Novalnet + * @license https://www.novalnet.de/payment-plugins/kostenlos/lizenz + * @link https://www.novalnet.de + * + * Script : novalnet_auto_config.js + * + */ + +/** + * To get the backend field configuration values + */ +$( document ).ready(function() { + jQuery('input[name="configuration[MODULE_PAYMENT_NOVALNET_PUBLIC_KEY]"]').attr('id', 'novalnet_signature').attr('autocomplete', 'off'); + jQuery('input[name="configuration[MODULE_PAYMENT_NOVALNET_TARIFF_ID]"]').attr('id', 'novalnet_tariff_id'); + jQuery('input[name="configuration[MODULE_PAYMENT_NOVALNET_PAYMENT_ACCESS_KEY]"]').attr('id', 'novalnet_access_key').attr('autocomplete', 'off'); + jQuery('input[name="configuration[MODULE_PAYMENT_NOVALNET_CALLBACK_URL]"]').attr('id','novalnet_webhook_url'); + jQuery('#novalnet_signature, #novalnet_access_key').change(function () { + if (jQuery('#novalnet_signature').val() != '' && jQuery('#novalnet_access_key').val() != '') { + get_merchant_details(); + return true; + } else if (jQuery('#novalnet_signature').val() == '' && jQuery('#novalnet_access_key').val() == '') { + clear_basic_params(); + } + }).change(); + + jQuery('#novalnet_signature').closest('form').submit(function (event){ + if (jQuery('#novalnet_signature').val() == '') { + event.preventDefault(); + alert(jQuery('#merchant_credentials_error').val()); + } + }); + + jQuery('#webhook_url_button').on('click', function() { + var webhook_url = jQuery.trim(jQuery('#novalnet_webhook_url').val()); + var regex = /(http|https):\/\/(\w+:{0,1}\w*)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%!\-\/]))?/; + if (webhook_url != '' && regex.test(webhook_url)) { + confirm(jQuery('#nn_webhook_alert').val()); + configure_webhook(); + return true; + } else if (!regex.test( webhook_url) || webhook_url === '' || webhook_url === undefined){ + alert(jQuery('#nn_webhook_error').val()); + return false; + } + }); +}); + +/** Get merchant data */ +function get_merchant_details() { + var signature = jQuery.trim(jQuery('#novalnet_signature').val()); + var access_key = jQuery.trim(jQuery('#novalnet_access_key').val()); + var data_to_send = {'action': 'merchant', 'signature': signature, 'access_key': access_key, 'lang': jQuery('#nn_language').val()}; + do_ajax_call(data_to_send, 'merchant'); + return true; +} + +/** Configure webhook URL in Novalnet system */ +function configure_webhook() { + var signature = jQuery.trim(jQuery('#novalnet_signature').val()); + var access_key = jQuery.trim(jQuery('#novalnet_access_key').val()); + var webhook_url = jQuery.trim(jQuery('#novalnet_webhook_url').val()); + if (signature == '' || access_key == '') { + alert(jQuery('#nn_key_error').val()); + clear_basic_params(); + return false; + } + var data_to_send = {'action': 'webhook', 'signature': signature, 'access_key': access_key, 'webhook_url': webhook_url, 'lang': jQuery('#nn_language').val()}; + do_ajax_call(data_to_send, 'webhook'); + return true; +} + +/** Handle the response */ +function process_result(result) { + var saved_tariff_id = jQuery('#novalnet_tariff_id').val(); + jQuery('#novalnet_tariff_id').replaceWith(''); + var tariff = result.merchant.tariff; + if (tariff != undefined) { + jQuery.each(tariff, function( index, value ) { + var tariff_val = index; + jQuery('#novalnet_tariff_id').append(jQuery('