PluginProbe ʕ •ᴥ•ʔ
LatePoint – Calendar Booking Plugin for Appointments and Events / 5.6.2
LatePoint – Calendar Booking Plugin for Appointments and Events v5.6.2
5.6.7 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 / razorpay_connect_controller.php
latepoint / lib / controllers Last commit date
activities_controller.php 2 months ago auth_controller.php 3 months ago booking_form_settings_controller.php 3 months ago bookings_controller.php 3 weeks ago calendars_controller.php 3 months ago carts_controller.php 3 months ago controller.php 3 months ago customer_cabinet_controller.php 2 months ago customers_controller.php 3 months ago dashboard_controller.php 2 months ago default_agent_controller.php 3 months ago events_controller.php 3 months ago form_fields_controller.php 3 months ago integrations_controller.php 3 months ago invoices_controller.php 1 month ago manage_booking_by_key_controller.php 3 months ago manage_order_by_key_controller.php 3 months ago notifications_controller.php 3 months ago orders_controller.php 3 weeks ago pro_controller.php 3 weeks ago process_jobs_controller.php 3 months ago processes_controller.php 1 month ago razorpay_connect_controller.php 1 month ago search_controller.php 3 months ago services_controller.php 3 months ago settings_controller.php 2 months ago steps_controller.php 3 weeks ago stripe_connect_controller.php 2 months ago support_topics_controller.php 3 months ago todos_controller.php 3 months ago transactions_controller.php 3 months ago wizard_controller.php 2 months ago
razorpay_connect_controller.php
345 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 if ( ! class_exists( 'OsRazorpayConnectController' ) ) :
11
12 class OsRazorpayConnectController extends OsController {
13
14 function __construct() {
15 parent::__construct();
16 $this->action_access['public'] = array_merge( $this->action_access['public'], [ 'webhook', 'create_razorpay_order', 'create_razorpay_order_for_transaction' ] );
17 $this->views_folder = LATEPOINT_VIEWS_ABSPATH . 'razorpay_connect/';
18 }
19
20 private function get_env_from_params(): string {
21 return ( ! empty( $this->params['env'] ) && in_array( $this->params['env'], [ LATEPOINT_PAYMENTS_ENV_LIVE, LATEPOINT_PAYMENTS_ENV_DEV ] ) )
22 ? $this->params['env']
23 : OsSettingsHelper::get_payments_environment();
24 }
25
26 public function create_razorpay_order() {
27 try {
28 OsStepsHelper::set_required_objects( $this->params );
29
30 $booking_form_page_url = $this->params['booking_form_page_url'] ?? OsUtilHelper::get_referrer();
31 $order_intent = OsOrderIntentHelper::create_or_update_order_intent(
32 OsStepsHelper::$cart_object,
33 OsStepsHelper::$restrictions,
34 OsStepsHelper::$presets,
35 $booking_form_page_url,
36 OsStepsHelper::get_customer_object_id()
37 );
38
39 if ( ! $order_intent->is_bookable() ) {
40 throw new Exception( empty( $order_intent->get_error_messages() ) ? __( 'Booking slot is not available anymore.', 'latepoint' ) : implode( ', ', $order_intent->get_error_messages() ) );
41 }
42
43 if ( ! OsSettingsHelper::get_settings_value( OsSettingsHelper::append_payment_env_key( 'razorpay_connect_account_id' ) ) ) {
44 throw new Exception( __( 'Razorpay connect account ID not set', 'latepoint' ) );
45 }
46
47 $order_data = OsRazorpayConnectHelper::generate_razorpay_order_for_order_intent( $order_intent );
48
49 $order_data['options']['name'] = OsSettingsHelper::get_settings_value( 'razorpay_connect_company_name', 'RazorPay' );
50 $order_data['options']['description'] = 'LatePoint Order Intent Key: ' . $order_intent->intent_key;
51 $order_data['options']['image'] = OsImageHelper::get_image_url_by_id(
52 OsSettingsHelper::get_settings_value( 'razorpay_connect_logo_image_id', false ),
53 'thumbnail',
54 get_site_icon_url()
55 );
56 $order_data['options']['theme'] = [
57 'color' => OsSettingsHelper::get_settings_value( 'razorpay_connect_theme_color', '#4366ff' ),
58 ];
59 $order_data['options']['notes'] = [
60 'order_intent_key' => $order_intent->intent_key,
61 ];
62 $customer = OsStepsHelper::get_customer_object();
63 if ( $customer ) {
64 $order_data['options']['prefill'] = [
65 'name' => $customer->full_name,
66 'email' => $customer->email,
67 'contact' => $customer->phone,
68 ];
69 }
70
71 if ( $this->get_return_format() === 'json' ) {
72 $this->send_json(
73 [
74 'status' => LATEPOINT_STATUS_SUCCESS,
75 'continue_order_intent_url' => OsOrderIntentHelper::generate_continue_intent_url( $order_intent->intent_key ),
76 'order_intent_key' => $order_intent->intent_key,
77 'razorpay_order_id' => $order_data['order_id'],
78 'amount' => $order_data['amount'],
79 'currency' => $order_data['currency'],
80 'options' => $order_data['options'],
81 ]
82 );
83 }
84 } catch ( Exception $e ) {
85 if ( $this->get_return_format() === 'json' ) {
86 $this->send_json(
87 [
88 'status' => LATEPOINT_STATUS_ERROR,
89 'message' => $e->getMessage(),
90 ]
91 );
92 }
93 }
94 }
95
96 public function create_razorpay_order_for_transaction() {
97 try {
98 $invoice_access_key = sanitize_text_field( $this->params['key'] ?? '' );
99 if ( empty( $invoice_access_key ) ) {
100 throw new Exception( __( 'Invoice not found', 'latepoint' ) );
101 }
102 $invoice = OsInvoicesHelper::get_invoice_by_key( $invoice_access_key );
103 if ( ! ( $invoice instanceof OsInvoiceModel ) || $invoice->is_new_record() ) {
104 throw new Exception( __( 'Invoice not found', 'latepoint' ) );
105 }
106
107 $transaction_intent = OsTransactionIntentHelper::create_or_update_transaction_intent( $invoice, $this->params );
108
109 if ( ! OsSettingsHelper::get_settings_value( OsSettingsHelper::append_payment_env_key( 'razorpay_connect_account_id' ) ) ) {
110 throw new Exception( __( 'Razorpay connect account ID not set', 'latepoint' ) );
111 }
112
113 $order_data = OsRazorpayConnectHelper::generate_razorpay_order_for_transaction_intent( $transaction_intent );
114
115 $order_data['options']['name'] = OsSettingsHelper::get_settings_value( 'razorpay_connect_company_name', 'RazorPay' );
116 $order_data['options']['description'] = 'LatePoint Transaction Intent Key: ' . $transaction_intent->intent_key;
117 $order_data['options']['image'] = OsImageHelper::get_image_url_by_id(
118 OsSettingsHelper::get_settings_value( 'razorpay_connect_logo_image_id', false ),
119 'thumbnail',
120 get_site_icon_url()
121 );
122 $order_data['options']['theme'] = [
123 'color' => OsSettingsHelper::get_settings_value( 'razorpay_connect_theme_color', '#4366ff' ),
124 ];
125 $order_data['options']['notes'] = [
126 'transaction_intent_key' => $transaction_intent->intent_key,
127 ];
128 if ( ! empty( $transaction_intent->customer_id ) ) {
129 $customer = new OsCustomerModel( $transaction_intent->customer_id );
130 $order_data['options']['prefill'] = [
131 'name' => $customer->full_name,
132 'email' => $customer->email,
133 'contact' => $customer->phone,
134 ];
135 }
136
137 if ( $this->get_return_format() === 'json' ) {
138 $this->send_json(
139 [
140 'status' => LATEPOINT_STATUS_SUCCESS,
141 'continue_transaction_intent_url' => OsTransactionIntentHelper::generate_continue_intent_url( $transaction_intent->intent_key ),
142 'transaction_intent_key' => $transaction_intent->intent_key,
143 'razorpay_order_id' => $order_data['order_id'],
144 'amount' => $order_data['amount'],
145 'currency' => $order_data['currency'],
146 'options' => $order_data['options'],
147 ]
148 );
149 }
150 } catch ( Exception $e ) {
151 if ( $this->get_return_format() === 'json' ) {
152 $this->send_json(
153 [
154 'status' => LATEPOINT_STATUS_ERROR,
155 'message' => $e->getMessage(),
156 ]
157 );
158 }
159 }
160 }
161
162 public function webhook() {
163 $payload = @file_get_contents( 'php://input' );
164 $data = json_decode( $payload, true );
165
166 if ( empty( $data['server_token'] ) || empty( $data['razorpay_account_id'] ) || $data['server_token'] !== OsRazorpayConnectHelper::get_server_token() || $data['razorpay_account_id'] !== OsRazorpayConnectHelper::get_connect_account_id() ) {
167 http_response_code( 400 );
168 echo 'Validation issue with webhook';
169 exit();
170 }
171
172 if ( empty( $data['event'] ) || empty( $data['event']['type'] ) ) {
173 http_response_code( 400 );
174 exit();
175 }
176
177 $event = $data['event'];
178 switch ( $event['type'] ) {
179 case 'payment.captured':
180 if ( ! empty( $event['data']['order_intent_key'] ) ) {
181 $order_intent = OsOrderIntentHelper::get_order_intent_by_intent_key( $event['data']['order_intent_key'] );
182 if ( $order_intent->is_new_record() ) {
183 OsDebugHelper::log( 'Error processing Razorpay connect webhook: Order intent not found' );
184 http_response_code( 400 );
185 exit();
186 }
187 // Store the payment ID so process_payment() can verify it
188 $payment_data = json_decode( $order_intent->payment_data, true ) ?? [];
189 $payment_data['token'] = sanitize_text_field( $event['data']['payment_id'] ?? '' );
190 $order_intent->update_attributes( [ 'payment_data' => wp_json_encode( $payment_data ) ] );
191
192 if ( $order_intent->convert_to_order() ) {
193 http_response_code( 200 );
194 } else {
195 http_response_code( 400 );
196 OsDebugHelper::log( 'Error converting order intent', 'razorpay_connect_webhook', $order_intent->get_error_messages() );
197 }
198 }
199 if ( ! empty( $event['data']['transaction_intent_key'] ) ) {
200 $transaction_intent = OsTransactionIntentHelper::get_transaction_intent_by_intent_key( $event['data']['transaction_intent_key'] );
201 if ( $transaction_intent->is_new_record() ) {
202 OsDebugHelper::log( 'Error processing Razorpay connect webhook: Transaction intent not found' );
203 http_response_code( 400 );
204 exit();
205 }
206 $payment_data = json_decode( $transaction_intent->payment_data, true ) ?? [];
207 $payment_data['token'] = sanitize_text_field( $event['data']['payment_id'] ?? '' );
208 $transaction_intent->update_attributes( [ 'payment_data' => wp_json_encode( $payment_data ) ] );
209
210 if ( $transaction_intent->convert_to_transaction() ) {
211 http_response_code( 200 );
212 } else {
213 http_response_code( 400 );
214 OsDebugHelper::log( 'Error converting transaction intent', 'razorpay_connect_webhook' );
215 }
216 }
217 break;
218 }
219 exit();
220 }
221
222 public function start_connect_process() {
223 $env = $this->get_env_from_params();
224 OsSettingsHelper::save_setting_by_name( OsSettingsHelper::append_payment_env_key( 'enable_payment_processor_razorpay_connect', $env ), LATEPOINT_VALUE_ON );
225 $url = OsRazorpayConnectHelper::get_connect_url( $env );
226 $this->send_json(
227 [
228 'status' => LATEPOINT_STATUS_SUCCESS,
229 'url' => $url,
230 'message' => __( 'Redirecting to Razorpay', 'latepoint' ),
231 ]
232 );
233 }
234
235 public function disconnect_connect_account() {
236 $env = $this->get_env_from_params();
237 try {
238 $account_id = OsRazorpayConnectHelper::get_connect_account_id( $env );
239 $path = $account_id . '/server-tokens/' . OsRazorpayConnectHelper::get_server_token( $env ) . '/disconnect/';
240 $response = OsRazorpayConnectHelper::do_request( $path, '', 'DELETE', [], [], $env );
241 if ( $response['status']['code'] === 200 ) {
242 OsSettingsHelper::remove_setting_by_name( OsSettingsHelper::append_payment_env_key( 'razorpay_connect_charges_enabled', $env ) );
243 OsSettingsHelper::remove_setting_by_name( OsSettingsHelper::append_payment_env_key( 'razorpay_connect_account_id', $env ) );
244 OsSettingsHelper::remove_setting_by_name( OsSettingsHelper::append_payment_env_key( 'razorpay_connect_public_token', $env ) );
245 OsRazorpayConnectHelper::reset_server_token( $env );
246 } else {
247 OsDebugHelper::log( 'Razorpay Connect Error', 'razorpay_connect_disconnect_error', $response );
248 }
249 } catch ( Exception $e ) {
250 OsDebugHelper::log( 'Error disconnecting Razorpay account', 'razorpay_connect_error', [ 'error_message' => $e->getMessage() ] );
251 $this->send_json(
252 [
253 'status' => LATEPOINT_STATUS_ERROR,
254 'message' => $e->getMessage(),
255 ]
256 );
257 }
258 $this->send_json(
259 [
260 'status' => LATEPOINT_STATUS_SUCCESS,
261 'message' => OsRazorpayConnectHelper::get_connection_buttons_and_status( $env ),
262 ]
263 );
264 }
265
266 public function check_connect_status() {
267 $env = $this->get_env_from_params();
268 try {
269 $response = OsRazorpayConnectHelper::do_request( 'server-tokens/' . OsRazorpayConnectHelper::get_server_token( $env ) . '/status', '', 'GET', [], [], $env );
270 if ( $env === LATEPOINT_PAYMENTS_ENV_LIVE ) {
271 $fee_info = empty( $response['data']['transaction_fee_info'] ) ? '0' : $response['data']['transaction_fee_info'];
272 OsSettingsHelper::save_setting_by_name( 'razorpay_connect_transaction_fee_info', $fee_info );
273 }
274 if ( ! empty( $response['data'] ) && ! empty( $response['data']['account_id'] ) ) {
275 OsSettingsHelper::save_setting_by_name( OsSettingsHelper::append_payment_env_key( 'razorpay_connect_account_id', $env ), $response['data']['account_id'] );
276 OsSettingsHelper::save_setting_by_name( OsSettingsHelper::append_payment_env_key( 'razorpay_connect_public_token', $env ), $response['data']['public_token'] ?? '' );
277 if ( ! empty( $response['data']['charges_enabled'] ) ) {
278 OsSettingsHelper::save_setting_by_name( OsSettingsHelper::append_payment_env_key( 'razorpay_connect_charges_enabled', $env ), LATEPOINT_VALUE_ON );
279 } else {
280 OsSettingsHelper::remove_setting_by_name( OsSettingsHelper::append_payment_env_key( 'razorpay_connect_charges_enabled', $env ) );
281 }
282 } else {
283 OsSettingsHelper::remove_setting_by_name( OsSettingsHelper::append_payment_env_key( 'razorpay_connect_charges_enabled', $env ) );
284 OsSettingsHelper::remove_setting_by_name( OsSettingsHelper::append_payment_env_key( 'razorpay_connect_account_id', $env ) );
285 OsSettingsHelper::remove_setting_by_name( OsSettingsHelper::append_payment_env_key( 'razorpay_connect_public_token', $env ) );
286 }
287 if ( ! empty( $response['data']['active_site_urls'] ) ) {
288 OsSettingsHelper::save_setting_by_name( OsSettingsHelper::append_payment_env_key( 'razorpay_connect_duplicate_token_activations', $env ), $response['data']['active_site_urls'] );
289 } else {
290 OsSettingsHelper::remove_setting_by_name( OsSettingsHelper::append_payment_env_key( 'razorpay_connect_duplicate_token_activations', $env ) );
291 }
292 if ( ! empty( $response['data']['error'] ) ) {
293 OsDebugHelper::log( 'Error checking Razorpay connect status', 'razorpay_connect_error', [ 'error_message' => $response['data']['error'] ] );
294 }
295 } catch ( Exception $e ) {
296 OsDebugHelper::log( 'Error getting Razorpay connection status', 'razorpay_connect_error', [ 'error_message' => $e->getMessage() ] );
297 $this->send_json(
298 [
299 'status' => LATEPOINT_STATUS_ERROR,
300 'message' => $e->getMessage(),
301 ]
302 );
303 }
304 $this->send_json(
305 [
306 'status' => LATEPOINT_STATUS_SUCCESS,
307 'message' => OsRazorpayConnectHelper::get_connection_buttons_and_status( $env ),
308 ]
309 );
310 }
311
312 public function heartbeat() {
313 $payload = @file_get_contents( 'php://input' );
314 $data = json_decode( $payload, true );
315
316 if ( empty( $data['wp_latepoint_server_token'] ) ) {
317 $this->send_json(
318 [
319 'status' => LATEPOINT_STATUS_ERROR,
320 'message' => 'Token is missing',
321 ],
322 404
323 );
324 }
325 if ( $data['wp_latepoint_server_token'] !== OsRazorpayConnectHelper::get_server_token() ) {
326 $this->send_json(
327 [
328 'status' => LATEPOINT_STATUS_ERROR,
329 'message' => 'Invalid Token',
330 ],
331 404
332 );
333 }
334 $this->send_json(
335 [
336 'status' => LATEPOINT_STATUS_SUCCESS,
337 'message' => 'Heartbeat detected',
338 ],
339 200
340 );
341 }
342 }
343
344 endif;
345