PluginProbe ʕ •ᴥ•ʔ
LatePoint – Calendar Booking Plugin for Appointments and Events / 5.1.3
LatePoint – Calendar Booking Plugin for Appointments and Events v5.1.3
5.6.6 5.6.5 5.6.4 5.6.3 5.6.2 5.6.1 5.6.0 5.5.2 5.5.1 5.5.0 5.4.2 trunk 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.1.8 5.1.9 5.1.91 5.1.92 5.1.93 5.1.94 5.2.0 5.2.1 5.2.10 5.2.11 5.2.2 5.2.3 5.2.4 5.2.5 5.2.6 5.2.7 5.2.8 5.2.9 5.3.0 5.3.1 5.3.2 5.4.0 5.4.1
latepoint / lib / controllers / stripe_connect_controller.php
latepoint / lib / controllers Last commit date
activities_controller.php 1 year ago auth_controller.php 1 year ago booking_form_settings_controller.php 1 year ago bookings_controller.php 1 year ago calendars_controller.php 1 year ago carts_controller.php 1 year ago controller.php 1 year ago customer_cabinet_controller.php 1 year ago customers_controller.php 1 year ago dashboard_controller.php 1 year ago default_agent_controller.php 1 year ago events_controller.php 1 year ago form_fields_controller.php 1 year ago integrations_controller.php 1 year ago invoices_controller.php 1 year ago manage_booking_by_key_controller.php 1 year ago manage_order_by_key_controller.php 1 year ago notifications_controller.php 1 year ago orders_controller.php 1 year ago pro_controller.php 1 year ago process_jobs_controller.php 1 year ago processes_controller.php 1 year ago search_controller.php 1 year ago services_controller.php 1 year ago settings_controller.php 1 year ago steps_controller.php 1 year ago stripe_connect_controller.php 1 year ago support_topics_controller.php 1 year ago todos_controller.php 1 year ago transactions_controller.php 1 year ago wizard_controller.php 1 year ago
stripe_connect_controller.php
257 lines
1 <?php
2 /*
3 * Copyright (c) 2024 LatePoint LLC. All rights reserved.
4 */
5
6 if ( ! defined( 'ABSPATH' ) ) {
7 exit; // Exit if accessed directly.
8 }
9
10
11 if ( ! class_exists( 'OsStripeConnectController' ) ) :
12
13
14 class OsStripeConnectController extends OsController {
15
16
17 function __construct() {
18 parent::__construct();
19
20 $this->action_access['public'] = array_merge( $this->action_access['public'], [ 'webhook', 'create_payment_intent_for_transaction' ] );
21 $this->action_access['customer'] = array_merge( $this->action_access['customer'], [ 'create_payment_intent' ] );
22 $this->views_folder = LATEPOINT_VIEWS_ABSPATH . 'stripe_connect/';
23 }
24
25 public function refund_transaction(){
26 if(!filter_var($this->params['transaction_refund']['transaction_id'], FILTER_VALIDATE_INT)) {
27 $this->send_json( array( 'status' => LATEPOINT_STATUS_ERROR, 'message' => __( 'Invalid Transaction', 'latepoint' ) ) );
28 }
29 $transaction = new OsTransactionModel($this->params['transaction_refund']['transaction_id']);
30 if(empty($transaction) || $transaction->is_new_record() || $transaction->processor != OsStripeConnectHelper::$processor_code){
31 $this->send_json( array( 'status' => LATEPOINT_STATUS_ERROR, 'message' => __( 'Invalid Transaction', 'latepoint' ) ) );
32 }
33 try {
34 $refund_amount = ($this->params['transaction_refund']['portion'] == 'custom') ? $this->params['transaction_refund']['custom_amount'] : ($transaction->amount - $transaction->get_total_refunded_amount());
35 $refund_amount = OsParamsHelper::sanitize_param( $refund_amount, 'money' );
36 if(empty($refund_amount) || $refund_amount > $transaction->amount - $transaction->get_total_refunded_amount()){
37 throw new Exception(__('Invalid Refund Amount', 'latepoint'));
38 }
39 $transaction_refund = OsStripeConnectHelper::refund_transaction($transaction, $refund_amount);
40 $this->vars['transaction'] = new OsTransactionModel($transaction->id); # reload to get new refund info
41 $message = $this->render(LATEPOINT_VIEWS_ABSPATH.'orders/_transaction_box', 'none');
42 $this->send_json( array( 'status' => LATEPOINT_STATUS_SUCCESS, 'message' => $message ) );
43 }catch(Exception $e){
44 $this->send_json( array( 'status' => LATEPOINT_STATUS_ERROR, 'message' => $e->getMessage() ) );
45 }
46 }
47
48 public function create_payment_intent_for_transaction(){
49 if(!filter_var($this->params['invoice_id'], FILTER_VALIDATE_INT)) exit();
50 try {
51
52 $invoice = new OsInvoiceModel($this->params['invoice_id']);
53
54 $transaction_intent = new OsTransactionIntentModel();
55
56 $transaction_intent = $transaction_intent->where(['status' => LATEPOINT_TRANSACTION_INTENT_STATUS_NEW, 'invoice_id' => $invoice->id])->set_limit(1)->get_results_as_models();
57 if(empty($transaction_intent)) $transaction_intent = new OsTransactionIntentModel();
58
59 $transaction_intent->charge_amount = $invoice->charge_amount;
60 $transaction_intent->invoice_id = $invoice->id;
61 $order = $invoice->get_order();
62 $transaction_intent->order_id = $order->id;
63 $transaction_intent->customer_id = $order->customer_id;
64 $transaction_intent->specs_charge_amount = OsStripeConnectHelper::convert_amount_to_specs($transaction_intent->charge_amount);
65 $transaction_intent->set_payment_data_value('time', LATEPOINT_PAYMENT_TIME_NOW, false);
66 $transaction_intent->set_payment_data_value('portion', sanitize_text_field($this->params['payment_portion']), false);
67 $transaction_intent->set_payment_data_value('method', sanitize_text_field($this->params['payment_method']), false);
68 $transaction_intent->set_payment_data_value('processor', sanitize_text_field($this->params['payment_processor']), false);
69 $transaction_intent->generate_intent_key();
70
71 if ( OsSettingsHelper::get_settings_value( OsSettingsHelper::append_payment_env_key( 'stripe_connect_account_id' ) ) ) {
72 $payment_intent_data = OsStripeConnectHelper::generate_payment_intent_id_and_secret_for_transaction_intent( $transaction_intent );
73 $payment_intent_id = $payment_intent_data['id'];
74 $payment_intent_client_secret = $payment_intent_data['client_secret'];
75 } else {
76 throw new Exception( __( 'Stripe connect account ID not set', 'latepoint' ) );
77 }
78
79
80 $transaction_intent->set_payment_data_value('token', $payment_intent_id, false);
81 if(!$transaction_intent->save()){
82 throw new Exception( __( 'Unable to save transaction intent', 'latepoint' ) );
83 }
84
85 if ( $this->get_return_format() == 'json' ) {
86 $this->send_json( [
87 'status' => LATEPOINT_STATUS_SUCCESS,
88 'continue_transaction_intent_url' => OsTransactionIntentHelper::generate_continue_intent_url( $transaction_intent->intent_key ),
89 'payment_intent_id' => $payment_intent_id,
90 'payment_intent_secret' => $payment_intent_client_secret,
91 'transaction_intent_key' => $transaction_intent->intent_key
92 ] );
93 }
94 } catch ( Exception $e ) {
95 if ( $this->get_return_format() == 'json' ) {
96 $this->send_json( array( 'status' => LATEPOINT_STATUS_ERROR, 'message' => $e->getMessage() ) );
97 }
98 }
99 }
100
101 public function webhook() {
102 $payload = @file_get_contents( 'php://input' );
103 $data = json_decode( $payload, true );
104 if ( empty( $data['server_token'] ) || $data['server_token'] != OsStripeConnectHelper::get_server_token() || $data['stripe_account_id'] != OsStripeConnectHelper::get_connect_account_id() ) {
105 http_response_code( 400 );
106 echo 'Error converting order intent';
107 exit();
108 }
109 $event = $data['event'];
110 // Handle the event
111 switch ( $event['type'] ) {
112 case 'payment_intent.succeeded':
113 if ( ! empty( $event['data']['order_intent_key'] ) ) {
114 $order_intent = OsOrderIntentHelper::get_order_intent_by_intent_key( $event['data']['order_intent_key'] );
115 if ( $order_intent->is_new_record() ) {
116 OsDebugHelper::log( 'Error processing stripe connect webhook: Order intent not found for key' );
117 http_response_code( 400 );
118 exit();
119 }
120 if ( $order_intent->convert_to_order() ) {
121 http_response_code( 200 );
122 } else {
123 http_response_code( 400 );
124 OsDebugHelper::log( 'Error converting order intent' );
125 }
126 }
127 break;
128 }
129 exit();
130 }
131
132 private function get_env_from_params(): string {
133 return ( ! empty( $this->params['env'] && in_array( $this->params['env'], [
134 LATEPOINT_PAYMENTS_ENV_LIVE,
135 LATEPOINT_PAYMENTS_ENV_DEV
136 ] ) ) ) ? $this->params['env'] : OsSettingsHelper::get_payments_environment();
137 }
138
139 public function start_connect_process() {
140 $env = $this->get_env_from_params();
141 OsSettingsHelper::save_setting_by_name( OsSettingsHelper::append_payment_env_key( 'enable_payment_processor_stripe_connect', $env ), LATEPOINT_VALUE_ON );
142 $url = OsStripeConnectHelper::get_connect_url( $env );
143 $this->send_json( array( 'status' => LATEPOINT_STATUS_SUCCESS, 'url' => $url, 'message' => __( 'Redirecting to Stripe', 'latepoint' ) ) );
144 }
145
146 public function disconnect_connect_account() {
147 $env = $this->get_env_from_params();
148 try {
149 $path = 'server-tokens/' . OsStripeConnectHelper::get_server_token( $env ) . '/disconnect/';
150 $response = OsStripeConnectHelper::do_account_request( $path, $env, '', 'DELETE' );
151 if ( $response['status']['code'] == 200 ) {
152 OsSettingsHelper::remove_setting_by_name( OsSettingsHelper::append_payment_env_key( 'stripe_connect_charges_enabled' ) );
153 OsSettingsHelper::remove_setting_by_name( OsSettingsHelper::append_payment_env_key( 'stripe_connect_account_id' ) );
154 } else {
155 OsDebugHelper::log( 'Stripe Connect Error', 'stripe_connect_disconnect_error', $response );
156 }
157 } catch ( Exception $e ) {
158 OsDebugHelper::log( 'Error getting status of a stripe connection', 'stripe', [ 'error_message' => $e->getMessage() ] );
159 $this->send_json( array( 'status' => LATEPOINT_STATUS_ERROR, 'message' => $e->getMessage() ) );
160 }
161 $this->send_json( array( 'status' => LATEPOINT_STATUS_SUCCESS, 'message' => OsStripeConnectHelper::get_connection_buttons_and_status( $env ) ) );
162 }
163
164
165 public function check_connect_status() {
166 $env = $this->get_env_from_params();
167 try {
168 $response = OsStripeConnectHelper::do_request( 'server-tokens/' . OsStripeConnectHelper::get_server_token( $env ) . '/status', '', 'GET', [], [], $env );
169 if ( ! empty( $response['data'] ) && ! empty( $response['data']['account_id'] ) ) {
170 OsSettingsHelper::save_setting_by_name( OsSettingsHelper::append_payment_env_key( 'stripe_connect_account_id', $env ), $response['data']['account_id'] );
171 if ( ! empty( $response['data']['charges_enabled'] ) ) {
172 OsSettingsHelper::save_setting_by_name( OsSettingsHelper::append_payment_env_key( 'stripe_connect_charges_enabled', $env ), LATEPOINT_VALUE_ON );
173 } else {
174 OsSettingsHelper::remove_setting_by_name( OsSettingsHelper::append_payment_env_key( 'stripe_connect_charges_enabled', $env ) );
175 }
176 } else {
177 OsSettingsHelper::remove_setting_by_name( OsSettingsHelper::append_payment_env_key( 'stripe_connect_charges_enabled', $env ) );
178 OsSettingsHelper::remove_setting_by_name( OsSettingsHelper::append_payment_env_key( 'stripe_connect_account_id', $env ) );
179 }
180 if ( ! empty( $response['data']['error'] ) ) {
181 OsDebugHelper::log( 'Error checking status of server token', 'stripe_connect_error', [ 'error_message' => $response['data']['error'] ] );
182 }
183 } catch ( Exception $e ) {
184 OsDebugHelper::log( 'Error getting status of a stripe connection', 'stripe_connect_error', [ 'error_message' => $e->getMessage() ] );
185 $this->send_json( array( 'status' => LATEPOINT_STATUS_ERROR, 'message' => $e->getMessage() ) );
186 }
187 $this->send_json( array( 'status' => LATEPOINT_STATUS_SUCCESS, 'message' => OsStripeConnectHelper::get_connection_buttons_and_status( $env ) ) );
188 }
189
190
191 public function heartbeat() {
192 $payload = @file_get_contents( 'php://input' );
193 $data = json_decode( $payload, true );
194
195 if ( empty( $data['wp_latepoint_server_token'] ) ) {
196 $this->send_json( array( 'status' => LATEPOINT_STATUS_ERROR, 'message' => 'Token is missing' ), 404 );
197 }
198 if ( $data['wp_latepoint_server_token'] != OsStripeConnectHelper::get_server_token() ) {
199 $this->send_json( array( 'status' => LATEPOINT_STATUS_ERROR, 'message' => 'Invalid Token' ), 404 );
200 }
201
202 $this->send_json( array( 'status' => LATEPOINT_STATUS_SUCCESS, 'message' => 'Heartbeat detected' ), 200 );
203 }
204
205 public function create_payment_intent() {
206 try {
207 OsStepsHelper::set_required_objects( $this->params );
208
209 $booking_form_page_url = $this->params['booking_form_page_url'] ?? wp_get_original_referer();
210 $order_intent = OsOrderIntentHelper::create_or_update_order_intent( OsStepsHelper::$cart_object, OsStepsHelper::$restrictions, OsStepsHelper::$presets, $booking_form_page_url );
211
212 if ( ! $order_intent->is_bookable() ) {
213 throw new Exception( empty($order_intent->get_error_messages()) ? __( 'Booking slot is not available anymore.', 'latepoint' ) : implode(', ', $order_intent->get_error_messages()) );
214 }
215
216 if ( OsSettingsHelper::get_settings_value( OsSettingsHelper::append_payment_env_key( 'stripe_connect_account_id' ) ) ) {
217 $payment_intent_data = OsStripeConnectHelper::generate_payment_intent_id_and_secret_for_order_intent( $order_intent );
218 $payment_intent_id = $payment_intent_data['id'];
219 $payment_intent_client_secret = $payment_intent_data['client_secret'];
220 } else {
221 throw new Exception( __( 'Stripe connect account ID not set', 'latepoint' ) );
222 }
223
224
225 // update cart with payment intent id
226 OsStepsHelper::$cart_object->payment_token = $payment_intent_id;
227
228 // cart_item_data might be changed after filters run, make sure to get the latest version
229 $cart_items_data = json_decode( $order_intent->cart_items_data, true );
230 $payment_data = json_decode( $order_intent->payment_data, true );
231
232 $payment_data['token'] = $payment_intent_id;
233 $order_intent->update_attributes( [
234 'cart_items_data' => wp_json_encode( $cart_items_data ),
235 'payment_data' => wp_json_encode( $payment_data )
236 ] );
237 if ( $this->get_return_format() == 'json' ) {
238 $this->send_json( [
239 'status' => LATEPOINT_STATUS_SUCCESS,
240 'continue_order_intent_url' => OsOrderIntentHelper::generate_continue_intent_url( $order_intent->intent_key ),
241 'payment_intent_id' => $payment_intent_id,
242 'payment_intent_secret' => $payment_intent_client_secret,
243 'order_intent_key' => $order_intent->intent_key
244 ] );
245 }
246 } catch ( Exception $e ) {
247 if ( $this->get_return_format() == 'json' ) {
248 $this->send_json( array( 'status' => LATEPOINT_STATUS_ERROR, 'message' => $e->getMessage() ) );
249 }
250 }
251
252 }
253 }
254
255
256 endif;
257