From a4184fa50327484d641ae00d732e5c5cf4d241d9 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 --- application/config/config.php | 11 + application/controllers/Booking.php | 8 +- application/controllers/Calendar.php | 1 + application/controllers/Payment.php | 246 ++++++++++++++++++ .../language/arabic/translations_lang.php | 6 + .../language/bulgarian/translations_lang.php | 6 + .../language/catalan/translations_lang.php | 6 + .../language/chinese/translations_lang.php | 6 + .../language/czech/translations_lang.php | 6 + .../language/danish/translations_lang.php | 6 + .../language/dutch/translations_lang.php | 6 + .../language/english/translations_lang.php | 7 + .../language/estonian/translations_lang.php | 6 + .../language/finnish/translations_lang.php | 6 + .../language/french/translations_lang.php | 6 + .../language/german/translations_lang.php | 6 + .../language/greek/translations_lang.php | 6 + .../language/hebrew/translations_lang.php | 6 + .../language/hindi/translations_lang.php | 6 + .../language/hungarian/translations_lang.php | 6 + .../language/italian/translations_lang.php | 6 + .../language/japanese/translations_lang.php | 6 + .../luxembourgish/translations_lang.php | 6 + .../language/marathi/translations_lang.php | 6 + .../language/persian/translations_lang.php | 6 + .../language/polish/translations_lang.php | 6 + .../portuguese-br/translations_lang.php | 6 + .../language/portuguese/translations_lang.php | 6 + .../language/romanian/translations_lang.php | 6 + .../language/russian/translations_lang.php | 6 + .../language/serbian/translations_lang.php | 6 + .../language/slovak/translations_lang.php | 6 + .../language/spanish/translations_lang.php | 7 + .../language/swedish/translations_lang.php | 6 + .../language/turkish/translations_lang.php | 6 + application/libraries/Email_messages.php | 9 + ...d_is_paid_column_to_appointments_table.php | 49 ++++ ..._payment_link_column_to_services_table.php | 48 ++++ ...nt_intent_column_to_appointments_table.php | 48 ++++ application/models/Appointments_model.php | 29 ++- application/models/Services_model.php | 9 +- .../views/components/appointments_modal.php | 7 + .../views/components/booking_type_step.php | 22 +- .../emails/appointment_deleted_email.php | 13 +- .../views/emails/appointment_saved_email.php | 12 + application/views/pages/booking.php | 7 +- application/views/pages/payment.php | 40 +++ application/views/pages/services.php | 8 + assets/js/components/appointments_modal.js | 2 + assets/js/pages/services.js | 5 +- assets/js/utils/calendar_default_view.js | 40 ++- assets/js/utils/calendar_event_popover.js | 27 +- assets/js/utils/calendar_table_view.js | 1 + composer.json | 3 +- composer.lock | 197 +++++++++----- 55 files changed, 949 insertions(+), 81 deletions(-) create mode 100755 application/controllers/Payment.php create mode 100644 application/migrations/043_add_is_paid_column_to_appointments_table.php create mode 100644 application/migrations/044_add_payment_link_column_to_services_table.php create mode 100644 application/migrations/045_add_payment_intent_column_to_appointments_table.php create mode 100755 application/views/pages/payment.php diff --git a/application/config/config.php b/application/config/config.php index 1b7e624df4..9347f0438f 100644 --- a/application/config/config.php +++ b/application/config/config.php @@ -465,5 +465,16 @@ $config['rate_limiting'] = TRUE; +/* +|-------------------------------------------------------------------------- +| Stripe Payment Configuration +|-------------------------------------------------------------------------- +| +| Declare some of the global config values of the Stripe Payments +| +*/ + +$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 25ace397f0..02b356b66b 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([ @@ -268,9 +270,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/Calendar.php b/application/controllers/Calendar.php index 148aca4474..51818c8e17 100644 --- a/application/controllers/Calendar.php +++ b/application/controllers/Calendar.php @@ -252,6 +252,7 @@ public function save_appointment() 'id_users_provider', 'id_users_customer', 'id_services', + 'is_paid', ]); $appointment['id'] = $this->appointments_model->save($appointment); diff --git a/application/controllers/Payment.php b/application/controllers/Payment.php new file mode 100755 index 0000000000..fa7146ef40 --- /dev/null +++ b/application/controllers/Payment.php @@ -0,0 +1,246 @@ + + * @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. + * + * This method sets a flag as paid for an appointment and renders a 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 will call the "index" callback to handle the page rendering. + * + * @param string $checkout_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'); + } + } + + /** + * Register the appointment to the database. + */ + 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 012ccbb675..78ba8b2fc4 100755 --- a/application/language/arabic/translations_lang.php +++ b/application/language/arabic/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/bulgarian/translations_lang.php b/application/language/bulgarian/translations_lang.php index 852cf25fde..5477b236d7 100755 --- a/application/language/bulgarian/translations_lang.php +++ b/application/language/bulgarian/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/catalan/translations_lang.php b/application/language/catalan/translations_lang.php index 70bb1cbdda..f0a449b110 100644 --- a/application/language/catalan/translations_lang.php +++ b/application/language/catalan/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/chinese/translations_lang.php b/application/language/chinese/translations_lang.php index 497d2a27d2..88fb0b6ee2 100755 --- a/application/language/chinese/translations_lang.php +++ b/application/language/chinese/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/czech/translations_lang.php b/application/language/czech/translations_lang.php index ca7e77e99c..5a0ede4fd8 100644 --- a/application/language/czech/translations_lang.php +++ b/application/language/czech/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/danish/translations_lang.php b/application/language/danish/translations_lang.php index 9812f97d9f..cfdfbfda69 100755 --- a/application/language/danish/translations_lang.php +++ b/application/language/danish/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/dutch/translations_lang.php b/application/language/dutch/translations_lang.php index 156d2e1507..41e4bed05b 100755 --- a/application/language/dutch/translations_lang.php +++ b/application/language/dutch/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/english/translations_lang.php b/application/language/english/translations_lang.php index f8caea6d94..0ed7dcbf0f 100755 --- a/application/language/english/translations_lang.php +++ b/application/language/english/translations_lang.php @@ -405,4 +405,11 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; +$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.'; // End diff --git a/application/language/estonian/translations_lang.php b/application/language/estonian/translations_lang.php index 27f3ea64de..171824504a 100644 --- a/application/language/estonian/translations_lang.php +++ b/application/language/estonian/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/finnish/translations_lang.php b/application/language/finnish/translations_lang.php index 95ed81bf8e..39d1f384d6 100755 --- a/application/language/finnish/translations_lang.php +++ b/application/language/finnish/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/french/translations_lang.php b/application/language/french/translations_lang.php index 815059c4b1..de50f3c924 100755 --- a/application/language/french/translations_lang.php +++ b/application/language/french/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/german/translations_lang.php b/application/language/german/translations_lang.php index 2e0d5dde06..62b76f1358 100755 --- a/application/language/german/translations_lang.php +++ b/application/language/german/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/greek/translations_lang.php b/application/language/greek/translations_lang.php index 60fc0a97ed..3ecd4f83eb 100755 --- a/application/language/greek/translations_lang.php +++ b/application/language/greek/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/hebrew/translations_lang.php b/application/language/hebrew/translations_lang.php index 5ee023bcf4..22bbfa5984 100644 --- a/application/language/hebrew/translations_lang.php +++ b/application/language/hebrew/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/hindi/translations_lang.php b/application/language/hindi/translations_lang.php index c4dbd00af7..11409b3eea 100755 --- a/application/language/hindi/translations_lang.php +++ b/application/language/hindi/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/hungarian/translations_lang.php b/application/language/hungarian/translations_lang.php index e7fbceee79..b28262b2a0 100755 --- a/application/language/hungarian/translations_lang.php +++ b/application/language/hungarian/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/italian/translations_lang.php b/application/language/italian/translations_lang.php index 39d10fddb4..70bbf57b77 100755 --- a/application/language/italian/translations_lang.php +++ b/application/language/italian/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/japanese/translations_lang.php b/application/language/japanese/translations_lang.php index cca792b5e4..f4ae19fdba 100755 --- a/application/language/japanese/translations_lang.php +++ b/application/language/japanese/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/luxembourgish/translations_lang.php b/application/language/luxembourgish/translations_lang.php index 73b70b904e..824f323e6b 100755 --- a/application/language/luxembourgish/translations_lang.php +++ b/application/language/luxembourgish/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/marathi/translations_lang.php b/application/language/marathi/translations_lang.php index 1815df5f6d..18e05a7272 100644 --- a/application/language/marathi/translations_lang.php +++ b/application/language/marathi/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/persian/translations_lang.php b/application/language/persian/translations_lang.php index 1b6ae74b75..5df56a2ff4 100644 --- a/application/language/persian/translations_lang.php +++ b/application/language/persian/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/polish/translations_lang.php b/application/language/polish/translations_lang.php index 3fcbe467f8..5006196679 100755 --- a/application/language/polish/translations_lang.php +++ b/application/language/polish/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/portuguese-br/translations_lang.php b/application/language/portuguese-br/translations_lang.php index 92662835e7..ee466001c7 100755 --- a/application/language/portuguese-br/translations_lang.php +++ b/application/language/portuguese-br/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/portuguese/translations_lang.php b/application/language/portuguese/translations_lang.php index 9d3dd1a0ce..97de4c2bf7 100755 --- a/application/language/portuguese/translations_lang.php +++ b/application/language/portuguese/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/romanian/translations_lang.php b/application/language/romanian/translations_lang.php index df14a0358d..3993a6ed9c 100755 --- a/application/language/romanian/translations_lang.php +++ b/application/language/romanian/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/russian/translations_lang.php b/application/language/russian/translations_lang.php index 869a103a47..7082c85a86 100755 --- a/application/language/russian/translations_lang.php +++ b/application/language/russian/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/serbian/translations_lang.php b/application/language/serbian/translations_lang.php index 3b960b8276..18b278bbd8 100644 --- a/application/language/serbian/translations_lang.php +++ b/application/language/serbian/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/slovak/translations_lang.php b/application/language/slovak/translations_lang.php index a0b2558545..25c7c44f6c 100755 --- a/application/language/slovak/translations_lang.php +++ b/application/language/slovak/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/spanish/translations_lang.php b/application/language/spanish/translations_lang.php index 71a0dc43e7..90f07aedb9 100755 --- a/application/language/spanish/translations_lang.php +++ b/application/language/spanish/translations_lang.php @@ -405,4 +405,11 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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.'; // End diff --git a/application/language/swedish/translations_lang.php b/application/language/swedish/translations_lang.php index cb97806ef4..335bf0a8b6 100644 --- a/application/language/swedish/translations_lang.php +++ b/application/language/swedish/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // End diff --git a/application/language/turkish/translations_lang.php b/application/language/turkish/translations_lang.php index c90e76c4a1..b278f52b78 100755 --- a/application/language/turkish/translations_lang.php +++ b/application/language/turkish/translations_lang.php @@ -405,4 +405,10 @@ $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$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 /index.php/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'] = 'El pago se ha realizado satisfactoriamente'; +$lang['payment_intent'] = 'Stripe Payment Intent'; // 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/043_add_is_paid_column_to_appointments_table.php b/application/migrations/043_add_is_paid_column_to_appointments_table.php new file mode 100644 index 0000000000..9a03a961cc --- /dev/null +++ b/application/migrations/043_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/044_add_payment_link_column_to_services_table.php b/application/migrations/044_add_payment_link_column_to_services_table.php new file mode 100644 index 0000000000..66ca6f14b5 --- /dev/null +++ b/application/migrations/044_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/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/models/Appointments_model.php b/application/models/Appointments_model.php index 97115bea39..0c0922ed0e 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', ]; /** @@ -42,6 +43,8 @@ class Appointments_model extends EA_Model { 'hash' => 'hash', 'providerId' => 'id_users_provider', 'googleCalendarId' => 'id_google_calendar', + 'isPaid' => 'is_paid', + 'paymentIntent' => 'payment_intent', ]; @@ -88,7 +91,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']) @@ -119,7 +122,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() @@ -137,7 +140,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() @@ -153,7 +156,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) @@ -199,7 +202,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.'); @@ -254,6 +257,8 @@ public function find(int $appointment_id, bool $with_trashed = FALSE): array $this->cast($appointment); + error_log( print_r($appointment, TRUE) ); + return $appointment; } @@ -566,7 +571,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; @@ -637,6 +644,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 a32e8424bf..cdcc7098d0 100644 --- a/application/views/components/appointments_modal.php +++ b/application/views/components/appointments_modal.php @@ -168,6 +168,13 @@ class="form-label"> +
+ + + +
diff --git a/application/views/components/booking_type_step.php b/application/views/components/booking_type_step.php index b71a2a73a9..1a53961aac 100644 --- a/application/views/components/booking_type_step.php +++ b/application/views/components/booking_type_step.php @@ -1,7 +1,7 @@ @@ -17,7 +17,13 @@ - + + + +

+ 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..3d96f0efdb 100644 --- a/application/views/emails/appointment_deleted_email.php +++ b/application/views/emails/appointment_deleted_email.php @@ -1,7 +1,7 @@ @@ -54,6 +55,12 @@ + + + + + +

@@ -71,8 +78,8 @@ - - + + diff --git a/application/views/emails/appointment_saved_email.php b/application/views/emails/appointment_saved_email.php index f32cecba50..2d5fad82fd 100644 --- a/application/views/emails/appointment_saved_email.php +++ b/application/views/emails/appointment_saved_email.php @@ -16,6 +16,8 @@ * @var string $customer_address * @var string $appointment_link * @var string $company_link + * @var string $payment_link + * @var boolean $is_paid */ ?> @@ -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/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 2161d34401..8965a7f163 100755 --- a/application/views/pages/services.php +++ b/application/views/pages/services.php @@ -157,6 +157,14 @@ +
+ + + +
+