diff --git a/README.md b/README.md new file mode 100644 index 0000000..331fb65 --- /dev/null +++ b/README.md @@ -0,0 +1,84 @@ +# 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.7f - 1.5.7h 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 commonly used 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 +- Direct Debit ACH +- 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 +- MB Way +- PostFinance Card +- PostFinance E-Finance +- Bancontact +- Multibanco +- Online bank transfer +- Alipay +- WeChat Pay +- Trustly +- Blik +- Payconiq + +## Quick Installation via plugin downloads +Follow these steps to install the Zencart payment module by Novalnet: +1. **Download** the payment module from here or contact us. +2. Upload and install the payment module in the shop admin panel. +3. Configure the Novalnet Merchant API details in the shop admin panel. +4. Activate & configure the preferred payment methods from Novalnet Admin Portal. + +## License +See our License Agreement at: https://www.novalnet.com/payment-plugins-free-license/ + +## Documentation & Support +For more information about the Zencart Payment Integration by Novalnet, please get in touch with us: sales@novalnet.de or +49 89 9230683-20
+ +Novalnet AG
+Zahlungsinstitut (ZAG)
+Gutenbergstraße 7
+D-85748 Garching
+Deutschland
+E-mail: sales@novalnet.de
+Tel: +49 89 9230683-20
+Web: 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/includes/extra_datafiles/novalnet.php b/admin/includes/extra_datafiles/novalnet.php new file mode 100644 index 0000000..781d380 --- /dev/null +++ b/admin/includes/extra_datafiles/novalnet.php @@ -0,0 +1,16 @@ + 0) { + // Let the user know that there are problem(s) with the installation + foreach ($error_messages as $error_message) { + print '

' . + 'Error: ' . $error_message . "

\n"; + } + } else { + zen_register_admin_page('customersNovalnetTransactions', 'BOX_CUSTOMERS_NOVALNET_TRANSACTIONS', 'FILENAME_NOVALNET_TRANSACTIONS','' , 'customers', 'Y', 400); + } +} +} + +if ($can_autodelete) { + // Either the config utility file has been registered, or it doesn't need to be. Can stop the wasteful process + // of having this script run again by having it delete itself + @unlink(DIR_WS_INCLUDES . 'functions/extra_functions/reg_novalnet_transactions.php'); +} diff --git a/admin/includes/languages/english/extra_definitions/novalnet.php b/admin/includes/languages/english/extra_definitions/novalnet.php new file mode 100644 index 0000000..6fee843 --- /dev/null +++ b/admin/includes/languages/english/extra_definitions/novalnet.php @@ -0,0 +1,12 @@ +RecordCount()) { + $payment_details = '{}'; + $payment_details = !empty($txn_details->fields['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'])); + $data = []; + $update_data = []; + $response = []; + $message = ''; + $order_status_value = $current_order_status->fields['orders_status']; + $data = [ + 'custom' => [ + 'lang' => (isset($_SESSION['languages_code'])) ? strtoupper($_SESSION['languages_code']) : 'DE', + 'shop_invoked' => 1 + ] + ]; + if (!empty($request['nn_book_confirm']) && !empty($request['book_amount'])) { // Zero amount booking transaction process + + NovalnetHelper::buildRequestParams($data); + $data['custom']['shop_invoked'] = 1; + $data['transaction']['payment_type'] = $txn_details->fields['payment_type']; + $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') { + $message = 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'], + ]; + } + } elseif (!empty($request['nn_instacancel_allcycles']) || !empty($request['nn_instacancel_remaincycles'])) { // Instalment cancel process + $data['instalment'] = [ + 'tid' => $txn_details->fields['tid'], + 'cancel_type' => isset($request['nn_instacancel_allcycles']) ? 'CANCEL_ALL_CYCLES' : 'CANCEL_REMAINING_CYCLES' + ]; + $response = NovalnetHelper::sendRequest($data, NovalnetHelper::getActionEndpoint('instalment_cancel')); + if ($response['result']['status'] == 'SUCCESS') { + $instalment_details = !empty($txn_details->fields['instalment_cycle_details']) ? json_decode($txn_details->fields['instalment_cycle_details'], true) : []; + foreach ($instalment_details as $cycle => $cycle_details) { + $update_data['status'] = 'CONFIRMED'; + $message = PHP_EOL. sprintf((MODULE_PAYMENT_NOVALNET_INSTALMENT_CANCEL_REMAINING_CYCLES_TEXT), $txn_details->fields['tid'], date('d.m.Y H:i:s')); + if ($cycle_details['status'] == 'Pending') { // Cancel the instalment cycles if its pending + $instalment_details[$cycle]['status'] = 'Canceled'; + } + if (!empty($request['nn_instacancel_allcycles'])) { // If instalment all cycle cancel + $update_data['status'] = 'DEACTIVATED'; + $message = PHP_EOL. sprintf((MODULE_PAYMENT_NOVALNET_INSTALMENT_CANCEL_ALLCYCLES_TEXT), $txn_details->fields['tid'], date('d.m.Y H:i:s'), $currencies->format(($response['transaction']['refund']['amount']/100), 1, $order->info['currency'])); + if ($cycle_details['status'] == 'Paid') { // Refund the instalment cycles if its paid + $instalment_details[$cycle]['status'] = 'Refunded'; + } + } + } + $update_data = [ + 'instalment_cycle_details' => !empty($instalment_details) ? json_encode($instalment_details) : '{}', + ]; + $order_status_value = !empty($request['nn_instacancel_allcycles']) ? NovalnetHelper::getOrderStatusId() : $current_order_status->fields['orders_status']; + } + } elseif ((!empty($request['nn_refund_confirm']) && ($request['refund_trans_amount'] != '' ) && $txn_details->fields['status'] != 'Canceled')) { // To process instalment payments refund process + $refunded_amount = 0; + $data['transaction'] = [ + 'tid' => (!empty($request['refund_tid'])) ? $request['refund_tid'] : $txn_details->fields['tid'], + 'amount' => $request['refund_trans_amount'], + ]; + 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 (!empty($txn_details->fields['instalment_cycle_details'])) { + $instalment_details = json_decode($txn_details->fields['instalment_cycle_details'], true); + 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 =sprintf((MODULE_PAYMENT_NOVALNET_REFUND_PARENT_TID_MSG), $txn_details->fields['tid'], $currencies->format(($refunded_amount/100), 1, $order->info['currency'])); + // Check for refund TID + if (!empty($response['transaction']['refund']['tid'])) { + $message .= sprintf((MODULE_PAYMENT_NOVALNET_REFUND_CHILD_TID_MSG), $response['transaction']['refund']['tid']); + } + $order_status_value = ($update_data['refund_amount'] >= $txn_details->fields['amount']) ? NovalnetHelper::getOrderStatusId() : $current_order_status->fields['orders_status']; + } + } + if (isset($response['result']['status']) && $response['result']['status'] == 'SUCCESS') { + zen_db_perform(TABLE_NOVALNET_TRANSACTION_DETAIL, $update_data, 'update', 'order_no='.$request['oID']); + $messageStack->add_session($response['result']['status_text'], 'success'); + }elseif (isset($response['result']['status_text'])){ + $messageStack->add_session($response['result']['status_text'], 'error'); + } + else{ + $messageStack->add_session('No valid amount given (FULL or digits only, in smallest amount of currency)', 'error'); + } + NovalnetHelper::novalnetUpdateOrderStatus($request['oID'], $message, $order_status_value); + zen_redirect(zen_href_link(FILENAME_ORDERS, zen_get_all_get_params(['action']) . 'action=edit' . '&oID=' . (int)$request['oID'])); +} diff --git a/admin/novalnet_transactions.php b/admin/novalnet_transactions.php new file mode 100644 index 0000000..24e00cf --- /dev/null +++ b/admin/novalnet_transactions.php @@ -0,0 +1,310 @@ + 'id_desc', 'text' => TEXT_SORT_NOVALNET_ID_DESC], + ['id' => 'id_asc', 'text' => TEXT_SORT_NOVALNET_ID], + ['id' => 'shop_order_desc', 'text' => TEXT_SORT_ZEN_ORDER_ID_DESC], + ['id' => 'shop_order_asc', 'text' => TEXT_SORT_ZEN_ORDER_ID], + ['id' => 'nn_payment_desc', 'text' => TEXT_SORT_NOVALNET_PAYMENT_TYPE_DESC], + ['id' => 'nn_payment_asc', 'text' => TEXT_SORT_NOVALNET_PAYMENT_TYPE], + ['id' => 'status_desc', 'text' => TEXT_SORT_NOVALNET_STATUS_DESC], + ['id' => 'status_asc', 'text' => TEXT_SORT_NOVALNET_STATUS] + ]; + + $novalnet_sort_order = 0; + + if (isset($_GET['novalnet_sort_order'])) { + $novalnet_sort_order = $_GET['novalnet_sort_order']; + } + switch ($novalnet_sort_order) { + case ('id_desc'): + $order_by = " order by n.id DESC"; + break; + case ('id_asc'): + $order_by = " order by n.order_no"; + break; + case ('shop_order_desc'): + $order_by = " order by n.order_no DESC, n.id"; + break; + case ('shop_order_asc'): + $order_by = " order by n.order_no, n.id"; + break; + case ('nn_payment_desc'): + $order_by = " order by n.payment_type DESC"; + break; + case ('nn_payment_asc'): + $order_by = " order by n.payment_type"; + break; + case ('status_desc'): + $order_by = " order by n.status"; + break; + case ('status_asc'): + $order_by = " order by n.status DESC"; + break; + + default: + $order_by = " order by n.id DESC"; + break; + } + + $action = (isset($_GET['action']) ? $_GET['action'] : ''); + $selected_status = (isset($_GET['novalnet_status']) ? $_GET['novalnet_status'] : ''); + $novalnet_statuses = []; + $novalnet_statuses[0] = array('id' => 'ON_HOLD', 'text' => 'ON_HOLD'); + $novalnet_statuses[1] = array('id' => 'CONFIRMED', 'text' => 'CONFIRMED'); + $novalnet_statuses[2] = array('id' => 'PENDING', 'text' => 'PENDING'); + $novalnet_statuses[3]= array('id' => 'DEACTIVATED', 'text' => 'DEACTIVATED'); +?> + +> + + + + + + + + + + + +
+

+ + +
'', 'text' => TEXT_ALL_IPNS]], $novalnet_statuses), $selected_status, 'onchange="this.form.submit();"') . zen_hide_session_id() . $hidden_field . ''; + $hidden_field = (isset($_GET['novalnet_status'])) ? zen_draw_hidden_field('novalnet_status', $_GET['novalnet_status']) : ''; + echo '   ' . TEXT_NOVALNET_SORT_ORDER_INFO . zen_draw_form('novalnet_sort_order', FILENAME_NOVALNET_TRANSACTIONS, '', 'get') . '  ' . zen_draw_pull_down_menu('novalnet_sort_order', $novalnet_sort_order_array, $novalnet_sort_order, 'onChange="this.form.submit();"') . zen_hide_session_id() . $hidden_field . ''; +?>
+ | Novalnet Admin Portal + +
+
+ + + + + + + + + + + + + + +bindVars($novalnet_search, ':selectedStatus:', $selected_status, 'string'); + switch ($selected_status) { + case 'ON_HOLD' : + case 'CONFIRMED' : + case 'PENDING' : + case 'DEACTIVATED': $novalnet_query_raw = "SELECT * FROM " . TABLE_NOVALNET_TRANSACTION_DETAIL . " AS n LEFT JOIN " . TABLE_ORDERS . " AS o ON o.orders_id = n.order_no WHERE n.status = '" . $selected_status . "'" . $order_by; + break; + } + } else { + $novalnet_query_raw = "SELECT * from `".TABLE_NOVALNET_TRANSACTION_DETAIL."` as n left join " .TABLE_ORDERS . " as o on o.orders_id = n.order_no " . $order_by; +} + + require(DIR_WS_CLASSES . 'currencies.php'); + $currencies = new currencies(); + $novalnet_split = new splitPageResults($_GET['page'], MAX_DISPLAY_SEARCH_RESULTS_NOVALNET_IPN, $novalnet_query_raw, $novalnet_query_numrows); + $novalnet_response = $db->Execute($novalnet_query_raw); + foreach ($novalnet_response as $novalnet_tran) { + if ((!isset($_GET['novalnetId']) || (isset($_GET['novalnetId']) && ($_GET['novalnetId'] == $novalnet_response->fields['id']))) && !isset($novalnetInfo) ) { + $novalnetInfo = new objectInfo($novalnet_tran); + } + + echo '' . "\n"; + +?> + + + + + + + + + '; + } +?> + + + + +
ID
' . zen_image(DIR_WS_ICONS . 'preview.gif', ICON_PREVIEW . ' ' . TABLE_HEADING_CUSTOMERS) . ' ' . $novalnet_tran['customers_name'] . ($novalnet_tran['customers_company'] !== '' ? '
' . $novalnet_tran['customers_company'] : ''); ?>
format(($novalnet_tran['amount'] / 100), 1, $novalnet_tran['currency']); ?> + format(($novalnet_tran['refund_amount'] / 100), 1, $novalnet_tran['currency']); ?> + format(($novalnet_tran['callback_amount'] / 100), 1, $novalnet_tran['currency']); ?> + + ' . zen_image(DIR_WS_IMAGES . 'icon_edit.gif', ICON_EDIT) . ''; + ?> +   +
display_count($novalnet_query_numrows, MAX_DISPLAY_SEARCH_RESULTS_NOVALNET_IPN, $_GET['page'], "Zeige %d bis %d (von %d Transaktionen)"); ?>display_links($novalnet_query_numrows, MAX_DISPLAY_SEARCH_RESULTS_NOVALNET_IPN, MAX_DISPLAY_PAGE_LINKS, isset($_GET['page']) ? (int)$_GET['page'] : 1, zen_get_all_get_params(['page'])); ?>
+
+Execute("SELECT * FROM " . TABLE_NOVALNET_TRANSACTION_DETAIL . " WHERE id = '" . $novalnetInfo->id . "'"); + $novalnet_count = $novalnet->RecordCount(); + + + switch ($novalnet->fields['status']){ + case 'ON_HOLD': + + require_once(DIR_WS_CLASSES . 'order.php'); + + $order = new order($novalnetInfo->order_no); + $heading[] = array('text' => '' . TEXT_INFO_NOVALNET_RESPONSE_BEGIN.'#'.$novalnetInfo->id.' '.TEXT_INFO_NOVALNET_RESPONSE_END.'#'. $novalnetInfo->order_no . ''); + $contents[] = array('text' => '' . TABLE_HEADING_ORDER_NUMBER .'' . ': '.$novalnetInfo->order_no); + $contents[] = array('text' => '' . NOVALNET_REFERENCE_ID .'' . ': '.$novalnetInfo->tid); + $contents[] = array('text' => '' . TABLE_HEADING_AMOUNT .'' . ': '.$currencies->format(($novalnetInfo->amount / 100), 1, $novalnetInfo->currency)); + $contents[] = array('text' => '' . NOVALNET_PAYMENT_TYPE .'' . ': '.$novalnetInfo->payment_method); + if (!empty($novalnetInfo->refund_amount)) + $contents[] = array('text' => '' . NOVALNET_REFUND_AMOUNT .'' . ': '.$currencies->format(($novalnetInfo->refund_amount / 100), 1, $novalnetInfo->currency)); + if (!empty($novalnetInfo->callback_amount)) + $contents[] = array('text' => '' . NOVALNET_CALLBACK_AMOUNT .'' . ': '.$currencies->format(($novalnetInfo->callback_amount / 100), 1, $novalnetInfo->currency)); + + $count = 1; + + $contents[] = array('text' => ''); + break; + case 'CONFIRMED': + + require_once(DIR_WS_CLASSES . 'order.php'); + + $order = new order($novalnetInfo->order_no); + $heading[] = array('text' => '' . TEXT_INFO_NOVALNET_RESPONSE_BEGIN.'#'.$novalnetInfo->id.' '.TEXT_INFO_NOVALNET_RESPONSE_END.'#'. $novalnetInfo->order_no . ''); + $contents[] = array('text' => '' . TABLE_HEADING_ORDER_NUMBER .'' . ': '.$novalnetInfo->order_no); + $contents[] = array('text' => '' . NOVALNET_REFERENCE_ID .'' . ': '.$novalnetInfo->tid); + $contents[] = array('text' => '' . TABLE_HEADING_AMOUNT .'' . ': '.$currencies->format(($novalnetInfo->amount / 100), 1, $novalnetInfo->currency)); + $contents[] = array('text' => '' . NOVALNET_PAYMENT_TYPE .'' . ': '.$novalnetInfo->payment_method); + if (!empty($novalnetInfo->refund_amount)) + $contents[] = array('text' => '' . NOVALNET_REFUND_AMOUNT .'' . ': '.$currencies->format(($novalnetInfo->refund_amount / 100), 1, $novalnetInfo->currency)); + if (!empty($novalnetInfo->callback_amount)) + $contents[] = array('text' => '' . NOVALNET_CALLBACK_AMOUNT .'' . ': '.$currencies->format(($novalnetInfo->callback_amount / 100), 1, $novalnetInfo->currency)); + + $count = 1; + + $contents[] = array('text' => ''); + break; + + case 'PENDING': + + require_once(DIR_WS_CLASSES . 'order.php'); + + $order = new order($novalnetInfo->order_no); + $heading[] = array('text' => '' . TEXT_INFO_NOVALNET_RESPONSE_BEGIN.'#'.$novalnetInfo->id.' '.TEXT_INFO_NOVALNET_RESPONSE_END.'#'. $novalnetInfo->order_no . ''); + $contents[] = array('text' => '' . TABLE_HEADING_ORDER_NUMBER .'' . ': '.$novalnetInfo->order_no); + $contents[] = array('text' => '' . NOVALNET_REFERENCE_ID .'' . ': '.$novalnetInfo->tid); + $contents[] = array('text' => '' . TABLE_HEADING_AMOUNT .'' . ': '.$currencies->format(($novalnetInfo->amount / 100), 1, $novalnetInfo->currency)); + $contents[] = array('text' => '' . NOVALNET_PAYMENT_TYPE .'' . ': '.$novalnetInfo->payment_method); + if (!empty($novalnetInfo->refund_amount)) + $contents[] = array('text' => '' . NOVALNET_REFUND_AMOUNT .'' . ': '.$currencies->format(($novalnetInfo->refund_amount / 100), 1, $novalnetInfo->currency)); + if (!empty($novalnetInfo->callback_amount)) + $contents[] = array('text' => '' . NOVALNET_CALLBACK_AMOUNT .'' . ': '.$currencies->format(($novalnetInfo->callback_amount / 100), 1, $novalnetInfo->currency)); + + $count = 1; + + $contents[] = array('text' => ''); + break; + + case 'DEACTIVATED': + + require_once(DIR_WS_CLASSES . 'order.php'); + + $order = new order($novalnetInfo->order_no); + $heading[] = array('text' => '' . TEXT_INFO_NOVALNET_RESPONSE_BEGIN.'#'.$novalnetInfo->id.' '.TEXT_INFO_NOVALNET_RESPONSE_END.'#'. $novalnetInfo->order_no . ''); + $contents[] = array('text' => '' . TABLE_HEADING_ORDER_NUMBER .'' . ': '.$novalnetInfo->order_no); + $contents[] = array('text' => '' . NOVALNET_REFERENCE_ID .'' . ': '.$novalnetInfo->tid); + $contents[] = array('text' => '' . TABLE_HEADING_AMOUNT .'' . ': '.$currencies->format(($novalnetInfo->amount / 100), 1, $novalnetInfo->currency)); + $contents[] = array('text' => '' . NOVALNET_PAYMENT_TYPE .'' . ': '.$novalnetInfo->payment_method); + if (!empty($novalnetInfo->refund_amount)) + $contents[] = array('text' => '' . NOVALNET_REFUND_AMOUNT .'' . ': '.$currencies->format(($novalnetInfo->refund_amount / 100), 1, $novalnetInfo->currency)); + if (!empty($novalnetInfo->callback_amount)) + $contents[] = array('text' => '' . NOVALNET_CALLBACK_AMOUNT .'' . ': '.$currencies->format(($novalnetInfo->callback_amount / 100), 1, $novalnetInfo->currency)); + + $count = 1; + + $contents[] = array('text' => ''); + break; + + default: + $heading[] = array('text' => ''); + $contents[] = array('text'=> '' ); + } + } + break; + } + if (!empty($heading) && !empty($contents)) { + $box = new box(); + echo '
'; + echo $box->infoBox($heading, $contents); + echo '
'; + } +?> +
+ +
+ + + + diff --git a/changelog.txt b/changelog.txt new file mode 100644 index 0000000..dc57d7e --- /dev/null +++ b/changelog.txt @@ -0,0 +1,66 @@ +*** Changelog *** + += 13.3.3 - 2024.06.21 = +* Enhanced - Payment module has been optimized as per the new testcase + += 13.3.2 - 2024.06.06 = +* Fix - An undefined error that occurred when an order was not found in the shop for canceled transactions +* Enhanced - Refund process has been extended for subsequent installment cycles + += 13.3.1 - 2024.05.17 = +* Enhanced - Extension of Instalment Payment cycles till 36 cycles +* Enhanced - Optimized the Callback/Webhook process for fetching Dynamic IP +* Enhanced - Alert email notification for successful transactions to the store owner for missing orders + += 13.3.0 - 2024.03.22 = +* New - Implemented Direct Debit ACH, MB Way, Payconiq and Blik payments +* Fix - Adapted the sort menu in the shop admin for Novalnet transactions overview to match shop CSS +* Fix - Sort order in the Novalnet transactions overview based on the order status +* Fix - Restructured installment payment tables to improve the readability in the shop's admin interface +* Enhanced - Offering Instalment payments and Guarantee payments to B2B customers in Switzerland +* Removed - Payment due date configuration for Direct Debit SEPA with payment guarantee + += 13.2.0 - 2023.03.15 = +* New - Implemented Novalnet Transaction Overview in the shop admin area +* New - Barzahlen/viacash payment slip implemented on the payment success page +* Fix - setPaymentPending parameter implemented for Apple Pay and Google Pay to avoid amount mismatch +* Fix - Constant value is used for table novalnet_transaction_detail +* Enhanced - Payment module has been optimized as per the new testcase + += 13.0.1 - 2023.03.29 = +* Fix - Code structures optimized to match Zen Cart coding standards + += 13.0.1 - 2023.03.07 = +* Fix - Transaction amount mismatch for PayPal payment +* Fix - Adjusted payment module for standard Instalment cancellation process +* Enhanced - Payment module has been updated for Zen Cart 1.5.7f German version + += 13.0.0 - 2023.02.17 = +Major version release: We've improved the seamless customer experience and brand configurations in the Novalnet Merchant Admin Portal to make it easier to preview and customise the checkout page + += 2.0.0 - 2020.10.01 = +* New - Implemented Guaranteed Direct Debit SEPA, Guaranteed Invoice, Instalment by Direct Debit SEPA, Instalment by Invoice, Barzahlen, Giropay, Eps, Przelewy24, PostFinace Card and PostFinance E-Finance Payments +* New - Force 3D secure process has been implemented as per predefined filters and settings in the Novalnet admin portal +* Enhanced - Implemented new encryption method for redirect payments +* Enhanced - Credit Card iframe has been optimized +* Enhanced - Auto configuration call perform via cURL method +* Enhanced - Adjusted the payment module for IPV6 condition +* Enhanced - On-hold transaction configuration has been implemented for Credit Card, Direct Debit SEPA, Guaranteed Direct Debit SEPA, Invoice, Guaranteed Invoice, Instalment by Direct Debit SEPA, Instalment by Invoice and PayPal. +* Enhanced - Callback has been optimized as per the new testcase +* Fix - Compatible for Zen Cart 1.5.7 + += 1.0.2 - 2013.01.02 = +- Optimized all novalnet payment modules as per new testcase document. +- Developed Novalnet Ideal Payment Module + += 1.0.1 - 2012.01.12 = +- Implement the Novalnet paypal payment method and CALLBACK SCRIPT file. +- Add call back testing method in readme file. + += 1.0.0 - 2011.12.15 +- Readme File(Specification Details included). +- Zencart Payment Module Installation Guide (PDF included) +- update_info File included. +- Check hash implemented in PCI payment modules and include +- Post back Params (Order no., Invoice Reference). +- Iframe implemented for Credit Card Payment method. diff --git a/extras/novalnet_callback.php b/extras/novalnet_callback.php new file mode 100644 index 0000000..4f18c63 --- /dev/null +++ b/extras/novalnet_callback.php @@ -0,0 +1,706 @@ + [ + 'type', + 'checksum', + 'tid', + ], + '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; + + /** + * Core Function : Constructor() + * + */ + public 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 = $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_tid; + + $this->order_details = $this->getOrderDetails(); + 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 the request received from Novalnet or not + * + */ + private function authenticateEventData() + { + $novalnet_host_name = 'pay-nn.de'; + $novalnet_host_ip = gethostbyname($novalnet_host_name); + $request_received_ip = $this->getRemoteAddress($novalnet_host_ip); + if (!empty($novalnet_host_ip) && !empty($request_received_ip)) { + if (MODULE_PAYMENT_NOVALNET_CALLBACK_TEST_MODE == 'False' && $novalnet_host_ip != $request_received_ip) { + $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(); + } + + /** + * Get remote address + * + * @param $novalnet_host_ip + * + */ + public function getRemoteAddress($novalnet_host_ip) + { + $ip_keys = array('HTTP_X_FORWARDED_HOST', 'HTTP_X_REAL_IP', 'HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR'); + foreach ($ip_keys as $key) { + if (array_key_exists($key, $_SERVER) === true) { + if(in_array($key, ['HTTP_X_FORWARDED_HOST', 'HTTP_X_FORWARDED_FOR'])) { + $forwarded_ip = !empty($_SERVER[$key]) ? explode(',', $_SERVER[$key]) : []; + return in_array($novalnet_host_ip, $forwarded_ip) ? $novalnet_host_ip : $_SERVER[$key]; + } + return $_SERVER[$key]; + } + } + } + + /** + * Validate event data mandatory parameters + * + */ + private function validateEventData() + { + if (!empty($this->event_data['custom']['shop_invoked'])) { + $this->displayMessage(['message' => 'Process already handled in the shop.']); + } + 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 + * + */ + private function validateCheckSum() + { + if (!empty($this->event_data['event']['checksum']) && !empty($this->event_tid) && !empty($this->event_data['event']['type']) + && !empty($this->event_data['result']['status'])) { + $token_string = $this->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 (defined('MODULE_PAYMENT_NOVALNET_ACCESS_KEY') && !empty(MODULE_PAYMENT_NOVALNET_ACCESS_KEY)) { + $token_string .= strrev(MODULE_PAYMENT_NOVALNET_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']); + } + } + } + + /** + * Get order details + * + */ + private function getOrderDetails() + { + global $db; + $order_details = []; + $novalnet_order_details = $db->Execute("SELECT * FROM ".TABLE_NOVALNET_TRANSACTION_DETAIL." WHERE tid = '".$this->parent_tid."'"); + if(isset($novalnet_order_details->fields['order_no'])){ + $order_number = $novalnet_order_details->fields['order_no']; + } + if (empty($order_number) && !empty($this->event_data['transaction']['order_no'])) { + $novalnet_order_details = $db->Execute("SELECT * FROM ".TABLE_NOVALNET_TRANSACTION_DETAIL." WHERE order_no = '".$this->event_data['transaction']['order_no']."'"); + if( !isset($novalnet_order_details->fields['order_no']) ){ + $this->displayMessage(['message' => 'Order reference not found in the Shop']); + } + $order_number = $novalnet_order_details->fields['order_no']; + } + // If order number not found in shop and Novalnet + if (empty($order_number) ) + { + if( $this->event_data['result']['status'] == 'SUCCESS') { + $this->sentCriticalMail($this->event_data); + $this->displayMessage(['message' => 'Order reference not found for the TID '. $this->parent_tid]); + } + else{ + $this->displayMessage(['message' => $this->event_data['result']['status_text'] ]); + } + } + // If the order number at Novalnet and the shop doesn't match + if (!empty($this->event_data['transaction']['order_no']) && !empty($novalnet_order_details->fields['order_no']) + && (($this->event_data['transaction']['order_no']) != $novalnet_order_details->fields['order_no'])) { + $this->displayMessage(['message' => 'Order reference not matching for the order number '. $this->event_data['transaction']['order_no']]); + } + $shop_order_details = $db->Execute("SELECT order_total, orders_id, orders_status, language_code FROM ".TABLE_ORDERS." WHERE orders_id = '".$order_number."'"); + $order_lang = $db->Execute("SELECT directory FROM " . TABLE_LANGUAGES . " WHERE code = '" . $shop_order_details->fields['language_code'] ."'"); + $this->includeRequiredFiles($order_lang->fields['directory']); + $order_details['nn_trans_details'] = $novalnet_order_details->fields; + $order_details['shop_order_no'] = $order_number; + $order_details['shop_order_details'] = $shop_order_details->fields; + return $order_details; + } + + /** + * Handle transaction capture + * + */ + private function handleTransactionCapture() + { + $novalnet_update_data = [ + 'status' => $this->event_data['transaction']['status'], + ]; + $order_status = NovalnetHelper::getOrderStatus($this->event_data['transaction']['status'], $this->event_data['transaction']['payment_type']); + if (!empty($this->event_data['transaction']['due_date'])) { + $comments =sprintf(MODULE_PAYMENT_NOVALNET_TRANS_CONFIRM_SUCCESSFUL_MESSAGE, $this->event_data['transaction']['tid'], gmdate('d.m.Y')).PHP_EOL; + } else { + $comments =sprintf(MODULE_PAYMENT_NOVALNET_TRANS_CONFIRM_SUCCESSFUL_MESSAGE_TEXT, gmdate('d.m.Y')).PHP_EOL; + } + if (!empty($this->event_data['instalment']['cycle_dates'])) { + $total_amount = ((isset($this->order_details['nn_trans_details']['amount']) ? $this->order_details['nn_trans_details']['amount'] : 0) < $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); + $this->event_data['transaction']['bank_details'] = empty($this->event_data['transaction']['bank_details']) ? (!empty($this->order_details['nn_trans_details']['payment_details']) ? json_decode($this->order_details['nn_trans_details']['payment_details'], true) : []) : $this->event_data['transaction']['bank_details']; + if (!empty($this->event_data['transaction']['bank_details'])) { + $order_comment .= NovalnetHelper::getBankDetails($this->event_data); + } + if (!empty($this->event_data['instalment'])) { + $order_comment .= NovalnetHelper::getInstalmentDetails($this->event_data); + } + $this->updateOrderStatusHistory($this->event_data['transaction']['order_no'], $order_status, $order_comment); + if (in_array($this->event_data['transaction']['payment_type'], array( 'INSTALMENT_INVOICE','GUARANTEED_INVOICE')) && $this->event_data['transaction']['status'] == 'CONFIRMED') { + NovalnetHelper::sendPaymentConfirmationMail($order_comment, $this->event_data['transaction']['order_no']); + } + $this->updateNovalnetTransaction($novalnet_update_data, "tid='{$this->parent_tid}'"); + $this->sendWebhookMail($comments); + $this->displayMessage(['message' => zen_db_prepare_input($comments . PHP_EOL)]); + } + + /** + * Handle transaction cancel + * + */ + private function handleTransactionCancel() + { + $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'], NovalnetHelper::getOrderStatusId(), $comments); + $this->sendWebhookMail($comments); + $this->displayMessage(['message' => zen_db_prepare_input($comments . PHP_EOL)]); + } + + + /** + * Handle transaction refund + * + */ + private function handleTransactionRefund() + { + global $currencies; + $order_status_id = ''; + $refund_amount = 0; + $comments = 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 = (isset($this->order_details['nn_trans_details']['refund_amount']) ? $this->order_details['nn_trans_details']['refund_amount'] : 0) + $refund_amount; + $novalnet_update_data = array( + 'refund_amount' => $refunded_amount, + 'status' => $this->event_data['transaction']['status'], + ); + if (in_array($this->event_data['transaction']['refund']['payment_type'], array('INSTALMENT_INVOICE_BOOKBACK','INSTALMENT_SEPA_BOOKBACK'))) { + $instalment_details = (!empty($this->order_details['nn_trans_details']['instalment_cycle_details'])) ? json_decode($this->order_details['nn_trans_details']['instalment_cycle_details'], true) : []; + if (!empty($instalment_details)) { + foreach ($instalment_details as $cycle => $cycle_details) { + if (!empty($cycle_details['reference_tid']) && ($cycle_details['reference_tid'] == $this->event_data['transaction']['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'] = (!empty($instalment_details) ? json_encode($instalment_details) : '{}'); + } + if (isset($this->order_details['nn_trans_details']['amount']) && $refunded_amount >= $this->order_details['nn_trans_details']['amount']) { + $order_status_id = NovalnetHelper::getOrderStatusId(); + } + + $this->updateNovalnetTransaction($novalnet_update_data, "tid='{$this->order_details['nn_trans_details']['tid']}'"); + $this->updateOrderStatusHistory($this->order_details['shop_order_no'], $order_status_id, $comments); + $this->sendWebhookMail($comments); + $this->displayMessage(['message' => zen_db_prepare_input($comments . PHP_EOL)]); + } + + /** + * Handle chargeback + * + */ + private function handleTransactionCredit() + { + global $db, $currencies; + $update_comments = true; + $order_status = ''; + $comments = PHP_EOL .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 + $order_status = ($this->order_details['nn_trans_details']['payment_type'] == 'INVOICE') ? 3 : 2; + } else { // Partial paid + $order_status = ($this->order_details['nn_trans_details']['payment_type'] == 'INVOICE') ? 2 : 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->order_details['shop_order_no'], $order_status, $comments); + $this->sendWebhookMail($comments); + } + $this->displayMessage(['message' => zen_db_prepare_input($comments . PHP_EOL)]); + } + + /** + * Handle chargeback + * + */ + private function handleChargeback() + { + global $currencies; + $comments = ''; + 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' => zen_db_prepare_input($comments . PHP_EOL)]); + } + } + + /** + * Handle instalment + * + */ + private function handleInstalment() + { + global $currencies; + $comment = ''; + if ($this->event_data['transaction']['status'] == 'CONFIRMED' && !empty($this->event_data['instalment']['cycles_executed'])) { + $instalment_details = (!empty($this->order_details['nn_trans_details']['instalment_cycle_details'])) ? json_decode($this->order_details['nn_trans_details']['instalment_cycle_details'], true) : []; + $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('d.m.Y H:i:s'); + } + } + if (empty($this->event_data ['transaction']['bank_details'])) { + $this->event_data ['transaction']['bank_details'] = !empty($this->order_details['nn_trans_details']['payment_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}'"); + $comment .= PHP_EOL. NovalnetHelper::insertTransactionDetails($this->event_data, $this->order_details['shop_order_no']); + $this->updateOrderStatusHistory($this->event_data['transaction']['order_no'], '', $comment); + $this->sendWebhookMail($comment); + $this->displayMessage(['message' => zen_db_prepare_input($comment . PHP_EOL)]); + } + } + + /** + * Handle instalment cancel + * + */ + private function handleInstalmentCancel() + { + global $currencies; + $comments = ''; + $novalnet_update_data = []; + if ($this->event_data['transaction']['status'] == 'CONFIRMED') { + $order_status = ''; + $instalment_details = isset($this->order_details['nn_trans_details']['instalment_cycle_details']) ? json_decode($this->order_details['nn_trans_details']['instalment_cycle_details'], true) : []; + if (!empty($instalment_details)) { + $comments = sprintf(MODULE_PAYMENT_NOVALNET_INSTALMENT_CANCEL_ALLCYCLES_TEXT, $this->parent_tid, gmdate('d.m.Y'), $currencies->format(((isset($this->event_data['transaction']['refund']['amount']) ? $this->event_data['transaction']['refund']['amount']/100 : 0)), 1, ($this->event_data['transaction']['refund']['currency']))); + foreach ($instalment_details as $key => $instalment_details_data) { + if ($instalment_details_data['status'] == 'Pending') { + $instalment_details[$key]['status'] = 'Canceled'; + } + + if ($this->event_data['instalment']['cancel_type'] == 'ALL_CYCLES' && $instalment_details_data['status'] == 'Paid'){ + $instalment_details[$key]['status'] = 'Refunded'; + } + } + + if (isset($this->event_data['instalment']['cancel_type']) && $this->event_data['instalment']['cancel_type'] == 'REMAINING_CYCLES') { + $comments = sprintf(MODULE_PAYMENT_NOVALNET_INSTALMENT_CANCEL_REMAINING_CYCLES_TEXT, $this->parent_tid, gmdate('d.m.Y')); + } + } + $novalnet_update_data = [ + 'instalment_cycle_details' => !empty($instalment_details) ? json_encode($instalment_details) : '{}', + 'status' => 'DEACTIVATED', + ]; + $this->updateNovalnetTransaction($novalnet_update_data, "tid='{$this->parent_tid}'"); + $this->updateOrderStatusHistory($this->event_data['transaction']['order_no'], $order_status, $comments); + $this->sendWebhookMail($comments); + $this->displayMessage(['message' => zen_db_prepare_input($comments . PHP_EOL)]); + } + } + + /** + * Handle transaction update + * + */ + private function handleTransactionUpdate() + { + global $currencies; + $transaction_comments = ''; + $order_status = ''; + $novalnet_update_data = [ + 'status' => $this->event_data ['transaction']['status'], + ]; + $amount = (!empty($this->event_data['instalment']['cycle_amount'])) ? $this->event_data['instalment']['cycle_amount'] : $this->event_data['transaction']['amount']; + if ($this->event_data['transaction']['update_type'] == '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')); + $order_status = NovalnetHelper::getOrderStatusId(); + } else if (in_array($this->order_details['nn_trans_details']['status'], array('PENDING', 'ON_HOLD'), true)) { + 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')); + } elseif ($this->event_data['transaction']['status'] == 'CONFIRMED') { + $order_status = 2; + if (!empty($this->event_data['transaction']['bank_details']) || !empty($this->event_data['instalment'])) { + if (!empty($this->event_data['transaction']['due_date'])) { + $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; + } 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; + } + 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); + } + } 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; + } + $novalnet_update_data['callback_amount'] = $this->order_details['nn_trans_details']['amount']; + } + } + } else if ($this->event_data['transaction']['update_type'] == 'AMOUNT') { + $transaction_comments = PHP_EOL.sprintf(MODULE_PAYMENT_NOVALNET_AMOUNT_UPDATE_NOTE, $currencies->format(($amount/100), 1, $this->event_data['transaction']['currency']), gmdate('d.m.Y')).PHP_EOL; + } elseif ($this->event_data['transaction']['update_type'] == 'DUE_DATE') { + $transaction_comments = PHP_EOL.sprintf(MODULE_PAYMENT_NOVALNET_DUEDATE_UPDATE_NOTE, $this->event_data['transaction']['due_date'], gmdate('d.m.Y')).PHP_EOL; + } elseif ($this->event_data['transaction']['update_type'] == 'AMOUNT_DUE_DATE') { + $transaction_comments = PHP_EOL.sprintf(MODULE_PAYMENT_NOVALNET_AMOUNT_DUEDATE_UPDATE_NOTE, $currencies->format(($amount/100), 1, $this->event_data['transaction']['currency']), $this->event_data['transaction']['due_date'], gmdate('d.m.Y')).PHP_EOL; + } + + // Reform the transaction comments. + $transaction_comments .= NovalnetHelper::getTransactionDetails($this->event_data); + $this->event_data['transaction']['bank_details'] = empty($this->event_data['transaction']['bank_details']) ? (!empty($this->order_details['nn_trans_details']['payment_details']) ? json_decode($this->order_details['nn_trans_details']['payment_details'], true) : []) : $this->event_data['transaction']['bank_details']; + if (($this->event_data['transaction']['status'] != 'DEACTIVATED') && !empty($this->event_data['transaction']['bank_details'])) { + $transaction_comments .= NovalnetHelper::getBankDetails($this->event_data); + } + if ($this->event_data['transaction']['payment_type'] === 'CASHPAYMENT') { + $nn_barzahlen_stores = json_decode($this->order_details['nn_trans_details']['payment_details'], true); + $this->event_data['transaction']['nearest_stores'] = !empty($nn_barzahlen_stores) ? $nn_barzahlen_stores['nearest_stores'] : []; + $transaction_comments .= NovalnetHelper::getNearestStoreDetails($this->event_data); + } + if (!empty($this->event_data['instalment'])) { + $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 ($this->event_data['transaction']['status'] === 'CONFIRMED') { + $novalnet_update_data['callback_amount'] = $this->event_data['transaction']['amount']; + } + } + } + if (in_array($this->event_data['transaction']['payment_type'], array('INSTALMENT_INVOICE','GUARANTEED_INVOICE')) && in_array($this->event_data['transaction']['status'], array('CONFIRMED', 'ON_HOLD'))) { + NovalnetHelper::sendPaymentConfirmationMail($transaction_comments, $this->event_data['transaction']['order_no']); + } + $this->updateNovalnetTransaction($novalnet_update_data, "tid='{$this->parent_tid}'"); + $this->updateOrderStatusHistory($this->order_details['shop_order_no'], $order_status, $transaction_comments); + $this->sendWebhookMail($transaction_comments); + $this->displayMessage(['message' => zen_db_prepare_input($transaction_comments . PHP_EOL)]); + } + + /** + * Handle Payment Reminder + * + */ + private function handlePaymentReminder() + { + $comments =sprintf(NOVALNET_PAYMENT_REMINDER_NOTE, explode('_', $this->event_type)[2]); + $this->updateOrderStatusHistory($this->event_data['transaction']['order_no'], '', $comments); + $this->sendWebhookMail($comments); + $this->displayMessage([ 'message' => zen_db_prepare_input($comments . PHP_EOL)]); + } + + /** + * Handle Collection Agency Submission + * + */ + private function handleCollectionSubmission() + { + $comments =sprintf(NOVALNET_COLLECTION_SUBMISSION_NOTE, $this->event_data['collection']['reference']); + $this->updateOrderStatusHistory($this->event_data['transaction']['order_no'], '', $comments); + $this->sendWebhookMail($comments); + $this->displayMessage([ 'message' => zen_db_prepare_input($comments . PHP_EOL)]); + } + + /** + * Print the Webhook messages. + * + * @param $message + * + * @return void + */ + private function displayMessage($message) + { + echo json_encode($message); + exit; + } + + /** + * Update the details in Shop order status table. + * + * @param $order_no + * @param $order_status_id + * @param $comments + */ + private function updateOrderStatusHistory($order_no, $order_status_id = '', $comments = '') + { + global $db; + if ($order_status_id == '') { + $current_order_status = $db->Execute("SELECT orders_status FROM " . TABLE_ORDERS . " WHERE orders_id = " . $order_no); + $order_status_id = $current_order_status->fields['orders_status']; + } + $datas_need_to_update['orders_status'] = $order_status_id; + // Update order status id in orders table + zen_db_perform(TABLE_ORDERS, $datas_need_to_update, "update", "orders_id = '$order_no'"); + $data_array = array( + 'orders_id' => $order_no, + 'orders_status_id' => $order_status_id, + 'date_added' => date('Y-m-d H:i:s'), + 'customer_notified' => 1, + 'comments' => zen_db_prepare_input($comments . PHP_EOL) + ); + // Update order details in history table + zen_db_perform(TABLE_ORDERS_STATUS_HISTORY, $data_array, 'insert'); + } + + /* + * Update the transaction details in Novalnet table + * + * @param $data + * @param $parameters + */ + private function updateNovalnetTransaction($data, $parameters = '') + { + if ($parameters == '') { + return false; + } + zen_db_perform(TABLE_NOVALNET_TRANSACTION_DETAIL, $data, 'update', $parameters); + } + + /** + * Send notification mail to Merchant + * + * @param $comments + */ + private 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. + */ + private function includeRequiredFiles($lang) + { + + // include language + include_once(DIR_FS_CATALOG . DIR_WS_LANGUAGES. $lang."/modules/payment/novalnet_payments.php"); + + // include helper file after language files. + require_once(DIR_FS_CATALOG . DIR_WS_MODULES. 'payment/novalnet/NovalnetHelper.php'); + return; + } + + /** + * Send critical mail + * + * @return none + */ +private function sentCriticalMail($data) + { + global $currencies; + $this->includeRequiredFiles('german'); + $subject = MODULE_PAYMENT_NOVALNET_WEBHOOK_ACTION_REQUIRED . $data['event']['tid'] .MODULE_PAYMENT_NOVALNET_WEBHOOK_IN . STORE_NAME; + $message = MODULE_PAYMENT_NOVALNET_WEBHOOK_SALUTATION . STORE_OWNER . ',' . PHP_EOL . PHP_EOL. MODULE_PAYMENT_NOVALNET_WEBHOOK_ATTENTION . PHP_EOL; + $message .= MODULE_PAYMENT_NOVALNET_WEBHOOK_PROJECT_ID . $data['merchant']['project'] . PHP_EOL; + $message .= MODULE_PAYMENT_NOVALNET_WEBHOOK_TID . $data['event']['tid'] . PHP_EOL; + $message .= MODULE_PAYMENT_NOVALNET_WEBHOOK_TID_STATUS . $data['transaction']['status'] . PHP_EOL; + $message .= MODULE_PAYMENT_NOVALNET_WEBHOOK_PAYMENT_TYPE . $data['transaction']['payment_type'] . PHP_EOL; + $message .= MODULE_PAYMENT_NOVALNET_AMOUNT . $currencies->format(($data['transaction']['amount'] /100), 1, $data['transaction']['currency']). PHP_EOL; + $message .= MODULE_PAYMENT_NOVALNET_WEBHOOK_EMAIL . $data['customer']['email'] . PHP_EOL; + $message .= PHP_EOL . MODULE_PAYMENT_NOVALNET_WEBHOOK_COMMUNICATION_PROBLEM . PHP_EOL; + $message .= PHP_EOL . MODULE_PAYMENT_NOVALNET_WEBHOOK_DISCREPANCIES . PHP_EOL; + $message .= PHP_EOL . MODULE_PAYMENT_NOVALNET_WEBHOOK_MANUAL_ORDER_CREATION . PHP_EOL; + $message .= MODULE_PAYMENT_NOVALNET_WEBHOOK_REFUND_INITIATION . PHP_EOL; + $message .= PHP_EOL . MODULE_PAYMENT_NOVALNET_WEBHOOK_PROMPT_REVIEW . PHP_EOL; + $message .= PHP_EOL . MODULE_PAYMENT_NOVALNET_WEBHOOK_REGARDS . PHP_EOL . 'Novalnet Team'; + zen_mail(STORE_NAME, STORE_OWNER_EMAIL_ADDRESS, $subject, str_replace('
', PHP_EOL, $message), STORE_NAME, EMAIL_FROM, array(), '', '', STORE_NAME, EMAIL_FROM); + } +} +new NovalnetWebhooks(); diff --git a/includes/extra_datafiles/novalnet.php b/includes/extra_datafiles/novalnet.php new file mode 100644 index 0000000..f313e00 --- /dev/null +++ b/includes/extra_datafiles/novalnet.php @@ -0,0 +1,15 @@ +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_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_MULTIBANCO_SUPPLIER_NOTE', 'Entity: %s'); +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_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 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_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_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', 'Refund / Cancellation Reason'); +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 cycle date'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_REFUND_BACKEND', 'Instalment refund'); +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_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_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)'); +define('MODULE_PAYMENT_NOVALNET_ONHOLD_EN_ORDER_STATUS', 'Payment authorized (Novalnet)'); +define('MODULE_PAYMENT_NOVALNET_CANCELED_EN_ORDER_STATUS', 'Canceled (Novalnet)'); +define('MODULE_PAYMENT_NOVALNET_ORDER_MAIL_SUBJECT', 'Order Confirmation - Your Order number %1$s with %2$s has been confirmed!'); +define('MODULE_PAYMENT_NOVALNET_ORDER_MAIL_MESSAGE', 'Order Confirmation from %s'); +define('MODULE_PAYMENT_NOVALNET_ORDER_MAIL_DATE', 'Date Ordered: %s'); +define('MODULE_PAYMENT_NOVALNET_ORDER_NUMBER', 'Order number: %s'); +define('MODULE_PAYMENT_NOVALNET_DELIVERY_ADDRESS', 'Delivery address'); +define('MODULE_PAYMENT_NOVALNET_BILLING_ADDRESS', 'Billing address'); +define('MODULE_PAYMENT_NOVALNET_ORDER_CONFIRMATION', 'Payment confirmation:'); +define('MODULE_PAYMENT_NOVALNET_CUSTOMER_SALUTATION', 'Dear Mr/Ms '); +define('MODULE_PAYMENT_NOVALNET_INCL_TAX_LABEL', 'Incl.Tax'); +define('MODULE_PAYMENT_NOVALNET_EXCL_TAX_LABEL', 'Excl.Tax'); +define('MODULE_PAYMENT_NOVALNET_DISCOUNT_AND_GIFT_VOUCHER_LABEL', 'Discount'); +define('MODULE_PAYMENT_NOVALNET_SHIPPING_LABEL', 'Shipping'); +define('MODULE_PAYMENT_NOVALNET_AMOUNT_UPDATE_NOTE', 'Transaction amount %1$s has been updated successfully on %2$s'); +define('MODULE_PAYMENT_NOVALNET_DUEDATE_UPDATE_NOTE', 'Transaction due date %1$s has been updated successfully on %2$s'); +define('MODULE_PAYMENT_NOVALNET_AMOUNT_DUEDATE_UPDATE_NOTE', 'Transaction amount %1$s and due date %2$s has been updated successfully on %3$s'); +define('MODULE_PAYMENT_NOVALNET_BARZAHLEN_SUCCESS_BUTTON', 'Pay now with Barzahlen'); +define('MODULE_PAYMENT_NOVALNET_WALLET_TOTAL_LABEL', 'Estimated total (No offers applied)'); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_ACTION_REQUIRED', 'Action Required - Order Not found for the Transaction ID: '); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_IN', ' in '); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_SALUTATION', 'Dear '); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_ATTENTION', 'We would like to bring to your attention the following transaction details:'); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_COMMUNICATION_PROBLEM', 'The payment for the above transaction details was successfully processed in Novalnet. However, it appears that our system encountered difficulties in communicating with your shop system.'); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_DISCREPANCIES', 'We kindly request one of the following actions to prevent any discrepancies for the transaction:'); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_MANUAL_ORDER_CREATION', 'Manual Order Creation: Please create an order manually in your shop back-office and generate an invoice corresponding to the provided transaction details.'); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_REFUND_INITIATION', 'Refund Initiation: Alternatively, you may initiate a refund for the transaction through the Novalnet Admin Portal(https://admin.novalnet.de/)'); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_PROMPT_REVIEW', 'Your prompt review and action on these transaction details would be greatly appreciated.'); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_EMAIL', 'Customer E-mail: '); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_PAYMENT_TYPE', 'Payment Type: '); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_TID_STATUS', 'Transaction ID Status: '); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_TID', 'Transaction ID: '); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_PROJECT_ID', 'Project ID: '); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_REGARDS', 'Regards,'); + 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..c4451db --- /dev/null +++ b/includes/languages/german/modules/payment/novalnet_payments.php @@ -0,0 +1,141 @@ +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_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_MULTIBANCO_SUPPLIER_NOTE', 'Entität: %s'); +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_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_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 nur den unten angegebenen Verwendungszweck für die Überweisung, da nur so Ihr Geldeingang zugeordnet werden kann:'); +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_SUMMARY_BACKEND', 'Zusammenfassung der Ratenzahlung'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_CANCEL_ADMIN_TEXT', 'Ratenzahlung Stornieren'); +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_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_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 der Rückerstattung/Stornierung'); +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', 'Nächstes Ratenzahlungsdatum: '); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_PAY_DATE_BACKEND', 'Bezahltes Datum'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_NEXT_DATE_BACKEND', 'Ratenzahlung Datum'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_REFUND_BACKEND', 'Ratenerstattung'); +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_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', 'Gesamte Ratenzahlung 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'); +define('MODULE_PAYMENT_NOVALNET_INSTALMENT_CANCEL_REMAINING_CYCLES', 'Alle übrigen Installationen abbrechen'); +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?'); +define('MODULE_PAYMENT_NOVALNET_ONHOLD_DE_ORDER_STATUS', 'Zahlung autorisiert (Novalnet)'); +define('MODULE_PAYMENT_NOVALNET_CANCELED_DE_ORDER_STATUS', 'Storniert (Novalnet)'); +define('MODULE_PAYMENT_NOVALNET_ORDER_MAIL_SUBJECT', ' Bestellbestätigung - Ihre Bestellung nummer %1$s bei %2$s wurde bestätigt!'); +define('MODULE_PAYMENT_NOVALNET_ORDER_MAIL_MESSAGE', ' Bestellbestätigung von %s'); +define('MODULE_PAYMENT_NOVALNET_ORDER_MAIL_DATE', 'Datum der Bestellung: %s'); +define('MODULE_PAYMENT_NOVALNET_ORDER_NUMBER', 'Bestellnummer: %s'); +define('MODULE_PAYMENT_NOVALNET_DELIVERY_ADDRESS', 'Lieferanschrift'); +define('MODULE_PAYMENT_NOVALNET_BILLING_ADDRESS', 'Rechnungsanschrift'); +define('MODULE_PAYMENT_NOVALNET_ORDER_CONFIRMATION', 'Bestätigung der Zahlung:'); +define('MODULE_PAYMENT_NOVALNET_CUSTOMER_SALUTATION', 'Sehr geehrte Herr/Frau '); +define('MODULE_PAYMENT_NOVALNET_INCL_TAX_LABEL', 'Inkl.Steuer'); +define('MODULE_PAYMENT_NOVALNET_EXCL_TAX_LABEL', 'Exkl.Steuer'); +define('MODULE_PAYMENT_NOVALNET_DISCOUNT_AND_GIFT_VOUCHER_LABEL', 'Rabatt'); +define('MODULE_PAYMENT_NOVALNET_SHIPPING_LABEL', 'Versand'); +define('MODULE_PAYMENT_NOVALNET_AMOUNT_UPDATE_NOTE', 'Der Transaktionsbetrag %1$s erfolgreich aktualisiert wurde am %2$s'); +define('MODULE_PAYMENT_NOVALNET_DUEDATE_UPDATE_NOTE', ' Fälligkeitsdatum der Transaktion %1$s erfolgreich aktualisiert wurde am %2$s'); +define('MODULE_PAYMENT_NOVALNET_AMOUNT_DUEDATE_UPDATE_NOTE', 'der Transaktion Betrag %1$s und Fälligkeitsdatum %2$s wurde erfolgreich aktualisiert auf %3$s'); +define('MODULE_PAYMENT_NOVALNET_BARZAHLEN_SUCCESS_BUTTON', 'Bezahlen mit Barzahlen'); +define('MODULE_PAYMENT_NOVALNET_WALLET_TOTAL_LABEL', 'Geschätzter Gesamtbetrag (Keine Angebote angewendet)'); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_ACTION_REQUIRED', 'Aktion erforderlich - Bestellung nicht gefunden für die Transaktions-ID: '); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_IN', ' im '); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_SALUTATION', 'Sehr geehrter '); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_ATTENTION', 'Wir möchten Sie auf die folgenden Transaktionsdetails aufmerksam machen:'); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_COMMUNICATION_PROBLEM', 'Die Zahlung für die oben genannten Transaktionsdetails wurde in Novalnet erfolgreich verarbeitet. Es scheint jedoch, dass unser System Schwierigkeiten bei der Kommunikation mit Ihrem Shopsystem hatte.'); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_DISCREPANCIES', 'Wir bitten Sie, eine der folgenden Maßnahmen zu ergreifen, um Unstimmigkeiten bei der Transaktion zu vermeiden:'); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_MANUAL_ORDER_CREATION', 'Manuelle Auftragserstellung: Bitte legen Sie eine Bestellung manuell im Back-Office Ihres Shops an und erstellen Sie eine Rechnung entsprechend den angegebenen Transaktionsdetails.'); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_REFUND_INITIATION', 'Einleitung der Rückerstattung: Alternativ können Sie über das Novalnet Admin Portal(https://admin.novalnet.de/) eine Rückerstattung der Transaktion beantragen.'); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_PROMPT_REVIEW', 'Wir würden es sehr begrüßen, wenn Sie diese Vorgänge umgehend überprüfen und entsprechende Maßnahmen ergreifen würden.'); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_EMAIL', 'Kunden-E-Mail: '); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_PAYMENT_TYPE', 'Zahlungsart: '); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_TID_STATUS', 'Transaktions-ID Status: '); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_TID', 'Transaktions-ID: '); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_PROJECT_ID', 'Projekt-ID: '); +define('MODULE_PAYMENT_NOVALNET_WEBHOOK_REGARDS', 'Herzliche Grüße,'); + diff --git a/includes/modules/payment/novalnet/NovalnetHelper.php b/includes/modules/payment/novalnet/NovalnetHelper.php new file mode 100644 index 0000000..d1ab67e --- /dev/null +++ b/includes/modules/payment/novalnet/NovalnetHelper.php @@ -0,0 +1,1014 @@ + 'PAYMENTFORM' + ]; + } + + /** + * Get shop date formate + * + * @return $date + */ + public static function format_date($date) { + return !empty(trim($date)) && trim($date) != "-" ? (new DateTime($date))->format('d.m.Y H:i:s') : ''; + } + + + /** + * Get transaction data + * + * @return $data + */ + public static function getTransactionData(&$params) + { + global $order; + $params['transaction'] = [ + 'amount' => self::getOrderAmount($order->info['total']), + 'currency' => $order->info['currency'], + 'system_name' => 'Zen_Cart', + 'system_version' => NovalnetHelper::getSystemVersion(), + 'system_url' => (defined('ENABLE_SSL') ? (ENABLE_SSL == true ? HTTPS_SERVER : HTTP_SERVER . DIR_WS_CATALOG) : (HTTPS_CATALOG_SERVER . DIR_WS_HTTPS_CATALOG)), + 'system_ip' => $_SERVER['SERVER_ADDR'] + ]; + + if (isset($_SESSION['nn_booking_details']) && ($_SESSION['nn_payment_details'])) { + $booking_details = $_SESSION['nn_booking_details']; + $payment_details = $_SESSION['nn_payment_details']; + $params['transaction']['payment_type'] = !empty($payment_details->type) ? $payment_details->type : ''; + $payment_action = !empty($booking_details->payment_action) ? $booking_details->payment_action : ''; + + if (isset($booking_details->test_mode)) { + $params['transaction']['test_mode'] = $booking_details->test_mode; + } + + $payment_data_keys = ['token', 'pan_hash', 'unique_id', 'iban', 'wallet_token', 'bic']; + + foreach ($payment_data_keys as $key) { + if (!empty($booking_details->{$key})) { + $params['transaction']['payment_data'][$key] = $booking_details->{$key}; + } + } + + if (!empty($booking_details->create_token)) { + $params['transaction']['create_token'] = $booking_details->create_token; + unset($_SESSION['nn_booking_details']->create_token); + } + + if (!empty($booking_details->enforce_3d)) { + $params['transaction']['enforce_3d'] = $booking_details->enforce_3d; + } + + if (!empty($booking_details->due_date)) { + $params['transaction']['due_date'] = date("Y-m-d", strtotime('+' . $booking_details->due_date . ' days')); + } + if (!empty($booking_details->account_number)) { + $params['transaction']['payment_data'] = + [ + 'account_holder' => $booking_details->account_holder, + 'account_number' => $booking_details->account_number, + 'routing_number' => $booking_details->routing_number, + ]; + } + if ($params['transaction']['payment_type'] == 'PAYPAL') { + + self::paypal_sheet_details($params); + } + + if ($payment_action == 'zero_amount') { + $params['transaction']['amount'] = 0; + $params['transaction']['create_token'] = 1; + } + + if (!empty($booking_details->payment_ref->token)) { + $params['transaction']['payment_data']['token'] = $booking_details->payment_ref->token; + unset($_SESSION['nn_booking_details']->payment_ref->token); + unset($params['transaction']['create_token']); + } + + if (!empty($booking_details->cycle)) { + $params['instalment'] = [ + 'interval' => '1m', + 'cycles' => $booking_details->cycle, + ]; + } + + if ((!empty($payment_details->process_mode) && $payment_details->process_mode == 'redirect') || + (!empty($booking_details->do_redirect) && ($booking_details->do_redirect == '1' || $booking_details->do_redirect == true)) + ) { + $params['transaction']['return_url'] = ((isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on") ? 'https://' : 'http://') . $_SERVER['HTTP_HOST']. $_SERVER['REQUEST_URI']; + } + } + } + + /** + * Get billing country + * @param $order + * + * @return string + */ + public static function getBillingCountry($order) + { + global $db; + if (isset($order->billing['country']['id']) && !empty($order->billing['country']['id'])) { + $billing_country_code = $db->Execute("select countries_iso_code_2 from ".TABLE_COUNTRIES." where countries_id = '".$order->billing['country']['id']."'"); + } else { + $billing_country_query = $db->Execute("select countries_id from ".TABLE_COUNTRIES_NAME." where countries_name = '".$order->billing['country']."'"); + if (isset($billing_country_query->fields['countries_id'])) { + $billing_country_code = $db->Execute("select countries_iso_code_2 from ".TABLE_COUNTRIES." where countries_id = '".$billing_country_query->fields['countries_id']."'"); + } + } + return !empty($billing_country_code->fields['countries_iso_code_2']) ? $billing_country_code->fields['countries_iso_code_2'] : ''; + } + + /** + * Get delivery country + * @param $order + * + * @return string + */ + public static function getDeliveryCountry($order) + { + global $db; + if (isset($order->delivery['country']['id']) && !empty($order->delivery['country']['id'])) { + $delivery_country_code = $db->Execute("select countries_iso_code_2 from ".TABLE_COUNTRIES." where countries_id = '".$order->delivery['country']['id']."'"); + } else { + $delivery_country_query = $db->Execute("select countries_id from ".TABLE_COUNTRIES_NAME." where countries_name = '".$order->delivery['country']."'"); + if (isset($delivery_country_query->fields['countries_id'])) { + $delivery_country_code = $db->Execute("select countries_iso_code_2 from ".TABLE_COUNTRIES." where countries_id = '".$delivery_country_query->fields['countries_id']."'"); + } + } + + return !empty($delivery_country_code->fields['countries_iso_code_2']) ? $delivery_country_code->fields['countries_iso_code_2'] : ''; + } + + /** + * Get customer data + * + * @return $params + */ + public static function getCustomerData(&$params) + { + global $order; + $billingCountry_code = !isset($order->billing['country']['iso_code_2']) ? self::getBillingCountry($order) : $order->billing['country']['iso_code_2']; + $deliveryCountry_code = !isset($order->delivery['country']['iso_code_2']) ? self::getDeliveryCountry($order) : $order->delivery['country']['iso_code_2']; + + $params['customer'] = [ + 'gender' => !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' => !empty($_SESSION['customer_id']) ? $_SESSION['customer_id'] : $order->customer['id'], + 'billing' => [ + 'street' => !empty($order->billing['suburb']) ? ($order->billing['street_address'] . ',' . $order->billing['suburb']) : $order->billing['street_address'], + 'city' => $order->billing['city'], + 'zip' => $order->billing['postcode'], + 'country_code' => $billingCountry_code + ] + ]; + if (isset($order->billing['state'])) { + $params['customer']['billing']['state'] = $order->billing['state']; + } + if (!empty($order->customer['telephone'])) { + $params['customer']['tel'] = $order->customer['telephone']; + } + + if (self::isBillingShippingsame($billingCountry_code, $deliveryCountry_code)) { + $params['customer']['shipping']['same_as_billing'] = 1; + } else { + $params['customer']['shipping'] = [ + 'street' => !empty($order->delivery['suburb']) ? $order->delivery['street_address'] . ',' . $order->delivery['suburb'] : $order->delivery['street_address'], + 'city' => $order->delivery['city'], + 'zip' => $order->delivery['postcode'], + 'country_code' => $deliveryCountry_code + ]; + + if (!empty($order->delivery['company'])) { + $params['customer']['shipping']['company'] = $order->delivery['company']; + } + if (isset($order->delivery['state'])) { + $params['customer']['shipping']['state'] = $order->delivery['state']; + } + } + + if (!empty($_SESSION['nn_booking_details']->birth_date)) { + $params['customer']['birth_date'] = date("Y-m-d", strtotime($_SESSION['nn_booking_details']->birth_date)); + } elseif (!empty($order->billing['company'])) { + $params['customer']['billing']['company'] = $order->billing['company']; + } + } + + /** + * Get request custom data + */ + public static function getCustomData(&$params) + { + $params['custom'] = [ + 'lang' => (isset($_SESSION['languages_code'])) ? strtoupper($_SESSION['languages_code']) : 'DE', + ]; + } + + /** + * Check billing and shpping address is same + * @param $billingCountry_code + * @param $deliveryCountry_code + * + * @return boolean + */ + public static function isBillingShippingsame($billingCountry_code, $deliveryCountry_code) + { + global $order; + + $delivery_address = array( + 'street' => $order->delivery['street_address'], + 'city' => $order->delivery['city'], + 'postcode' => $order->delivery['postcode'], + 'country' => $deliveryCountry_code + ); + $billing_address = array( + 'street' => $order->billing['street_address'], + 'city' => ($order->billing['city']), + 'postcode' => ($order->billing['postcode']), + 'country' => $billingCountry_code + ); + + if ((empty($delivery_address['street']) && empty($delivery_address['city']) && empty($delivery_address['postcode']) && empty($delivery_address['country'])) && + !empty($billing_address) + ) { + return true; + } elseif ($billing_address === $delivery_address) { + return true; + } + + return false; + } + + /** + * 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) + { + global $order; + $amount = 0; + $amount = ($order->info['currency_value'] != 0) ? ($order_amount * $order->info['currency_value']) : $order_amount; + return (sprintf('%0.2f', $amount) * 100); + } + + /** + * Get parameter for GooglePay process + * + * @return string Hidden fields with GooglePay data. + */ + public static function getWalletParam() + { + global $order, $db; + $tax_value = $coupon_amount = $discount = $currency_value = 0; + $currency_value = ($order->info['currency_value'] != 0) ? ($order->info['currency_value']) : ''; + $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']."'"); + } + + $productAmount = (DISPLAY_PRICE_WITH_TAX == 'true') ? (!empty($currency_value) ? (string)(($products['qty'] * (round(($products['final_price'] * $currency_value) + zen_calculate_tax($products['final_price'], $products['tax']), 2)))*100) : (string)(($products['qty'] * (round(($products['final_price']) + zen_calculate_tax($products['final_price'], $products['tax']), 2)))*100)) : (!empty($currency_value) ? (string)((round(($products['qty'] * $products['final_price'] * $currency_value), 2))*100) : (string)((round(($products['qty'] * $products['final_price']), 2))*100)); + $articleDetails[] = array( + 'label'=> str_replace("'", "#single_quote", $products['name']). ' x ' .$products['qty'], + 'amount' => $productAmount, + 'type' => 'SUBTOTAL', + ); + } + + if ($order->info['tax'] != 0) { + foreach ($order->info['tax_groups'] as $key => $value) { + $tax_value += zen_round($value, 2); + } + + $articleDetails[] = array( + 'label' => (DISPLAY_PRICE_WITH_TAX == 'true') ? (defined('MODULE_PAYMENT_NOVALNET_INCL_TAX_LABEL') ? MODULE_PAYMENT_NOVALNET_INCL_TAX_LABEL : '') : (defined('MODULE_PAYMENT_NOVALNET_EXCL_TAX_LABEL') ? MODULE_PAYMENT_NOVALNET_EXCL_TAX_LABEL : ''), + 'amount' => !empty($currency_value) ? (string) (round(($tax_value * $currency_value), 2) * 100) : (string) (round(($tax_value), 2) * 100), + 'type' => 'SUBTOTAL' + ); + } + + if ($_SESSION['cot_gv'] != 0.00 || (isset($order->info['coupon_code']) && !empty($order->info['coupon_code']))) { + $discount = (isset($order->info['coupon_amount']) && !empty($order->info['coupon_amount'])) ? $order->info['coupon_amount'] : ($coupon_amount->fields['coupon_amount']); + $deduction = $discount + $_SESSION['cot_gv']; + $articleDetails[] = array( + 'label'=> defined('MODULE_PAYMENT_NOVALNET_DISCOUNT_AND_GIFT_VOUCHER_LABEL') ? MODULE_PAYMENT_NOVALNET_DISCOUNT_AND_GIFT_VOUCHER_LABEL : '', + 'amount' => !empty($currency_value) ? (string) (round(($deduction * $currency_value), 2) * 100) : (string) (round(($deduction), 2) * 100), + 'type' => 'SUBTOTAL' + ); + } + + $articleDetails[] = array( + 'label'=> defined('MODULE_PAYMENT_NOVALNET_SHIPPING_LABEL') ? MODULE_PAYMENT_NOVALNET_SHIPPING_LABEL : '', + 'amount' => !empty($currency_value) ? (string)(round(($order->info['shipping_cost'] * $currency_value),2)*100) : (string)(round(($order->info['shipping_cost']),2)*100), + 'type' => 'SUBTOTAL' + ); + return ""; + } + + /** + * Handle redirect payments success response + * @param $request + * + * @return $response + */ + public static function handleRedirectSuccessResponse($request) + { + $transaction_details = array('transaction' => array('tid' => $request['tid'])); + return self::sendRequest($transaction_details, self::getActionEndpoint('transaction_details')); + } + + /** + * Get Novalnet transaction details from novalnet table + * + * @param array $order_no + * + * @return object + */ + public static function getNovalnetTransDetails($order_no) + { + global $db; + return $db->Execute("SELECT * FROM ".TABLE_NOVALNET_TRANSACTION_DETAIL." WHERE order_no='" . zen_db_input($order_no) . "'"); + } + + /** + * Send request to server + * + * @param array $data + * @param string paygate_url + * @param string access_key + */ + public static function sendRequest($data, $paygate_url, $access_key = null) + { + $headers = self::getHeadersParam($access_key); + $json_data = !empty($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)) { + return ['status_code' => 106, 'status_text' => curl_error($curl)]; + } + curl_close($curl); + + return !empty($result) ? json_decode($result, true) : []; + } + + /** + * Get transaction details + * @param $response + * + * @return $txn_details + */ + public static function getTransactionDetails($response) + { + global $currencies; + $txn_details = ''; + $payment_type = !empty($response['transaction']['payment_type']) ? $response['transaction']['payment_type'] : ''; + + if (!empty($response ['transaction']['tid'])) { + if ($payment_type == 'GOOGLEPAY' && isset($response['transaction']['payment_data'])) { + $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 : ''; + } + + // to do + if (($response ['transaction']['amount'] == 0) && ($_SESSION['nn_booking_details']->payment_action == 'zero_amount')) { + $txn_details .= PHP_EOL. MODULE_PAYMENT_NOVALNET_ZEROAMOUNT_BOOKING_MESSAGE; + } + + if ($response['transaction']['status_code'] == 75 && $response['transaction']['status'] == 'PENDING') { + $txn_details .= PHP_EOL . MODULE_PAYMENT_NOVALNET_MENTION_GUARANTEE_PAYMENT_PENDING_TEXT.PHP_EOL; + } + + if (!empty($response['transaction']['partner_payment_reference'])) { + $amount = $currencies->format($response['transaction']['amount'] / 100, true, $response['transaction']['currency']); + $txn_details .= 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']); + $txn_details .= PHP_EOL . sprintf(MODULE_PAYMENT_NOVALNET_MULTIBANCO_SUPPLIER_NOTE, $response['transaction']['service_supplier_id']) . 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 = 0; + $bank_details = []; + $amount = $currencies->format($response['transaction']['amount']/100, false, $response['transaction']['currency']); + + if (!empty($response['instalment']['cycle_amount'])) { + $amount = $currencies->format($response['instalment']['cycle_amount']/100, false, $response['transaction']['currency']); + } + + $note = !empty($response['instalment']['cycle_amount']) ? (PHP_EOL . sprintf(MODULE_PAYMENT_NOVALNET_INSTALMENT_AMOUNT_TRANSFER_NOTE, $amount) . PHP_EOL) : + (PHP_EOL.sprintf(MODULE_PAYMENT_NOVALNET_AMOUNT_TRANSFER_NOTE, $amount) .PHP_EOL); + + if ($response['transaction']['status'] != 'ON_HOLD' && !empty($response['transaction']['due_date'])) { // If due date is not empty + $note = !empty($response['instalment']['cycle_amount']) ? ( PHP_EOL.sprintf(MODULE_PAYMENT_NOVALNET_INSTALMENT_AMOUNT_TRANSFER_NOTE_DUE_DATE, $amount, date('d.m.Y', strtotime($response ['transaction']['due_date']))) . PHP_EOL ) : + (PHP_EOL.sprintf(MODULE_PAYMENT_NOVALNET_AMOUNT_TRANSFER_NOTE_DUE_DATE, $amount, date('d.m.Y', strtotime($response['transaction']['due_date']))) .PHP_EOL); + } + + $bank_details = array( + 'account_holder' => PHP_EOL.MODULE_PAYMENT_NOVALNET_ACCOUNT_HOLDER , + 'bank_name' => MODULE_PAYMENT_NOVALNET_BANK_NAME , + 'bank_place' => MODULE_PAYMENT_NOVALNET_BANK_PLACE , + 'iban' => MODULE_PAYMENT_NOVALNET_IBAN , + 'bic' => MODULE_PAYMENT_NOVALNET_BIC , + ); + + foreach ($bank_details as $key => $text) { + if (! empty($response ['transaction']['bank_details'][ $key ])) { + $note .= $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 = ''; + + if (!empty($response['transaction']['due_date'])) { + $txn_details .= PHP_EOL.MODULE_PAYMENT_NOVALNET_TRANS_SLIP_EXPIRY_DATE .date(DATE_FORMAT, strtotime($response['transaction']['due_date'])); + } + + $txn_details .= PHP_EOL .MODULE_PAYMENT_NOVALNET_NEAREST_STORE_DETAILS ; + + if (!empty($response['transaction']['nearest_stores'])) { + foreach ($response['transaction']['nearest_stores'] as $store) { + $txn_details .= PHP_EOL . $store['store_name']; + $txn_details .= PHP_EOL . $store['street']; + $txn_details .= PHP_EOL . $store['zip'] . ' ' . $store['city']; + $country_name = $db->Execute("select countries_name from " . TABLE_COUNTRIES . " where countries_iso_code_2 = '" . $store['country_code'] . "'"); + if ($country_name->RecordCount()) { + $txn_details .= PHP_EOL . $country_name->fields['countries_name']; + } + + $txn_details .= 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 = 0; + if(isset($response['instalment']['currency'])){ + $amount = $currencies->format($response['instalment']['cycle_amount']/100, false, $response['instalment']['currency']); + }else{ + $amount = $currencies->format($response['instalment']['cycle_amount']/100, false, $response['transaction']['currency']); + } + + if ($response['transaction']['status'] == 'CONFIRMED') { + $txn_details .= 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. self::format_date($response['instalment']['next_cycle_date']). PHP_EOL; + } + } + + return $txn_details; + } + + /** + * Get shop order status id + * + * @param $transaction_status + * @param $payment_name + * + * @return $order_status_id + */ + public static function getOrderStatus($transaction_status, $payment_name) + { + $order_status_id = ''; + + 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_details = []; + $payment_type = !empty($response['transaction']['payment_type']) ? $response['transaction']['payment_type'] : ''; + $payment_status['orders_status'] = $status_update['orders_status_id'] = self::getOrderStatus($response['transaction']['status'], $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'], + 'payment_type' => $payment_type, + 'status' => $response['transaction']['status'] + ); + + if (!empty($response['instalment']) && $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 (!empty($response['transaction']['bank_details'])) { + $payment_details = $response['transaction']['bank_details']; + + if (isset($response['transaction']['due_date'])) { + $payment_details['novalnet_due_date'] = $response['transaction']['due_date']; + } + } elseif (!empty($response['transaction']['nearest_stores'])) { + $payment_details['nearest_stores'] = $response['transaction']['nearest_stores']; + $_SESSION['novalnet_checkout_js'] = $response['transaction']['checkout_js']; + $_SESSION['novalnet_checkout_token'] = $response['transaction']['checkout_token']; + } elseif (!empty($response['transaction']['payment_data']['token']) && isset($_SESSION['nn_booking_details']->create_token) && $_SESSION['nn_booking_details']->create_token == '1') { + $payment_details = $response['transaction']['payment_data']; + if ($_SESSION['nn_booking_details']->payment_action == 'zero_amount') { + $payment_details['zero_amount_booking'] = 1; + } + } elseif (!empty($response['transaction']['payment_data']['token']) + && !empty($_SESSION['nn_booking_details']->payment_action) + && $_SESSION['nn_booking_details']->payment_action == 'zero_amount' + ) { + $payment_details = array( + 'token' => $response['transaction']['payment_data']['token'], + 'zero_amount_booking' => 1 + ); + } + $novalnet_transaction_details['payment_details'] = !empty($payment_details) ? json_encode($payment_details) : '{}'; + zen_db_perform(TABLE_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 '{}'; + } + $instalment = $response['instalment']; + if (isset($instalment['cycle_dates'])) { + $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 (isset($cycles[$cycle + 1])) { + $cycle_details[$cycle - 1]['next_instalment_date'] = $cycles[$cycle + 1]; + }else{ + $cycle_details[$cycle - 1]['next_instalment_date'] = ""; + } + $cycle_details[$cycle -1 ]['status'] = 'Pending'; + if (!empty($instalment['cycles_executed']) && $cycle == $instalment['cycles_executed']) { + $cycle_details[$cycle -1 ]['reference_tid'] = !empty($instalment['tid']) ? $instalment['tid'] : (!empty($response['transaction']['tid']) ? $response['transaction']['tid'] : ''); + $cycle_details[$cycle -1 ]['status'] = 'Paid'; + $cycle_details[$cycle -1 ]['paid_date'] = date('d.m.Y H:i:s'); + } + $cycle_details[$cycle -1 ]['instalment_cycle_amount'] = ($cycle == $total_cycles)?$last_cycle_amount : $instalment['cycle_amount']; + $cycle_details[$cycle -1 ]['instalment_cycle_amount_orginal_amount'] = ($cycle == $total_cycles)?$last_cycle_amount : $instalment['cycle_amount']; + } + return (!empty($cycle_details) ? 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) + { + $params = [ + 'transaction' => [ + 'tid' => $_SESSION['nn_response']['transaction']['tid'], + 'order_no' => $order_no, + ], + ]; + + self::getCustomData($params); + self::sendRequest($params, self::getActionEndpoint('transaction_update')); + + if (isset($_SESSION['nn_response'])) { + unset($_SESSION['nn_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_ACCESS_KEY)) { + $checksum = hash('sha256', $data['tid'] . $_SESSION['nn_txn_secret'] . $data['status'] . strrev(MODULE_PAYMENT_NOVALNET_ACCESS_KEY)); + if ($checksum == $data['checksum']) { + return true; + } + } + return false; + } + + /** + * Get payment response text + * + * @param array $response + * + * @return 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']; + } + + 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 $params + */ + public static function getMerchantData(&$params) + { + $params['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 : '', + ]; + } + + /** + * Get request header + */ + public static function getHeadersParam($access_key = null) + { + $access_key = !empty($access_key) ? $access_key : MODULE_PAYMENT_NOVALNET_ACCESS_KEY; + return [ + 'Content-Type:application/json', + 'Charset:utf-8', + 'Accept:application/json', + 'X-NN-Access-Key:' . base64_encode($access_key) + ]; + } + + /** + * 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, $order_no = '') + { + $txn_details = ''; + + if ($response['result']['status'] == 'SUCCESS') { + $txn_details = self::getTransactionDetails($response); + $payment_type = !empty($response['transaction']['payment_type']) ? $response['transaction']['payment_type'] : ''; + + // Invoice payments + if (!empty($response['transaction']['bank_details']) && $response['transaction']['status_code'] != 75) { + $txn_details .= self::getBankDetails($response); + } + + // Cashpayment + if (!empty($response['transaction']['nearest_stores'])) { + $txn_details .= self::getNearestStoreDetails($response); + } + + if (!empty($response['instalment']) && ($response['transaction']['status'] == 'CONFIRMED')) { + $txn_details .= self::getInstalmentDetails($response); + } + } + return $txn_details; + } + + /** + * Validate customer email + * + * @param $emails + * + * @return boolean + */ + public static function validateEmail($emails) + { + include_once(DIR_FS_CATALOG. 'includes/functions/functions_email.php'); + $email = explode(',', $emails); + + foreach ($email as $value) { + if (!zen_validate_email($value)) { + return ''; + } + + return $value; + } + } + + /** + * Paypal sheet details + * + * @return $params + */ + public static function paypal_sheet_details(&$params) + { + global $order, $db; + $currency_value = 0; + $currency_value = ($order->info['currency_value'] != 0) ? ($order->info['currency_value']) : ''; + + $coupon_amount = $db->Execute("select coupon_amount from ".TABLE_COUPONS." where coupon_code = '".$order->info['coupon_code']."'"); + $nn_total = 0; + + foreach ($order->products as $products) { + $attributes = ''; + if (!empty($products['attributes'])) { + foreach ($products['attributes'] as $attr => $value) { + $attributes .= ', ' . $value['option'] . ':' . $value['value']; + } + } + + $product_type = ($products['products_weight'] != 0) ? 'physical' : 'digital'; + $productId = !empty($products['id']) ? explode(":", $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'] . $attributes, + 'price' => !empty($currency_value) ? (string) ((round((float) ($products['final_price'] * $currency_value), 2)) * 100) : (string) ((round((float) ($products['final_price']), 2)) * 100), + 'quantity' => $products['qty'], + 'description' => !empty($product_desc->fields['products_description']) ? $product_desc->fields['products_description'] : '', + 'category' => $product_type, + ); + $nn_total += (string) ((round((float) ($products['final_price'] * $products['qty']), 2)) * 100); + } + + if (!empty($order->info['coupon_code']) || !empty($order->info['coupon_amount'])) { + $discount_amount = 0; + $discount_amount = !empty($order->info['coupon_amount']) ? ((string) ((round((float) $order->info['coupon_amount'], 2)) * 100)) : ((string) ((round((float) ($coupon_amount->fields['coupon_amount']), 2)) * 100)); + $params['cart_info']['line_items'][] = array( + 'name' => 'Discount coupon', + 'price' => '-'.$discount_amount, + 'quantity' => 1, + ); + $nn_total -= $discount_amount; + } + if ($_SESSION['cot_gv'] != 0.00) { + $params['cart_info']['line_items'][] = array( + 'name' => 'Gift certificate', + 'price' => '-'.(string) ((round((float) $_SESSION['cot_gv'], 2)) * 100), + 'quantity' => 1, + ); + $nn_total -= (string) ((round((float) $_SESSION['cot_gv'], 2)) * 100); + } + + $params['cart_info']['items_tax_price'] = !empty($currency_value) ? (string) ((round((float) (($order->info['tax']) * $currency_value), 2)) * 100) : (string) ((round((float) (($order->info['tax'])), 2)) * 100); + $nn_total += $params['cart_info']['items_tax_price']; + $params['cart_info']['items_shipping_price'] = !empty($currency_value) ? (string) ((round((float) ($order->info['shipping_cost'] * $currency_value), 2)) * 100) : (string) ((round((float) ($order->info['shipping_cost'] * $currency_value), 2)) * 100); + $nn_total += $params['cart_info']['items_shipping_price']; + $nn_diff_amount = $params['transaction']['amount'] - $nn_total; + + if (!empty($nn_diff_amount)) { + $params['cart_info']['items_tax_price'] = $nn_diff_amount + $params['cart_info']['items_tax_price']; + } + + } + + + /** + * Get order status ID. + * + * @return $status_id + */ + public static function getOrderStatusId() + { + global $db; + $status_id = ''; + $order_status = $db->Execute("SELECT orders_status_name, orders_status_id FROM ".TABLE_ORDERS_STATUS." WHERE orders_status_name LIKE '%cancel%'"); + if ($order_status->link->affected_rows > 0) { + $status_id = $order_status->fields['orders_status_id']; + } + + return $status_id; + } + + /** + * send payment confirmation mail to customer. + * + * @param $comments, $order_no + * + * @return boolean + */ + public static function sendPaymentConfirmationMail($comments, $order_no) + { + global $db; + global $zcDate; + $customer_info = ''; + $customer_info = $db->Execute("SELECT * FROM ".TABLE_ORDERS." WHERE orders_id = '".$order_no."'"); + $customer_details = $customer_info->fields; + $customer_name = $customer_details['customers_name']; + $email_subject = sprintf(MODULE_PAYMENT_NOVALNET_ORDER_MAIL_SUBJECT, $order_no, STORE_NAME); + $email_content = sprintf(MODULE_PAYMENT_NOVALNET_ORDER_MAIL_MESSAGE, STORE_NAME). PHP_EOL. MODULE_PAYMENT_NOVALNET_CUSTOMER_SALUTATION. ''. $customer_details['customers_name'].PHP_EOL .sprintf(MODULE_PAYMENT_NOVALNET_ORDER_NUMBER, $order_no) . PHP_EOL. sprintf(MODULE_PAYMENT_NOVALNET_ORDER_MAIL_DATE, $zcDate->output(DATE_FORMAT_LONG)). PHP_EOL. MODULE_PAYMENT_NOVALNET_ORDER_CONFIRMATION .zen_href_link(FILENAME_ACCOUNT_HISTORY_INFO, 'order_id=' . $order_no, 'SSL', false) . PHP_EOL . nl2br($comments); + $email_content .= PHP_EOL.MODULE_PAYMENT_NOVALNET_DELIVERY_ADDRESS. PHP_EOL. $customer_details['delivery_name'] .PHP_EOL . $customer_details['delivery_street_address'] . PHP_EOL. $customer_details['delivery_postcode'] . PHP_EOL . $customer_details['delivery_city'] . PHP_EOL . $customer_details['delivery_country'] . PHP_EOL; + $email_content .= PHP_EOL .MODULE_PAYMENT_NOVALNET_BILLING_ADDRESS. PHP_EOL. $customer_details['billing_name'] .PHP_EOL . $customer_details['billing_street_address'] . PHP_EOL. $customer_details['billing_postcode'] . PHP_EOL . $customer_details['billing_city'] . PHP_EOL . $customer_details['billing_country'] . PHP_EOL; + zen_mail($customer_name, $customer_details['customers_email_address'], $email_subject, str_replace('
', PHP_EOL, $email_content), '', '', array(), '', '', STORE_NAME, EMAIL_FROM); + } + + /** + * Update order status in the shop + * + * @param integer $order_id + * @param string $order_status + * @param string $message + */ + public static function novalnetUpdateOrderStatus($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/includes/modules/payment/novalnet/novalnet_admin_notification.php b/includes/modules/payment/novalnet/novalnet_admin_notification.php new file mode 100644 index 0000000..78449c7 --- /dev/null +++ b/includes/modules/payment/novalnet/novalnet_admin_notification.php @@ -0,0 +1,117 @@ +'; + $nn_html = ''; + $request = $_REQUEST; + +if (method_exists($this, '_doRefund')) { + // Refund process + if (isRefund($transaction_details->fields)) { + $avail_refund = $refund_value = 0; + $avail_refund = (!empty($transaction_details->fields['callback_amount'])) ? $transaction_details->fields['callback_amount'] : $transaction_details->fields['amount']; + $refund_value = (!empty($transaction_details->fields['refund_amount'])) ? ($avail_refund - $transaction_details->fields['refund_amount']) : $avail_refund; + + $outputRefund .= ''; + $outputRefund .= $nn_html; + $outputRefund .= '
'."\n"; + $outputRefund .= zen_draw_form('novalnet_trans_refund', FILENAME_ORDERS, zen_get_all_get_params(array('action')) . 'action=doRefund', 'post', '', true) ; + $outputRefund .= $nn_script ; + $outputRefund .= $nn_html.''; + $outputRefund .= ''; + $outputRefund .= ''; + $outputRefund .= zen_draw_hidden_field('oID', $request['oID']); + $outputRefund .= zen_draw_hidden_field('nn_amount_error', MODULE_PAYMENT_NOVALNET_AMOUNT_ERROR_MESSAGE); + $outputRefund .= zen_draw_hidden_field('nn_refund_amount_confirm', MODULE_PAYMENT_NOVALNET_PAYMENT_REFUND_CONFIRM); + $outputRefund .= ''; + $outputRefund .= ''; + $outputRefund .= ''; + $outputRefund .= ''; + $outputRefund .= ''; + $outputRefund .='
'; + $outputRefund .= '
'.MODULE_PAYMENT_NOVALNET_REFUND_AMT_TITLE . ''; + $outputRefund .= zen_draw_input_field('refund_trans_amount', $refund_value, 'id="refund_trans_amount" onkeypress="isNumber(event)" style="width:100px;margin:0 0 0 2%" autocomplete="off"') . MODULE_PAYMENT_NOVALNET_AMOUNT_EX . '
'.MODULE_PAYMENT_NOVALNET_REFUND_REASON_TITLE . '' . zen_draw_input_field('refund_reason', '', 'id="refund_reason" style="margin:0 0 0 2%;" autocomplete="off"').'
'.zen_draw_input_field('nn_refund_confirm', html_entity_decode(MODULE_PAYMENT_NOVALNET_CONFIRM_TEXT), 'class="btn btn-primary" onclick="return refund_amount_validation();" style="float:left"', false, 'submit').'
'."\n"; + } +} + +// On-hold process +if (method_exists($this, '_doVoid') && method_exists($this, '_doCapt')) { + if ($transaction_details->fields['status'] == 'ON_HOLD') { + $options = array ( + array('id'=> '', 'text' => MODULE_PAYMENT_NOVALNET_SELECT_STATUS_OPTION), + array('id'=> 'CONFIRM', 'text' => MODULE_PAYMENT_NOVALNET_CONFIRM_TEXT), + array('id'=> 'CANCEL', 'text' => MODULE_PAYMENT_NOVALNET_CANCEL_TEXT), + ); + + $outputVoidCapt .= ''; + $outputVoidCapt .= $nn_html; + $outputVoidCapt .= '
'."\n"; + $outputVoidCapt .= zen_draw_form('novalnet_status_change', FILENAME_ORDERS, zen_get_all_get_params(array('action')), 'post', 'id="novalnet_status_change"', true) ; + $outputVoidCapt .= $nn_script ; + $outputVoidCapt .= $nn_html.'
'; + $outputVoidCapt .= ''; + $outputVoidCapt .= zen_draw_hidden_field('oID', $request['oID']); + $outputVoidCapt .= zen_draw_hidden_field('nn_capture_update', MODULE_PAYMENT_NOVALNET_PAYMENT_CAPTURE_CONFIRM); + $outputVoidCapt .= zen_draw_hidden_field('nn_void_update', MODULE_PAYMENT_NOVALNET_PAYMENT_VOID_CONFIRM); + $outputVoidCapt .= zen_draw_hidden_field('nn_select_status', MODULE_PAYMENT_NOVALNET_SELECT_STATUS_TEXT); + $outputVoidCapt .= ''; + $outputVoidCapt .= ''; + $outputVoidCapt .= ''; + $outputVoidCapt .='
'; + $outputVoidCapt .= '
'.MODULE_PAYMENT_NOVALNET_SELECT_STATUS_TEXT; + $outputVoidCapt .= ''; + $outputVoidCapt .= zen_draw_pull_down_menu('trans_status', $options, '', 'id="trans_status"').'
'.zen_draw_input_field('nn_manage_confirm', html_entity_decode(MODULE_PAYMENT_NOVALNET_CONFIRM_TEXT), 'class="btn btn-primary" onclick="return void_capture_status();" style="float:left"', false, 'submit').'
'."\n"; + } +} + +// prepare output based on suitable content components +$output = ''; + +if (defined('MODULE_PAYMENT_NOVALNET_STATUS') && MODULE_PAYMENT_NOVALNET_STATUS == 'True') { + + if (method_exists($this, '_doRefund')) { + $output .= $outputRefund; + } + + if (method_exists($this, '_doVoid') && method_exists($this, '_doCapt')) { + $output .= $outputVoidCapt; + } +} + +$output .= ''; + + +/** +* Check whether refund block shown or not in admin panel +* +* @param array $txn_details +* +* @return boolean +*/ +function isRefund($txn_details) { + if (($txn_details['amount'] > 0) && + (($txn_details['status'] == 'CONFIRMED' && ($txn_details['amount'] != $txn_details['refund_amount'])) || + ($txn_details['status']=='PENDING' && + ($txn_details['amount'] > $txn_details['refund_amount']) && + in_array($txn_details['payment_type'], array('INVOICE','PREPAYMENT','CASHPAYMENT'))) + ) && + !in_array($txn_details['payment_type'], array('MULTIBANCO','INSTALMENT_INVOICE','INSTALMENT_DIRECT_DEBIT_SEPA'))) { + return true; + + } else { + return false; + } +} diff --git a/includes/modules/payment/novalnet/novalnet_auto_config.js b/includes/modules/payment/novalnet/novalnet_auto_config.js new file mode 100644 index 0000000..a646efa --- /dev/null +++ b/includes/modules/payment/novalnet/novalnet_auto_config.js @@ -0,0 +1,158 @@ +/** + * 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 + * + */ + +/** + * Auto configuration process + */ +jQuery(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_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('input[name="configuration[MODULE_PAYMENT_NOVALNET_CALLBACK_URL]"]').attr('readonly',true); + 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, #novalnet_access_key').closest('form').submit(function (event) { + if (jQuery('#novalnet_signature').val() == '') { + event.preventDefault(); + alert(jQuery('#merchant_credentials_error').val()); + } + }); + + if (jQuery('#novalnet_webhook_url').val() != '' && jQuery('#novalnet_webhook_url').val() != undefined) { + jQuery('#webhook_url_button').on('click', function () { + let webhook_url = jQuery.trim(jQuery('#novalnet_webhook_url').val()), + regex = /(http|https):\/\/(\w+:{0,1}\w*)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%!\-\/]))?/; + + if (webhook_url != '' && regex.test(webhook_url)) { + if (confirm(jQuery('#nn_webhook_alert').val())) { + configure_webhook(); + return true; + } else { + return false; + } + } 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() + { + let signature = jQuery.trim(jQuery('#novalnet_signature').val()), + access_key = jQuery.trim(jQuery('#novalnet_access_key').val()), + data_to_send = {'action': 'merchant_details', 'signature': signature, 'access_key': access_key, 'lang': jQuery('#nn_language').val()}; + + do_ajax_call(data_to_send); + return true; + } + + /** Configure webhook URL in Novalnet system */ + function configure_webhook() + { + let signature = jQuery.trim(jQuery('#novalnet_signature').val()), + access_key = jQuery.trim(jQuery('#novalnet_access_key').val()), + webhook_url = jQuery.trim(jQuery('#novalnet_webhook_url').val()); + + if (signature == '' || access_key == '') { + alert(jQuery('#nn_key_error').val()); + clear_basic_params(); + return false; + } + + let data_to_send = {'action': 'webhook_configure', 'signature': signature, 'access_key': access_key, 'webhook_url': webhook_url, 'lang': jQuery('#nn_language').val()}; + do_ajax_call(data_to_send); + return true; + } + + /** Handle the response */ + function process_result(result) + { + let saved_tariff_id = jQuery('#novalnet_tariff_id').val(); + jQuery('#novalnet_tariff_id').replaceWith(''); + let tariff = result.merchant.tariff; + if (tariff != undefined) { + jQuery.each(tariff, function ( index, value ) { + let tariff_val = index; + jQuery('#novalnet_tariff_id').append(jQuery('