PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.8.16
VikBooking Hotel Booking Engine & PMS v1.8.16
1.8.16 1.8.15 1.8.14 1.8.13 1.8.12 1.8.11 1.8.10 1.8.9 1.8.6 1.8.7 1.8.8 trunk 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 All 37 releases
← All changes | admin/helpers/widgets/virtual_terminal.php +312 -72 1.7.1 → 1.8.16 View file →
@@ -109,10 +109,10 @@
109 109 VBOHttpDocument::getInstance()->close(404, JText::translate('VBPEDITBUSYONE'));
110 110 }
111 111 }
112 112
113 - // check if direct charge is supported by the current payment processor
114 - if (!$this->getPaymentProcessor($booking_info)) {
113 + // ensure a valid payment processor is assigned to the reservation
114 + if (!($processor = $this->getPaymentProcessor($booking_info))) {
115 115 // unable to proceed due to unsupported transaction
116 116 return [
117 117 'html' => '<p class="err">' . JText::translate('VBO_PAY_PROCESS_NO_DIRECT_CHARGE') . '</p>',
118 118 ];
@@ -117,10 +117,14 @@
117 117 'html' => '<p class="err">' . JText::translate('VBO_PAY_PROCESS_NO_DIRECT_CHARGE') . '</p>',
118 118 ];
119 119 }
120 120
121 + // tell whether off-session capturing is supported
122 + $off_session_capturing = method_exists($processor, 'isOffSessionCaptureSupported') && $processor->isOffSessionCaptureSupported();
123 + $off_session_tn_data = $off_session_capturing ? VBOModelReservation::getInstance($booking_info, true)->getOffSessionTransactionData() : [];
124 +
121 125 // make sure the permissions are met
122 - if ($this->vcm_exists && !JFactory::getUser()->authorise('core.admin', 'com_vikchannelmanager')) {
126 + if ($this->vcm_exists && !JFactory::getUser()->authorise('core.admin', 'com_vikchannelmanager') && !$off_session_tn_data) {
123 127 // insufficient permissions to handle CC details
124 128 return [
125 129 'html' => '<p class="err">' . JText::translate('JERROR_ALERTNOAUTHOR') . '</p>',
126 130 ];
@@ -125,9 +129,9 @@
125 129 'html' => '<p class="err">' . JText::translate('JERROR_ALERTNOAUTHOR') . '</p>',
126 130 ];
127 131 }
128 132
129 - // get the reservation credit card value pairs
133 + // get the reservation credit card value pairs, if any
130 134 $cc_value_pairs = VBOModelReservation::getInstance($booking_info, true)->getCardValuePairs();
131 135
132 136 // currency code
133 137 $currency_code = !empty($booking_info['chcurrency']) ? $booking_info['chcurrency'] : VikBooking::getCurrencyName();
@@ -160,8 +164,9 @@
160 164 /**
161 165 * Consider calculating an outstanding balance in case of previous payments.
162 166 *
163 167 * @since 1.16.7 (J) - 1.6.7 (WP)
168 + * @since 1.18.0 (J) - 1.8.0 (WP) added support to amount raw for off-session capture.
164 169 */
165 170 $default_total = $booking_info['total'];
166 171 if ($booking_info['totpaid'] > 0 && $booking_info['totpaid'] < $booking_info['total']) {
167 172 // default to the outstanding balance
@@ -167,8 +172,16 @@
167 172 // default to the outstanding balance
168 173 $default_total = $booking_info['total'] - $booking_info['totpaid'];
169 174 }
170 175
176 + if (!$booking_info['totpaid'] && $off_session_tn_data && ($off_session_tn_data[0]->amount_raw ?? null)) {
177 + // default to the payable amount at the time of payment, unless empty
178 + $default_total = ((float) $off_session_tn_data[0]->amount_raw) ?: $booking_info['total'];
179 + }
180 +
181 + // tell whether we only have an off-session transaction to capture
182 + $only_off_session = $off_session_tn_data && !$cc_value_pairs;
183 +
171 184 // start output buffering
172 185 ob_start();
173 186
174 187 ?>
@@ -189,48 +202,80 @@
189 202 </div>
190 203 </div>
191 204 </div>
192 205
193 - <div class="vbo-vterminal-cc-row-group vbo-vterminal-cc-row-group-cardholder">
194 - <div class="vbo-vterminal-cc-row vbo-vterminal-cc-row-cardholder">
195 - <div class="vbo-vterminal-cc-lbl"><?php echo JText::translate('VBISNOMINATIVE'); ?></div>
206 + <?php
207 + if ($off_session_tn_data) {
208 + // when an off-session transaction is available, display the capture button
209 + ?>
210 + <div class="vbo-vterminal-cc-row-group vbo-vterminal-cc-row-group-submit" data-tn-type="off-session">
211 + <div class="vbo-vterminal-cc-row vbo-vterminal-cc-row-submit" data-tn-type="off-session">
196 212 <div class="vbo-vterminal-cc-val">
197 - <input type="text" autocomplete="off" value="<?php echo isset($known_tn_vals['name']) ? JHtml::fetch('esc_attr', $cc_value_pairs['name']) : ''; ?>" data-vt-cc-field="cardholder" />
213 + <button type="button" class="btn vbo-config-btn" onclick="vboWidgetVTerminalOffSessionCharge('<?php echo $wrapper; ?>');"><?php VikBookingIcons::e('credit-card'); ?> <?php echo JText::translate('VBO_CHARGE_AUTHORIZED_CARD'); ?></button>
198 214 </div>
199 215 </div>
200 216 </div>
217 + <?php
218 + }
219 + ?>
201 220
202 - <div class="vbo-vterminal-cc-row-group vbo-vterminal-cc-row-group-ccpan">
203 - <div class="vbo-vterminal-cc-row vbo-vterminal-cc-row-ccpan">
204 - <div class="vbo-vterminal-cc-lbl"><?php echo JText::translate('VBO_CC_NUMBER'); ?></div>
205 - <div class="vbo-vterminal-cc-val vbo-vterminal-cc-val-withlogo">
206 - <input type="text" autocomplete="off" value="<?php echo isset($known_tn_vals['card_number']) ? JHtml::fetch('esc_attr', $cc_value_pairs['card_number']) : ''; ?>" data-vt-cc-field="card_number" />
207 - <span class="vbo-vterminal-cc-type-logo"></span>
221 + <div class="vbo-vterminal-cc-group-cardwrap"<?php echo $off_session_tn_data ? ' data-has-offsession="1"' : ''; ?>>
222 +
223 + <?php
224 + if ($off_session_tn_data) {
225 + // add a label for using the card
226 + ?>
227 + <div class="vbo-vterminal-cc-row-group vbo-vterminal-cc-row-group-usecard">
228 + <div class="vbo-vterminal-cc-row vbo-vterminal-cc-row-usecard">
229 + <div class="vbo-vterminal-cc-lbl"><?php echo JText::translate('VBO_CREDIT_CARD') . ($only_off_session ? ' - ' . JText::translate('VBMAINPAYMENTSNEW') : ''); ?></div>
208 230 </div>
209 231 </div>
210 - </div>
232 + <?php
233 + }
234 + ?>
211 235
212 - <div class="vbo-vterminal-cc-row-group vbo-vterminal-cc-row-group-ccextra">
213 - <div class="vbo-vterminal-cc-row vbo-vterminal-cc-row-ccexpiry">
214 - <div class="vbo-vterminal-cc-lbl"><?php echo JText::translate('VBO_CC_EXPIRY_DT'); ?></div>
215 - <div class="vbo-vterminal-cc-val">
216 - <input type="text" autocomplete="off" placeholder="MM/YYYY" value="<?php echo isset($known_tn_vals['expiration_date']) ? JHtml::fetch('esc_attr', $cc_value_pairs['expiration_date']) : ''; ?>" data-vt-cc-field="expiry" />
236 + <div class="vbo-vterminal-cc-row-group vbo-vterminal-cc-row-group-cardholder">
237 + <div class="vbo-vterminal-cc-row vbo-vterminal-cc-row-cardholder">
238 + <div class="vbo-vterminal-cc-lbl"><?php echo JText::translate('VBISNOMINATIVE'); ?></div>
239 + <div class="vbo-vterminal-cc-val">
240 + <input type="text" autocomplete="off" value="<?php echo isset($known_tn_vals['name']) ? JHtml::fetch('esc_attr', $cc_value_pairs['name']) : ''; ?>" data-vt-cc-field="cardholder" />
241 + </div>
217 242 </div>
218 243 </div>
219 - <div class="vbo-vterminal-cc-row vbo-vterminal-cc-row-cvc">
220 - <div class="vbo-vterminal-cc-lbl"><?php echo JText::translate('VBO_CC_CVV'); ?></div>
221 - <div class="vbo-vterminal-cc-val">
222 - <input type="text" autocomplete="off" value="<?php echo isset($known_tn_vals['cvv']) ? JHtml::fetch('esc_attr', $cc_value_pairs['cvv']) : ''; ?>" data-vt-cc-field="cvv" />
244 +
245 + <div class="vbo-vterminal-cc-row-group vbo-vterminal-cc-row-group-ccpan">
246 + <div class="vbo-vterminal-cc-row vbo-vterminal-cc-row-ccpan">
247 + <div class="vbo-vterminal-cc-lbl"><?php echo JText::translate('VBO_CC_NUMBER'); ?></div>
248 + <div class="vbo-vterminal-cc-val vbo-vterminal-cc-val-withlogo">
249 + <input type="text" autocomplete="off" value="<?php echo isset($known_tn_vals['card_number']) ? JHtml::fetch('esc_attr', $cc_value_pairs['card_number']) : ''; ?>" data-vt-cc-field="card_number" />
250 + <span class="vbo-vterminal-cc-type-logo"></span>
251 + </div>
223 252 </div>
224 253 </div>
225 - </div>
226 254
227 - <div class="vbo-vterminal-cc-row-group vbo-vterminal-cc-row-group-submit">
228 - <div class="vbo-vterminal-cc-row vbo-vterminal-cc-row-submit">
229 - <div class="vbo-vterminal-cc-val">
230 - <button type="button" class="btn vbo-config-btn" onclick="vboWidgetVTerminalChargeCard('<?php echo $wrapper; ?>');"><?php VikBookingIcons::e('credit-card'); ?> <?php echo JText::translate('VBO_CC_DOCHARGE'); ?></button>
255 + <div class="vbo-vterminal-cc-row-group vbo-vterminal-cc-row-group-ccextra">
256 + <div class="vbo-vterminal-cc-row vbo-vterminal-cc-row-ccexpiry">
257 + <div class="vbo-vterminal-cc-lbl"><?php echo JText::translate('VBO_CC_EXPIRY_DT'); ?></div>
258 + <div class="vbo-vterminal-cc-val">
259 + <input type="text" autocomplete="off" placeholder="MM/YYYY" value="<?php echo isset($known_tn_vals['expiration_date']) ? JHtml::fetch('esc_attr', $cc_value_pairs['expiration_date']) : ''; ?>" data-vt-cc-field="expiry" />
260 + </div>
231 261 </div>
262 + <div class="vbo-vterminal-cc-row vbo-vterminal-cc-row-cvc">
263 + <div class="vbo-vterminal-cc-lbl"><?php echo JText::translate('VBO_CC_CVV'); ?></div>
264 + <div class="vbo-vterminal-cc-val">
265 + <input type="text" autocomplete="off" value="<?php echo isset($known_tn_vals['cvv']) ? JHtml::fetch('esc_attr', $cc_value_pairs['cvv']) : ''; ?>" data-vt-cc-field="cvv" />
266 + </div>
267 + </div>
232 268 </div>
269 +
270 + <div class="vbo-vterminal-cc-row-group vbo-vterminal-cc-row-group-submit" data-tn-type="direct-charge">
271 + <div class="vbo-vterminal-cc-row vbo-vterminal-cc-row-submit" data-tn-type="direct-charge">
272 + <div class="vbo-vterminal-cc-val">
273 + <button type="button" class="btn vbo-config-btn" onclick="vboWidgetVTerminalChargeCard('<?php echo $wrapper; ?>');"><?php VikBookingIcons::e('credit-card'); ?> <?php echo JText::translate('VBO_CC_DOCHARGE'); ?></button>
274 + </div>
275 + </div>
276 + </div>
277 +
233 278 </div>
234 279
235 280 <?php
236 281 // print hidden transaction values, if any
@@ -447,9 +492,9 @@
447 492 // update booking details
448 493 $dbo = JFactory::getDbo();
449 494
450 495 // get the amount paid
451 - $tn_amount = isset($array_result['tot_paid']) ? (float)$array_result['tot_paid'] : null;
496 + $tn_amount = isset($array_result['tot_paid']) ? (float) $array_result['tot_paid'] : null;
452 497
453 498 // get the log string, if any
454 499 $tn_log = !empty($array_result['log']) ? $array_result['log'] : '';
455 500
@@ -502,12 +547,12 @@
502 547 if ($tn_data && isset($array_result['tot_fees']) && $array_result['tot_fees']) {
503 548 // check event data payload to store
504 549 if (is_array($tn_data)) {
505 550 // set key
506 - $tn_data['processing_fees'] = (float)$array_result['tot_fees'];
551 + $tn_data['processing_fees'] = (float) $array_result['tot_fees'];
507 552 } elseif (is_object($tn_data)) {
508 553 // set property
509 - $tn_data->processing_fees = (float)$array_result['tot_fees'];
554 + $tn_data->processing_fees = (float) $array_result['tot_fees'];
510 555 }
511 556 }
512 557
513 558 // current admin-user
@@ -523,8 +568,157 @@
523 568 ];
524 569 }
525 570
526 571 /**
572 + * Custom method for this widget only to debit a credit card off-session.
573 + *
574 + * @return ?array
575 + *
576 + * @since 1.18.0 (J) - 1.8.0 (WP)
577 + */
578 + public function doOffSessionCapture()
579 + {
580 + $app = JFactory::getApplication();
581 +
582 + $wrapper = $app->input->getString('wrapper', '');
583 + $bid = $app->input->getUInt('bid', 0);
584 + $amount = $app->input->getFloat('amount', 0);
585 + $currency = $app->input->getString('currency', '');
586 +
587 + if (!$bid || !$amount) {
588 + // booking ID and amount are mandatory
589 + VBOHttpDocument::getInstance()->close(500, JText::translate('VBPEDITBUSYONE'));
590 + }
591 +
592 + // get booking details
593 + $booking_info = VikBooking::getBookingInfoFromID($bid);
594 +
595 + if (!$booking_info) {
596 + // booking record not found
597 + VBOHttpDocument::getInstance()->close(404, JText::translate('VBPEDITBUSYONE'));
598 + }
599 +
600 + // collect the previous transaction data list
601 + $tn_data = VBOModelReservation::getInstance($booking_info, true)->getOffSessionTransactionData();
602 + if (!$tn_data) {
603 + // previous transaction data not found
604 + VBOHttpDocument::getInstance()->close(400, 'Missing previous transaction data');
605 + }
606 +
607 + // set the amount to capture and transaction data before accessing the payment processor
608 + $booking_info['total_to_pay'] = $amount;
609 + $booking_info['tn_currency'] = $currency;
610 + $booking_info['transaction'] = $tn_data[0];
611 +
612 + // get the eligible payment processor
613 + $processor = $this->getPaymentProcessor($booking_info);
614 +
615 + if (!$processor) {
616 + VBOHttpDocument::getInstance()->close(500, JText::translate('VBO_PAY_PROCESS_NO_DIRECT_CHARGE'));
617 + }
618 +
619 + // default transaction response
620 + $array_result = [
621 + 'verified' => 0,
622 + ];
623 +
624 + try {
625 + // perform the transaction
626 + $array_result = $processor->offSessionCapture();
627 + } catch (Exception $e) {
628 + // set error message
629 + $array_result['log'] = sprintf(JText::translate('VBO_CC_TN_ERROR') . " \n%s", $e->getMessage());
630 + }
631 +
632 + if ($array_result['verified'] != 1) {
633 + // erroneous response
634 + if (!empty($array_result['log']) && is_string($array_result['log'])) {
635 + VBOHttpDocument::getInstance()->close(500, $array_result['log']);
636 + } else {
637 + VBOHttpDocument::getInstance()->close(500, 'Operation failed');
638 + }
639 + }
640 +
641 + // valid transaction response!
642 +
643 + // update booking details
644 + $dbo = JFactory::getDbo();
645 +
646 + // get the amount paid
647 + $tn_amount = isset($array_result['tot_paid']) ? (float) $array_result['tot_paid'] : null;
648 +
649 + // get the log string, if any
650 + $tn_log = !empty($array_result['log']) ? $array_result['log'] : '';
651 +
652 + // update record
653 + $upd_record = new stdClass;
654 + $upd_record->id = $booking_info['id'];
655 + if ($tn_amount) {
656 + // update amount paid
657 + $upd_record->totpaid = $booking_info['totpaid'] + $tn_amount;
658 + // update payable amount (if needed)
659 + $new_payable = $booking_info['payable'] - $tn_amount;
660 + $new_payable = $new_payable < 0 ? 0 : $new_payable;
661 + $upd_record->payable = $new_payable;
662 + }
663 + if ($tn_log) {
664 + $upd_record->paymentlog = $booking_info['paymentlog'] . "\n\n" . date('c') . "\n" . $tn_log;
665 + }
666 + $upd_record->paymcount = ((int) $booking_info['paymcount'] + 1);
667 +
668 + // update reservation record
669 + $dbo->updateObject('#__vikbooking_orders', $upd_record, 'id');
670 +
671 + // payment processor name
672 + $pay_process_name = $this->payment_method ? $this->payment_method['name'] : 'CC Manual Charge (Off-Session)';
673 +
674 + // handle transaction data to eventually support a later transaction of type refund
675 + $tn_data = isset($array_result['transaction']) ? $array_result['transaction'] : null;
676 + if ($tn_amount) {
677 + // check event data payload to store
678 + if (is_array($tn_data)) {
679 + // set key
680 + $tn_data['amount_paid'] = $tn_amount;
681 + } elseif (is_object($tn_data)) {
682 + // set property
683 + $tn_data->amount_paid = $tn_amount;
684 + } elseif (!$tn_data) {
685 + // build an array (we add the payment name because we know there is no other transaction data)
686 + $tn_data = [
687 + 'amount_paid' => $tn_amount,
688 + 'payment_method' => $pay_process_name,
689 + ];
690 + }
691 + }
692 +
693 + /**
694 + * Check if the payment processor returned the information about the amount of processing fees.
695 + */
696 + if ($tn_data && isset($array_result['tot_fees']) && $array_result['tot_fees']) {
697 + // check event data payload to store
698 + if (is_array($tn_data)) {
699 + // set key
700 + $tn_data['processing_fees'] = (float) $array_result['tot_fees'];
701 + } elseif (is_object($tn_data)) {
702 + // set property
703 + $tn_data->processing_fees = (float) $array_result['tot_fees'];
704 + }
705 + }
706 +
707 + // current admin-user
708 + $now_user = JFactory::getUser();
709 +
710 + // Booking History
711 + $ev_descr = JText::translate('VBO_W_VIRTUALTERMINAL_TITLE') . " - {$pay_process_name} ({$now_user->name})";
712 + VikBooking::getBookingHistoryInstance()->setBid($booking_info['id'])->setExtraData($tn_data)->store('P' . ($booking_info['paymcount'] > 0 ? 'N' : '0'), $ev_descr);
713 +
714 + return [
715 + 'success' => 1,
716 + 'log' => $tn_log,
717 + ];
718 + }
719 +
720 + /**
527 721 * Preload the necessary assets.
528 722 *
529 723 * @return void
530 724 */
@@ -537,13 +731,13 @@
537 731 /**
538 732 * Main method to invoke the widget. Contents will be loaded
539 733 * through AJAX requests, not via PHP when the page loads.
540 734 *
541 - * @param VBOMultitaskData $data
735 + * @param ?VBOMultitaskData $data
542 736 *
543 737 * @return void
544 738 */
545 - public function render(VBOMultitaskData $data = null)
739 + public function render(?VBOMultitaskData $data = null)
546 740 {
547 741 // increase widget's instance counter
548 742 static::$instance_counter++;
549 743
@@ -674,9 +868,9 @@
674 868 return false;
675 869 }
676 870
677 871 // the trigger button
678 - var charge_cmd = widget_instance.find('.vbo-vterminal-cc-row-submit').find('button');
872 + var charge_cmd = widget_instance.find('.vbo-vterminal-cc-row-submit[data-tn-type="direct-charge"]').find('button');
679 873
680 874 // disable button
681 875 charge_cmd.prop('disabled', true);
682 876
@@ -746,8 +940,83 @@
746 940 );
747 941 }
748 942
749 943 /**
944 + * Performs the request to charge a pre-authorized card (off-session).
945 + */
946 + function vboWidgetVTerminalOffSessionCharge(wrapper) {
947 + let widget_instance = jQuery('#' + wrapper);
948 + if (!widget_instance.length) {
949 + return false;
950 + }
951 +
952 + // the trigger button
953 + let charge_cmd = widget_instance.find('.vbo-vterminal-cc-row-submit[data-tn-type="off-session"]').find('button');
954 +
955 + // disable button
956 + charge_cmd.prop('disabled', true);
957 +
958 + if (VBOCore.options.default_loading_body) {
959 + // show loading spinner
960 + charge_cmd.find('i').replaceWith(VBOCore.options.default_loading_body);
961 + }
962 +
963 + // get the booking ID for the transaction
964 + let force_bid = widget_instance.attr('data-pagebid');
965 +
966 + // the widget method to call
967 + let call_method = 'doOffSessionCapture';
968 +
969 + // make a request to load the bookings calendar
970 + VBOCore.doAjax(
971 + "<?php echo $this->getExecWidgetAjaxUri(); ?>",
972 + {
973 + widget_id: "<?php echo $this->getIdentifier(); ?>",
974 + call: call_method,
975 + return: 1,
976 + bid: force_bid,
977 + currency: widget_instance.find('input[data-vt-cc-field="currency"]').val(),
978 + amount: widget_instance.find('input[data-vt-cc-field="amount"]').val(),
979 + wrapper: wrapper,
980 + tmpl: "component"
981 + },
982 + (response) => {
983 + try {
984 + let obj_res = typeof response === 'string' ? JSON.parse(response) : response;
985 + if (!obj_res.hasOwnProperty(call_method)) {
986 + console.error('Unexpected JSON response', obj_res);
987 + return false;
988 + }
989 +
990 + // turn flag on
991 + vbo_widget_vt_last_tn = 1;
992 +
993 + // update button status
994 + charge_cmd.removeClass('vbo-config-btn').addClass('btn-success').html(vbo_vt_icon_success + ' ' + Joomla.JText._('VBOUPLOADFILEDONE'));
995 +
996 + // check if we need to dismiss the modal widget
997 + let js_modal_id = widget_instance.attr('data-modalid');
998 + if (js_modal_id) {
999 + setTimeout(() => {
1000 + // dismiss modal widget
1001 + VBOCore.emitEvent('vbo-dismiss-widget-modal' + js_modal_id);
1002 + }, 1500);
1003 + }
1004 + } catch(err) {
1005 + console.error('could not parse JSON response', err, response);
1006 + }
1007 + },
1008 + (error) => {
1009 + // display error message
1010 + alert(error.responseText);
1011 + // restore button
1012 + charge_cmd.prop('disabled', false);
1013 + charge_cmd.find('i').replaceWith(vbo_vt_icon_error);
1014 + }
1015 + );
1016 + }
1017 +
1018 + /**
750 1019 * Generate the HTML skeleton loading string to build the form.
751 1020 */
752 1021 function vboWidgetVTerminalFormSkeleton(wrapper) {
753 1022 var widget_instance = jQuery('#' + wrapper);
@@ -1018,9 +1287,9 @@
1018 1287
1019 1288 // show loading skeletons
1020 1289 vboWidgetVTerminalFormSkeleton('<?php echo $wrapper_id; ?>');
1021 1290
1022 - // when document is ready, load bookings calendar for this widget's instance
1291 + // when document is ready, load terminal form for this widget's instance
1023 1292 vboWidgetVTerminalFormLoad('<?php echo $wrapper_id; ?>', '<?php echo $page_bid; ?>');
1024 1293
1025 1294 // subscribe to the multitask-panel-open event
1026 1295 document.addEventListener(VBOCore.multitask_open_event, function() {
@@ -1026,9 +1295,9 @@
1026 1295 document.addEventListener(VBOCore.multitask_open_event, function() {
1027 1296 vboWidgetVTerminalMultitaskOpen('<?php echo $wrapper_id; ?>');
1028 1297 });
1029 1298
1030 - // subscribe to the multitask-panel-close event to emit the event for the lastly created booking ID
1299 + // subscribe to the multitask-panel-close event to propagate the event for new transaction
1031 1300 document.addEventListener(VBOCore.multitask_close_event, function() {
1032 1301 if (vbo_widget_vt_last_tn) {
1033 1302 // emit the event with data for anyone who is listening to it
1034 1303 VBOCore.emitEvent('vbo_new_payment_transaction', {
@@ -1066,46 +1335,17 @@
1066 1335 *
1067 1336 * @param array $booking the reservation record as an associative array.
1068 1337 * @param array $card the card details collected through the Virtual Terminal.
1069 1338 *
1070 - * @return object|null the payment processor dispatcher instance or null.
1339 + * @return ?object the payment processor dispatcher instance or null.
1071 1340 */
1072 1341 protected function getPaymentProcessor(array $booking, array $card = [])
1073 1342 {
1074 - $processor = null;
1075 - $payment = [];
1076 -
1077 - if (!empty($booking['idpayment'])) {
1078 - $payment = VikBooking::getPayment($booking['idpayment']);
1343 + try {
1344 + $processor = VBOModelReservation::getInstance($booking, true)->getPaymentProcessor($card);
1345 + } catch (Exception $e) {
1346 + $processor = null;
1079 1347 }
1080 1348
1081 - if ($card) {
1082 - // inject CC details for the payment processor
1083 - $booking['card'] = $card;
1084 - }
1085 -
1086 - if ($payment && VBOPlatformDetection::isWordPress()) {
1087 - /**
1088 - * @wponly The payment gateway is loaded
1089 - * through the apposite dispatcher.
1090 - */
1091 - JLoader::import('adapter.payment.dispatcher');
1092 - $processor = JPaymentDispatcher::getInstance('vikbooking', $payment['file'], $booking, $payment['params']);
1093 - } elseif ($payment && VBOPlatformDetection::isJoomla()) {
1094 - /**
1095 - * @joomlaonly The Payment Factory library will invoke the gateway.
1096 - */
1097 - require_once VBO_ADMIN_PATH . DIRECTORY_SEPARATOR . 'payments' . DIRECTORY_SEPARATOR . 'libraries' . DIRECTORY_SEPARATOR . 'factory.php';
1098 - $processor = VBOPaymentFactory::getPaymentInstance($payment['file'], $booking, $payment['params']);
1099 - }
1100 -
1101 - if ($processor && method_exists($processor, 'isDirectChargeSupported') && $processor->isDirectChargeSupported()) {
1102 - // set payment method flag loaded
1103 - $this->payment_method = $payment;
1104 -
1105 - // return the valid payment processor instance
1106 - return $processor;
1107 - }
1108 -
1109 - return null;
1349 + return $processor;
1110 1350 }
1111 1351 }