From b07226ab450f59455793ca43bb0772af75191d03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Gonz=C3=A1lez?= Date: Sun, 7 Aug 2022 18:57:29 +0200 Subject: [PATCH] Adding Stripe link payments --- README.md | 1 + application/config/config.php | 16 +- application/controllers/Booking.php | 8 +- .../controllers/Booking_confirmation.php | 16 +- application/controllers/Calendar.php | 16 +- application/controllers/Payment.php | 245 ++++++++++++++++++ .../language/arabic/translations_lang.php | 9 + .../language/bulgarian/translations_lang.php | 9 + .../language/catalan/translations_lang.php | 9 + .../language/chinese/translations_lang.php | 9 + .../language/czech/translations_lang.php | 9 + .../language/danish/translations_lang.php | 9 + .../language/dutch/translations_lang.php | 9 + .../language/english/translations_lang.php | 9 + .../language/estonian/translations_lang.php | 9 + .../language/finnish/translations_lang.php | 9 + .../language/french/translations_lang.php | 9 + .../language/german/translations_lang.php | 9 + .../language/greek/translations_lang.php | 9 + .../language/hebrew/translations_lang.php | 9 + .../language/hindi/translations_lang.php | 9 + .../language/hungarian/translations_lang.php | 9 + .../language/italian/translations_lang.php | 9 + .../language/japanese/translations_lang.php | 9 + .../luxembourgish/translations_lang.php | 9 + .../language/marathi/translations_lang.php | 9 + .../language/persian/translations_lang.php | 9 + .../language/polish/translations_lang.php | 9 + .../portuguese-br/translations_lang.php | 9 + .../language/portuguese/translations_lang.php | 9 + .../language/romanian/translations_lang.php | 9 + .../language/russian/translations_lang.php | 9 + .../language/serbian/translations_lang.php | 9 + .../language/slovak/translations_lang.php | 9 + .../language/spanish/translations_lang.php | 9 + .../language/swedish/translations_lang.php | 9 + .../language/turkish/translations_lang.php | 9 + application/libraries/Email_messages.php | 9 + ...nt_intent_column_to_appointments_table.php | 48 ++++ ...d_is_paid_column_to_appointments_table.php | 49 ++++ ..._payment_link_column_to_services_table.php | 48 ++++ application/models/Appointments_model.php | 27 +- application/models/Services_model.php | 9 +- .../views/components/appointments_modal.php | 9 + .../views/components/booking_type_step.php | 20 +- .../emails/appointment_deleted_email.php | 13 +- .../views/emails/appointment_saved_email.php | 14 +- application/views/pages/booking.php | 7 +- .../views/pages/booking_confirmation.php | 7 + application/views/pages/payment.php | 40 +++ application/views/pages/services.php | 10 + assets/js/components/appointments_modal.js | 2 + assets/js/pages/services.js | 5 +- assets/js/utils/calendar_default_view.js | 14 + assets/js/utils/calendar_event_popover.js | 27 +- assets/js/utils/calendar_table_view.js | 13 + composer.json | 3 +- composer.lock | 197 +++++++++----- config-sample.php | 8 + docs/stripe-payment-links.md | 57 ++++ 60 files changed, 1127 insertions(+), 90 deletions(-) create mode 100755 application/controllers/Payment.php create mode 100644 application/migrations/045_add_payment_intent_column_to_appointments_table.php create mode 100644 application/migrations/046_add_is_paid_column_to_appointments_table.php create mode 100644 application/migrations/047_add_payment_link_column_to_services_table.php create mode 100755 application/views/pages/payment.php create mode 100644 docs/stripe-payment-links.md diff --git a/README.md b/README.md index 8dee30a878..3294810212 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,7 @@ The application is designed to be flexible enough so that it can handle any ente * Self hosted installation. * Translated user interface. * User community support. +* Service payment by [Stripe Payment links](https://stripe.com/en-gb-es/payments/payment-links) ## Setup diff --git a/application/config/config.php b/application/config/config.php index 1b7e624df4..1cb54e85d0 100644 --- a/application/config/config.php +++ b/application/config/config.php @@ -458,12 +458,24 @@ | Rate Limiting |-------------------------------------------------------------------------- | -| Toggle the rate limiting feature in your application. Using rate limiting -| will control the number of requests a client can sent to the app. +| Toggle the rate limiting feature in your application. Using rate limiting +| will control the number of requests a client can sent to the app. | */ $config['rate_limiting'] = TRUE; +/* +|-------------------------------------------------------------------------- +| Stripe Payment Configuration +|-------------------------------------------------------------------------- +| +| Declare some of the global config values of the Stripe Payments +| +*/ + +$config['stripe_payment_feature'] = Config::STRIPE_PAYMENT_FEATURE; +$config['stripe_api_key'] = Config::STRIPE_API_KEY; + /* End of file config.php */ /* Location: ./application/config/config.php */ diff --git a/application/controllers/Booking.php b/application/controllers/Booking.php index 33775d14d5..d90911ce2b 100755 --- a/application/controllers/Booking.php +++ b/application/controllers/Booking.php @@ -93,7 +93,7 @@ public function index() foreach ($available_providers as &$available_provider) { - // Only expose the required provider data. + // Only expose the required provider data. $this->providers_model->only($available_provider, [ 'id', @@ -170,7 +170,7 @@ public function index() return; } - // Make sure the appointment can still be rescheduled. + // Make sure the appointment can still be rescheduled. $start_datetime = strtotime($results[0]['start_datetime']); @@ -203,6 +203,7 @@ public function index() $provider = $this->providers_model->find($appointment['id_users_provider']); $customer = $this->customers_model->find($appointment['id_users_customer']); $customer_token = md5(uniqid(mt_rand(), TRUE)); + $is_paid = $appointment['is_paid']; // Cache the token for 10 minutes. $this->cache->save('customer-token-' . $customer_token, $customer['id'], 600); @@ -214,6 +215,7 @@ public function index() $appointment = NULL; $provider = NULL; $customer = NULL; + $is_paid = 0; } script_vars([ @@ -271,9 +273,11 @@ public function index() 'grouped_timezones' => $grouped_timezones, 'manage_mode' => $manage_mode, 'customer_token' => $customer_token, + 'is_paid' => $is_paid == 1, 'appointment_data' => $appointment, 'provider_data' => $provider, 'customer_data' => $customer, + 'company_email' => setting('company_email'), ]); $this->load->view('pages/booking'); diff --git a/application/controllers/Booking_confirmation.php b/application/controllers/Booking_confirmation.php index 4ca87e7e34..29f468a577 100755 --- a/application/controllers/Booking_confirmation.php +++ b/application/controllers/Booking_confirmation.php @@ -30,7 +30,7 @@ public function __construct() $this->load->model('providers_model'); $this->load->model('services_model'); $this->load->model('customers_model'); - + $this->load->library('google_sync'); } @@ -52,7 +52,17 @@ public function of() $appointment = $occurrences[0]; - $add_to_google_url = $this->google_sync->get_add_to_google_url($appointment['id']); + $add_to_google_url = $this->google_sync->get_add_to_google_url($appointment['id']); + + $service = $this->services_model->find($appointment['id_services']); + + $customer = $this->customers_model->find($appointment['id_users_customer']); + + $payment_link_vars = array( + '{$appointment_hash}' => $appointment['hash'], + '{$customer_email}' => $customer['email'], + ); + $payment_link = strtr($service['payment_link'], $payment_link_vars); html_vars([ 'page_title' => lang('success'), @@ -60,6 +70,8 @@ public function of() 'google_analytics_code' => setting('google_analytics_code'), 'matomo_analytics_url' => setting('matomo_analytics_url'), 'add_to_google_url' => $add_to_google_url, + 'is_paid' => $appointment['is_paid'], + 'payment_link' => $payment_link, ]); $this->load->view('pages/booking_confirmation'); diff --git a/application/controllers/Calendar.php b/application/controllers/Calendar.php index 6ba4efb127..fc8196e66c 100644 --- a/application/controllers/Calendar.php +++ b/application/controllers/Calendar.php @@ -134,6 +134,7 @@ public function index(string $appointment_hash = '') 'secretary_providers' => $secretary_providers, 'edit_appointment' => $edit_appointment, 'customers' => $this->customers_model->get(NULL, 50, NULL, 'update_datetime DESC'), + 'stripe_payment_feature' => config('stripe_payment_feature'), ]); html_vars([ @@ -233,7 +234,7 @@ public function save_appointment() } // If the appointment does not contain the customer record id, then it means that is going to be - // inserted. + // inserted. if ( ! isset($appointment['id_users_customer'])) { $appointment['id_users_customer'] = $customer['id'] ?? $customer_data['id']; @@ -256,6 +257,7 @@ public function save_appointment() 'id_users_provider', 'id_users_customer', 'id_services', + 'is_paid', ]); $appointment['id'] = $this->appointments_model->save($appointment); @@ -629,9 +631,9 @@ public function get_calendar_appointments() $end_date = $this->db->escape(date('Y-m-d', strtotime(request('end_date') . ' +1 day'))); $where_clause = $where_id . ' = ' . $record_id . ' - AND ((start_datetime > ' . $start_date . ' AND start_datetime < ' . $end_date . ') - or (end_datetime > ' . $start_date . ' AND end_datetime < ' . $end_date . ') - or (start_datetime <= ' . $start_date . ' AND end_datetime >= ' . $end_date . ')) + AND ((start_datetime > ' . $start_date . ' AND start_datetime < ' . $end_date . ') + or (end_datetime > ' . $start_date . ' AND end_datetime < ' . $end_date . ') + or (start_datetime <= ' . $start_date . ' AND end_datetime >= ' . $end_date . ')) AND is_unavailability = 0 '; @@ -650,9 +652,9 @@ public function get_calendar_appointments() if ($filter_type == FILTER_TYPE_PROVIDER) { $where_clause = $where_id . ' = ' . $record_id . ' - AND ((start_datetime > ' . $start_date . ' AND start_datetime < ' . $end_date . ') - or (end_datetime > ' . $start_date . ' AND end_datetime < ' . $end_date . ') - or (start_datetime <= ' . $start_date . ' AND end_datetime >= ' . $end_date . ')) + AND ((start_datetime > ' . $start_date . ' AND start_datetime < ' . $end_date . ') + or (end_datetime > ' . $start_date . ' AND end_datetime < ' . $end_date . ') + or (start_datetime <= ' . $start_date . ' AND end_datetime >= ' . $end_date . ')) AND is_unavailability = 1 '; diff --git a/application/controllers/Payment.php b/application/controllers/Payment.php new file mode 100755 index 0000000000..7ee4ea9d28 --- /dev/null +++ b/application/controllers/Payment.php @@ -0,0 +1,245 @@ + + * @copyright Copyright (c) Alex Tselegidis + * @license https://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link https://easyappointments.org + * @since v1.0.0 + * ---------------------------------------------------------------------------- */ + +/** + * Payment confirmation controller. + * + * Handles the confirmation of a payment. + * + * + * @package Controllers + */ +class Payment extends EA_Controller { + /** + * Booking constructor. + */ + public function __construct() + { + parent::__construct(); + + $this->load->model('appointments_model'); + $this->load->model('providers_model'); + $this->load->model('admins_model'); + $this->load->model('secretaries_model'); + $this->load->model('categories_model'); + $this->load->model('services_model'); + $this->load->model('customers_model'); + $this->load->model('settings_model'); + $this->load->model('consents_model'); + + $this->load->library('timezones'); + $this->load->library('synchronization'); + $this->load->library('notifications'); + $this->load->library('availability'); + $this->load->library('webhooks_client'); + + $this->load->driver('cache', ['adapter' => 'file']); + } + + /** + * Render the payment confirmation page. + */ + public function index() + { + if ( ! is_app_installed()) + { + redirect('installation'); + + return; + } + + $appointment = html_vars('appointment'); + + if (empty($appointment)) { + abort(404, "Forbidden"); + } else { + $manage_mode = TRUE; + $company_name = setting('company_name'); + $company_logo = setting('company_logo'); + $company_color = setting('company_color'); + $google_analytics_code = setting('google_analytics_code'); + $matomo_analytics_url = setting('matomo_analytics_url'); + $date_format = setting('date_format'); + $time_format = setting('time_format'); + + $display_first_name = setting('display_first_name'); + $require_first_name = setting('require_first_name'); + $display_last_name = setting('display_last_name'); + $require_last_name = setting('require_last_name'); + $display_email = setting('display_email'); + $require_email = setting('require_email'); + $display_phone_number = setting('display_phone_number'); + $require_phone_number = setting('require_phone_number'); + $display_address = setting('display_address'); + $require_address = setting('require_address'); + $display_city = setting('display_city'); + $require_city = setting('require_city'); + $display_zip_code = setting('display_zip_code'); + $require_zip_code = setting('require_zip_code'); + $display_notes = setting('display_notes'); + $require_notes = setting('require_notes'); + $display_cookie_notice = setting('display_cookie_notice'); + $cookie_notice_content = setting('cookie_notice_content'); + $display_terms_and_conditions = setting('display_terms_and_conditions'); + $terms_and_conditions_content = setting('terms_and_conditions_content'); + $display_privacy_policy = setting('display_privacy_policy'); + $privacy_policy_content = setting('privacy_policy_content'); + + $theme = request('theme', setting('theme', 'default')); + if (empty($theme) || ! file_exists(__DIR__ . '/../../assets/css/themes/' . $theme . '.min.css')) + { + $theme = 'default'; + } + + $timezones = $this->timezones->to_array(); + $grouped_timezones = $this->timezones->to_grouped_array(); + $provider = $this->providers_model->find($appointment['id_users_provider']); + $customer = $this->customers_model->find($appointment['id_users_customer']); + + script_vars([ + 'date_format' => $date_format, + 'time_format' => $time_format, + 'display_cookie_notice' => $display_cookie_notice, + 'display_any_provider' => setting('display_any_provider'), + ]); + + html_vars([ + 'theme' => $theme, + 'company_name' => $company_name, + 'company_logo' => $company_logo, + 'company_color' => $company_color === '#ffffff' ? '' : $company_color, + 'date_format' => $date_format, + 'time_format' => $time_format, + 'display_first_name' => $display_first_name, + 'display_last_name' => $display_last_name, + 'display_email' => $display_email, + 'display_phone_number' => $display_phone_number, + 'display_address' => $display_address, + 'display_city' => $display_city, + 'display_zip_code' => $display_zip_code, + 'display_notes' => $display_notes, + 'google_analytics_code' => $google_analytics_code, + 'matomo_analytics_url' => $matomo_analytics_url, + 'timezones' => $timezones, + 'grouped_timezones' => $grouped_timezones, + 'appointment' => $appointment, + 'provider' => $provider, + 'customer' => $customer, + ]); + + $this->load->view('pages/payment'); + } + } + + /** + * Validates Stripe payment and render confirmation screen for the appointment. + * + * This method sets a flag as paid for an appointment and call the "index" callback + * to handle the page rendering. + * + * @param string $checkout_session_id Stripe session id. + */ + public function confirm(string $checkout_session_id) + { + try + { + $stripe_api_key = config('stripe_api_key'); + + $stripe = new \Stripe\StripeClient($stripe_api_key); + + $session = $stripe->checkout->sessions->retrieve($checkout_session_id); + + $appointment_hash = $session->client_reference_id; + $payment_intent = $session->payment_intent; + + $appointment = $this->set_paid($appointment_hash, $payment_intent); + + html_vars(['appointment' => $appointment]); + + $this->index(); + } + catch (Throwable $e) + { + error_log( $e ); + abort(500, 'Internal server error'); + } + } + + /** + * Sets a paid flag and paid intent for an appointment to track paid bookings. + */ + private function set_paid($appointment_hash, $payment_intent) + { + try + { + $manage_mode = TRUE; + + $occurrences = $this->appointments_model->get(['hash' => $appointment_hash]); + + if (empty($occurrences)) + { + abort(404, 'Not Found'); + } + + $appointment = $occurrences[0]; + + $provider = $this->providers_model->find($appointment['id_users_provider']); + + $customer = $this->customers_model->find($appointment['id_users_customer']); + + $service = $this->services_model->find($appointment['id_services']); + + + $appointment['is_paid'] = 1; + $appointment['payment_intent'] = $payment_intent; + $this->appointments_model->only($appointment, [ + 'id', + 'start_datetime', + 'end_datetime', + 'location', + 'notes', + 'color', + 'is_unavailability', + 'id_users_provider', + 'id_users_customer', + 'id_services', + 'is_paid', + 'payment_intent', + ]); + $appointment_id = $this->appointments_model->save($appointment); + $appointment = $this->appointments_model->find($appointment_id); + + $settings = [ + 'company_name' => setting('company_name'), + 'company_link' => setting('company_link'), + 'company_email' => setting('company_email'), + 'date_format' => setting('date_format'), + 'time_format' => setting('time_format') + ]; + + $this->synchronization->sync_appointment_saved($appointment, $service, $provider, $customer, $settings, $manage_mode); + + $this->notifications->notify_appointment_saved($appointment, $service, $provider, $customer, $settings, $manage_mode); + + $this->webhooks_client->trigger(WEBHOOK_APPOINTMENT_SAVE, $appointment); + + return $appointment; + } + catch (Throwable $e) + { + error_log( $e ); + abort(500, 'Internal server error'); + } + } + +} diff --git a/application/language/arabic/translations_lang.php b/application/language/arabic/translations_lang.php index 16d7be76bb..1402690c9e 100755 --- a/application/language/arabic/translations_lang.php +++ b/application/language/arabic/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/bulgarian/translations_lang.php b/application/language/bulgarian/translations_lang.php index 32a1ea50b5..a17beaf6b9 100755 --- a/application/language/bulgarian/translations_lang.php +++ b/application/language/bulgarian/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/catalan/translations_lang.php b/application/language/catalan/translations_lang.php index 7395db3aec..67773f6141 100644 --- a/application/language/catalan/translations_lang.php +++ b/application/language/catalan/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/chinese/translations_lang.php b/application/language/chinese/translations_lang.php index 6372391eed..eb07b70361 100755 --- a/application/language/chinese/translations_lang.php +++ b/application/language/chinese/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/czech/translations_lang.php b/application/language/czech/translations_lang.php index 3731882a40..2b7d8e3d3e 100644 --- a/application/language/czech/translations_lang.php +++ b/application/language/czech/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/danish/translations_lang.php b/application/language/danish/translations_lang.php index 555af33e51..b627005559 100755 --- a/application/language/danish/translations_lang.php +++ b/application/language/danish/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/dutch/translations_lang.php b/application/language/dutch/translations_lang.php index c3ae57d3b0..a6af054fd9 100755 --- a/application/language/dutch/translations_lang.php +++ b/application/language/dutch/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/english/translations_lang.php b/application/language/english/translations_lang.php index 64d7043193..727d84d4d2 100755 --- a/application/language/english/translations_lang.php +++ b/application/language/english/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/estonian/translations_lang.php b/application/language/estonian/translations_lang.php index e18bf7ea41..286b48a36e 100644 --- a/application/language/estonian/translations_lang.php +++ b/application/language/estonian/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/finnish/translations_lang.php b/application/language/finnish/translations_lang.php index 5d65e570f1..1267be5f5b 100755 --- a/application/language/finnish/translations_lang.php +++ b/application/language/finnish/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/french/translations_lang.php b/application/language/french/translations_lang.php index d484364f10..e9ad6893e4 100755 --- a/application/language/french/translations_lang.php +++ b/application/language/french/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/german/translations_lang.php b/application/language/german/translations_lang.php index 029a97a1fb..c9b756b003 100755 --- a/application/language/german/translations_lang.php +++ b/application/language/german/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/greek/translations_lang.php b/application/language/greek/translations_lang.php index 388ec8a1c5..7285d48d75 100755 --- a/application/language/greek/translations_lang.php +++ b/application/language/greek/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/hebrew/translations_lang.php b/application/language/hebrew/translations_lang.php index da91bd4420..2a0dbdc183 100644 --- a/application/language/hebrew/translations_lang.php +++ b/application/language/hebrew/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/hindi/translations_lang.php b/application/language/hindi/translations_lang.php index 3c0c789c38..176580a82f 100755 --- a/application/language/hindi/translations_lang.php +++ b/application/language/hindi/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/hungarian/translations_lang.php b/application/language/hungarian/translations_lang.php index 523442fb64..eee35b11a4 100755 --- a/application/language/hungarian/translations_lang.php +++ b/application/language/hungarian/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/italian/translations_lang.php b/application/language/italian/translations_lang.php index ea6de8bfcd..9b373dc5e5 100755 --- a/application/language/italian/translations_lang.php +++ b/application/language/italian/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/japanese/translations_lang.php b/application/language/japanese/translations_lang.php index 771a900e79..3b39473e14 100755 --- a/application/language/japanese/translations_lang.php +++ b/application/language/japanese/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/luxembourgish/translations_lang.php b/application/language/luxembourgish/translations_lang.php index 1e20ef4b68..73b18fb969 100755 --- a/application/language/luxembourgish/translations_lang.php +++ b/application/language/luxembourgish/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/marathi/translations_lang.php b/application/language/marathi/translations_lang.php index 65b37e2761..5e1133188d 100644 --- a/application/language/marathi/translations_lang.php +++ b/application/language/marathi/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/persian/translations_lang.php b/application/language/persian/translations_lang.php index 55ff01f7ba..1bf54b0115 100644 --- a/application/language/persian/translations_lang.php +++ b/application/language/persian/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/polish/translations_lang.php b/application/language/polish/translations_lang.php index b5385c4276..ddfe4eb715 100755 --- a/application/language/polish/translations_lang.php +++ b/application/language/polish/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/portuguese-br/translations_lang.php b/application/language/portuguese-br/translations_lang.php index e09e2f79ec..24dd6eb7c1 100755 --- a/application/language/portuguese-br/translations_lang.php +++ b/application/language/portuguese-br/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/portuguese/translations_lang.php b/application/language/portuguese/translations_lang.php index bc514e53c1..434c7d154c 100755 --- a/application/language/portuguese/translations_lang.php +++ b/application/language/portuguese/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/romanian/translations_lang.php b/application/language/romanian/translations_lang.php index 4ae8d56c6b..507e03a895 100755 --- a/application/language/romanian/translations_lang.php +++ b/application/language/romanian/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/russian/translations_lang.php b/application/language/russian/translations_lang.php index f1c0e40499..50b515596f 100755 --- a/application/language/russian/translations_lang.php +++ b/application/language/russian/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/serbian/translations_lang.php b/application/language/serbian/translations_lang.php index 4f11b7eaec..14f9d07c8b 100644 --- a/application/language/serbian/translations_lang.php +++ b/application/language/serbian/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/slovak/translations_lang.php b/application/language/slovak/translations_lang.php index 68342cf6c3..71f52553e9 100755 --- a/application/language/slovak/translations_lang.php +++ b/application/language/slovak/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/spanish/translations_lang.php b/application/language/spanish/translations_lang.php index a47e75689a..dccf416ead 100755 --- a/application/language/spanish/translations_lang.php +++ b/application/language/spanish/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Enlace para el pago'; +$lang['service_payment_link_description'] = 'Puedes incluir las siguientes variables: {$appointment_hash}, {$customer_email}. Para procesar la confirmación del pago puedes usar la url https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} como pagina de confirmación en Stripe.'; +$lang['appointment_payment_title'] = 'Detalles del pago'; +$lang['appointment_payment_text'] = 'Pulse en el siguiente enlace para proceder con el pago'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'ID del pago'; +$lang['service_paid_warning'] = 'No es posible cambiar un servicio ya pagado. Pongase en contacto en el correo {$mail_link} para más información.'; +$lang['is_paid'] = 'Pagado'; +$lang['open_payment_process'] = 'Continuar con el pago'; // End diff --git a/application/language/swedish/translations_lang.php b/application/language/swedish/translations_lang.php index 903b72aed6..34d384120c 100644 --- a/application/language/swedish/translations_lang.php +++ b/application/language/swedish/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/language/turkish/translations_lang.php b/application/language/turkish/translations_lang.php index 5a1b852cdf..68f79ec941 100755 --- a/application/language/turkish/translations_lang.php +++ b/application/language/turkish/translations_lang.php @@ -408,4 +408,13 @@ $lang['status'] = 'Status'; $lang['appointment_status_options'] = 'Appointment Status Options'; $lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; +$lang['service_payment_link'] = 'Payment link'; +$lang['service_payment_link_description'] = 'You can include the following variables: {$appointment_hash}, {$customer_email}. In order to confirm the payment use https://YOUR_SERVER/payment/confirm/{CHECKOUT_SESSION_ID} url as confirmation page in Stripe'; +$lang['appointment_payment_title'] = 'Payment details'; +$lang['appointment_payment_text'] = 'Click on the following link to proceed with payment'; +$lang['appointment_paymentPaid_text'] = 'Payment has been successfully completed'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$lang['service_paid_warning'] = 'It is not possible to change an already paid service. Please contact us at {$mail_link} for more information.'; +$lang['is_paid'] = 'Paid'; +$lang['open_payment_process'] = 'Proceed with payment'; // End diff --git a/application/libraries/Email_messages.php b/application/libraries/Email_messages.php index ede1fd3467..3329c346ab 100644 --- a/application/libraries/Email_messages.php +++ b/application/libraries/Email_messages.php @@ -118,6 +118,12 @@ public function send_appointment_details( $appointment_end->setTimezone($appointment_timezone); } + $payment_link_vars = array( + '{$appointment_hash}' => $appointment['hash'], + '{$customer_email}' => $customer['email'], + ); + $payment_link = strtr($service['payment_link'], $payment_link_vars); + $html = $this->CI->load->view('emails/appointment_saved_email', [ 'email_title' => $subject, 'email_message' => $message, @@ -127,6 +133,8 @@ public function send_appointment_details( 'appointment_end_date' => $appointment_end->format($date_format . ' ' . $time_format), 'appointment_timezone' => $timezones[empty($timezone) ? $provider['timezone'] : $timezone], 'appointment_link' => $appointment_link_address, + 'payment_link' => $payment_link, + 'is_paid' => $appointment['is_paid'] == 1, 'company_link' => $settings['company_link'], 'company_name' => $settings['company_name'], 'customer_name' => $customer['first_name'] . ' ' . $customer['last_name'], @@ -229,6 +237,7 @@ public function send_delete_appointment( 'customer_phone' => $customer['phone_number'], 'customer_address' => $customer['address'], 'reason' => $reason, + 'payment_intent' => $appointment['payment_intent'], ], TRUE); $this->CI->email->from($settings['company_email'], $settings['company_email']); diff --git a/application/migrations/045_add_payment_intent_column_to_appointments_table.php b/application/migrations/045_add_payment_intent_column_to_appointments_table.php new file mode 100644 index 0000000000..1fc66a080c --- /dev/null +++ b/application/migrations/045_add_payment_intent_column_to_appointments_table.php @@ -0,0 +1,48 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.5.0 + * ---------------------------------------------------------------------------- */ + +/** + * @property CI_DB_query_builder $db + * @property CI_DB_forge $dbforge + */ +class Migration_Add_payment_intent_column_to_appointments_table extends CI_Migration { + /** + * Upgrade method. + */ + public function up() + { + if ( ! $this->db->field_exists('payment_intent', 'appointments')) + { + $fields = [ + 'payment_intent' => [ + 'type' => 'TEXT', + 'null' => TRUE + ] + ]; + + $this->dbforge->add_column('appointments', $fields); + + } + } + + /** + * Downgrade method. + */ + public function down() + { + if ($this->db->field_exists('payment_intent', 'appointments')) + { + $this->dbforge->drop_column('appointments', 'payment_intent'); + } + } +} diff --git a/application/migrations/046_add_is_paid_column_to_appointments_table.php b/application/migrations/046_add_is_paid_column_to_appointments_table.php new file mode 100644 index 0000000000..9a03a961cc --- /dev/null +++ b/application/migrations/046_add_is_paid_column_to_appointments_table.php @@ -0,0 +1,49 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.5.0 + * ---------------------------------------------------------------------------- */ + +/** + * @property CI_DB_query_builder $db + * @property CI_DB_forge $dbforge + */ +class Migration_Add_is_paid_column_to_appointments_table extends CI_Migration { + /** + * Upgrade method. + */ + public function up() + { + if ( ! $this->db->field_exists('is_paid', 'appointments')) + { + $fields = [ + 'is_paid' => [ + 'type' => 'TINYINT', + 'constraint' => '4', + 'default' => '0' + ] + ]; + + $this->dbforge->add_column('appointments', $fields); + + } + } + + /** + * Downgrade method. + */ + public function down() + { + if ($this->db->field_exists('is_paid', 'appointments')) + { + $this->dbforge->drop_column('appointments', 'is_paid'); + } + } +} diff --git a/application/migrations/047_add_payment_link_column_to_services_table.php b/application/migrations/047_add_payment_link_column_to_services_table.php new file mode 100644 index 0000000000..66ca6f14b5 --- /dev/null +++ b/application/migrations/047_add_payment_link_column_to_services_table.php @@ -0,0 +1,48 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.5.0 + * ---------------------------------------------------------------------------- */ + +/** + * @property CI_DB_query_builder $db + * @property CI_DB_forge $dbforge + */ +class Migration_Add_payment_link_column_to_services_table extends CI_Migration { + /** + * Upgrade method. + */ + public function up() + { + if ( ! $this->db->field_exists('payment_link', 'services')) + { + $fields = [ + 'payment_link' => [ + 'type' => 'TEXT', + 'null' => TRUE, + ] + ]; + + $this->dbforge->add_column('services', $fields); + + } + } + + /** + * Downgrade method. + */ + public function down() + { + if ($this->db->field_exists('payment_link', 'services')) + { + $this->dbforge->drop_column('services', 'payment_link'); + } + } +} diff --git a/application/models/Appointments_model.php b/application/models/Appointments_model.php index 329a149b1a..248e23b3c0 100644 --- a/application/models/Appointments_model.php +++ b/application/models/Appointments_model.php @@ -26,6 +26,7 @@ class Appointments_model extends EA_Model { 'id_users_provider' => 'integer', 'id_users_customer' => 'integer', 'id_services' => 'integer', + 'is_paid' => 'boolean', ]; /** @@ -43,6 +44,8 @@ class Appointments_model extends EA_Model { 'hash' => 'hash', 'providerId' => 'id_users_provider', 'googleCalendarId' => 'id_google_calendar', + 'isPaid' => 'is_paid', + 'paymentIntent' => 'payment_intent', ]; @@ -89,7 +92,7 @@ public function validate(array $appointment) } } - // Make sure all required fields are provided. + // Make sure all required fields are provided. if ( empty($appointment['start_datetime']) || empty($appointment['end_datetime']) @@ -120,7 +123,7 @@ public function validate(array $appointment) throw new InvalidArgumentException('The appointment duration cannot be less than ' . EVENT_MINIMUM_DURATION . ' minutes.'); } - // Make sure the provider ID really exists in the database. + // Make sure the provider ID really exists in the database. $count = $this ->db ->select() @@ -138,7 +141,7 @@ public function validate(array $appointment) if ( ! filter_var($appointment['is_unavailability'], FILTER_VALIDATE_BOOLEAN)) { - // Make sure the customer ID really exists in the database. + // Make sure the customer ID really exists in the database. $count = $this ->db ->select() @@ -154,7 +157,7 @@ public function validate(array $appointment) throw new InvalidArgumentException('The appointment customer ID was not found in the database: ' . $appointment['id_users_customer']); } - // Make sure the service ID really exists in the database. + // Make sure the service ID really exists in the database. $count = $this->db->get_where('services', ['id' => $appointment['id_services']])->num_rows(); if ( ! $count) @@ -200,7 +203,7 @@ protected function insert(array $appointment): int protected function update(array $appointment): int { $appointment['update_datetime'] = date('Y-m-d H:i:s'); - + if ( ! $this->db->update('appointments', $appointment, ['id' => $appointment['id']])) { throw new RuntimeException('Could not update appointment record.'); @@ -567,7 +570,9 @@ public function api_encode(array &$appointment) 'customerId' => $appointment['id_users_customer'] !== NULL ? (int)$appointment['id_users_customer'] : NULL, 'providerId' => $appointment['id_users_provider'] !== NULL ? (int)$appointment['id_users_provider'] : NULL, 'serviceId' => $appointment['id_services'] !== NULL ? (int)$appointment['id_services'] : NULL, - 'googleCalendarId' => $appointment['id_google_calendar'] !== NULL ? (int)$appointment['id_google_calendar'] : NULL + 'googleCalendarId' => $appointment['id_google_calendar'] !== NULL ? (int)$appointment['id_google_calendar'] : NULL, + 'isPaid' => $appointment['is_paid'], + 'paymentIntent' => $appointment['payment_intent'], ]; $appointment = $encoded_resource; @@ -638,6 +643,16 @@ public function api_decode(array &$appointment, array $base = NULL) $decoded_request['id_google_calendar'] = $appointment['googleCalendarId']; } + if (array_key_exists('isPaid', $appointment)) + { + $decoded_request['is_paid'] = $appointment['isPaid']; + } + + if (array_key_exists('paymentIntent', $appointment)) + { + $decoded_request['payment_intent'] = $appointment['paymentIntent']; + } + $decoded_request['is_unavailability'] = FALSE; $appointment = $decoded_request; diff --git a/application/models/Services_model.php b/application/models/Services_model.php index 1d2b1c1984..c54f130100 100644 --- a/application/models/Services_model.php +++ b/application/models/Services_model.php @@ -46,6 +46,7 @@ class Services_model extends EA_Model { 'attendantsNumber' => 'attendants_number', 'isPrivate' => 'is_private', 'categoryId' => 'id_categories', + 'paymentLink' => 'payment_link', ]; /** @@ -451,7 +452,8 @@ public function api_encode(array &$service) 'location' => $service['location'], 'availabilitiesType' => $service['availabilities_type'], 'attendantsNumber' => (int)$service['attendants_number'], - 'categoryId' => $service['id_categories'] !== NULL ? (int)$service['id_categories'] : NULL + 'categoryId' => $service['id_categories'] !== NULL ? (int)$service['id_categories'] : NULL, + 'paymentLink' => $service['payment_link'], ]; $service = $encoded_resource; @@ -502,6 +504,11 @@ public function api_decode(array &$service, array $base = NULL) $decoded_resource['location'] = $service['location']; } + if (array_key_exists('paymentLink', $service)) + { + $decoded_resource['payment_link'] = $service['paymentLink']; + } + if (array_key_exists('availabilitiesType', $service)) { $decoded_resource['availabilities_type'] = $service['availabilitiesType']; diff --git a/application/views/components/appointments_modal.php b/application/views/components/appointments_modal.php index eb86c166a5..b5ccb0591d 100644 --- a/application/views/components/appointments_modal.php +++ b/application/views/components/appointments_modal.php @@ -183,6 +183,15 @@ class="border rounded d-flex justify-content-between align-items-center bg-light + + +
+ + +
+ diff --git a/application/views/components/booking_type_step.php b/application/views/components/booking_type_step.php index b71a2a73a9..47bbe377c7 100644 --- a/application/views/components/booking_type_step.php +++ b/application/views/components/booking_type_step.php @@ -1,7 +1,7 @@ @@ -17,7 +17,11 @@ - + + + +

+ strtr('{$company_email}', [ + '{$company_email}' => $company_email + ]) + ]) + ?> + +

+
diff --git a/application/views/emails/appointment_deleted_email.php b/application/views/emails/appointment_deleted_email.php index 0213f932e5..57c028a625 100644 --- a/application/views/emails/appointment_deleted_email.php +++ b/application/views/emails/appointment_deleted_email.php @@ -1,7 +1,7 @@ @@ -54,6 +55,10 @@ + + + +

@@ -74,6 +79,12 @@ + + + + + +

diff --git a/application/views/emails/appointment_saved_email.php b/application/views/emails/appointment_saved_email.php index f32cecba50..2872469333 100644 --- a/application/views/emails/appointment_saved_email.php +++ b/application/views/emails/appointment_saved_email.php @@ -1,7 +1,7 @@ @@ -35,6 +37,16 @@

+ +

+ +

+ +

+ + + +

diff --git a/application/views/pages/booking.php b/application/views/pages/booking.php index 3e85134f7d..851efb025d 100755 --- a/application/views/pages/booking.php +++ b/application/views/pages/booking.php @@ -12,8 +12,11 @@ - vars('available_services')]) ?> - + vars('available_services'), + 'is_paid' => vars('is_paid'), + 'company_email' => vars('company_email') +]) ?> vars('grouped_timezones')]) ?> diff --git a/application/views/pages/booking_confirmation.php b/application/views/pages/booking_confirmation.php index 3ebf2d1ea2..2e4b756c65 100755 --- a/application/views/pages/booking_confirmation.php +++ b/application/views/pages/booking_confirmation.php @@ -28,6 +28,13 @@ + + + + + + + diff --git a/application/views/pages/payment.php b/application/views/pages/payment.php new file mode 100755 index 0000000000..5b35665c1d --- /dev/null +++ b/application/views/pages/payment.php @@ -0,0 +1,40 @@ + + + + +
+ success +
+ +
+

+ +

+ +

+ +

+ + + +

+ + + + + + + + + + +
+ + + + + + vars('google_analytics_code')]) ?> + vars('matomo_analytics_url')]) ?> + + diff --git a/application/views/pages/services.php b/application/views/pages/services.php index b56851cd9f..52510a2f51 100755 --- a/application/views/pages/services.php +++ b/application/views/pages/services.php @@ -156,6 +156,16 @@ + +
+ + + +
+ +