PluginProbe ʕ •ᴥ•ʔ
CommerceBird – AI Command Center, ERP Integrations & B2B for WooCommerce (Zoho, Exact Online). / 2.3.9
CommerceBird – AI Command Center, ERP Integrations & B2B for WooCommerce (Zoho, Exact Online). v2.3.9
3.0.3 3.0.2 3.0.1 trunk 2.2.14 2.2.15 2.2.16 2.2.17 2.2.18 2.2.19 2.3.0 2.3.1 2.3.10 2.3.11 2.3.12 2.3.13 2.3.14 2.3.2 2.3.3 2.3.4 2.3.5 2.3.6 2.3.7 2.3.8 2.3.9 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.4.5 2.4.6 2.5.0 2.5.1 2.5.2 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.6.5 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 2.7.8 2.7.9 2.7.91 2.7.92 2.7.93 2.8.0 2.8.1 2.8.2 2.8.3 2.8.4 2.8.5 2.9.0 2.9.1 2.9.2 2.9.3 3.0.0
commercebird / admin / includes / Actions / Ajax / ZohoCRMAjax.php
commercebird / admin / includes / Actions / Ajax Last commit date
AcfAjax.php 1 year ago ExactOnlineAjax.php 1 year ago ZohoCRMAjax.php 1 year ago ZohoInventoryAjax.php 1 year ago index.php 1 year ago
ZohoCRMAjax.php
369 lines
1 <?php
2
3 namespace CommerceBird\Admin\Actions\Ajax;
4
5 use CMBIRD_Auth_Zoho;
6 use CMBIRD_API_Handler_Zoho;
7 use CommerceBird\Admin\Actions\Sync\ZohoCRMSync;
8 use CommerceBird\Admin\Template;
9 use CommerceBird\Admin\Traits\AjaxRequest;
10 use CommerceBird\Admin\Traits\OptionStatus;
11 use CommerceBird\Admin\Traits\Singleton;
12 use CommerceBird\Admin\Traits\LogWriter;
13 use Throwable;
14
15
16 if ( ! defined( 'ABSPATH' ) ) {
17 exit;
18 }
19 /**
20 * Initializes the Zoho CRM class.
21 * @since 1.0.0
22 * @return void
23 */
24 final class ZohoCRMAjax {
25
26 use Singleton;
27 use AjaxRequest;
28 use OptionStatus;
29 use LogWriter;
30
31
32
33 private const FORMS = array(
34 'connect' => array(
35 'token',
36 ),
37 'product' => array(
38 'importProducts',
39 ),
40 'order' => array( 'range' ),
41 'customer' => array(
42 'importCustomers',
43 ),
44 'fields' => array(
45 'form',
46 'module',
47 ),
48 );
49 private const ACTIONS = array(
50 'save_sync_order_via_cron' => 'sync_order',
51 'get_zcrm_connect' => 'connection_get',
52 'save_zcrm_connect' => 'connection_set',
53 'reset_zcrm_connect' => 'connection_reset',
54 'is_zcrm_connected' => 'connection_done',
55 'import_zcrm_product' => 'product_import',
56 'map_zcrm_product' => 'product_map',
57 'map_zcrm_customer' => 'customer_map',
58 'map_zcrm_order' => 'order_map',
59 'export_zcrm_order' => 'order_export',
60 'refresh_zcrm_fields' => 'refresh_zcrm_fields',
61 'zcrm_get_custom_fields' => 'zcrm_get_custom_fields',
62 'zcrm_save_custom_fields' => 'zcrm_save_custom_fields',
63 'zcrm_reset_custom_fields' => 'zcrm_reset_custom_fields',
64 'zcrm_fields' => 'get_zcrm_fields',
65 'zcrm_handle_code' => 'handle_code',
66 );
67 private const OPTIONS = array(
68 'connect' => array(
69 'token' => 'commercebird-exact-online-token',
70 ),
71 'zcrm_sales_orders_fields' => 'zcrm_sales_orders_fields',
72 'zcrm_contacts_fields' => 'zcrm_contacts_fields',
73 'zcrm_products_fields' => 'zcrm_products_fields',
74 );
75
76 public function __construct() {
77 $this->load_actions();
78 }
79
80 /**
81 * Sets the connection for the Zoho crm API.
82 */
83 public function connection_set(): void {
84 $this->verify(
85 array(
86 'account_domain',
87 'client_id',
88 'client_secret',
89 'redirect_uri',
90 ),
91 );
92 try {
93 $crm_url = sprintf( 'https://www.zohoapis.%s/', $this->data['account_domain'] );
94 update_option( 'cmbird_zoho_crm_domain', $this->data['account_domain'] );
95 update_option( 'cmbird_zoho_crm_cid', $this->data['client_id'] );
96 update_option( 'cmbird_zoho_crm_cs', $this->data['client_secret'] );
97 update_option( 'cmbird_zoho_crm_url', $crm_url );
98 update_option( 'cmbird_authorization_redirect_uri', $this->data['redirect_uri'] );
99 $redirect = esc_url_raw(
100 'https://accounts.zoho.'
101 . $this->data['account_domain']
102 . '/oauth/v2/auth?response_type=code&client_id='
103 . $this->data['client_id'] . '&scope=ZohoCRM.users.ALL,ZohoCRM.bulk.ALL,ZohoCRM.modules.ALL,ZohoCRM.settings.ALL,ZohoCRM.org.ALL,profile.userphoto.READ,ZohoFiles.files.CREATE&redirect_uri='
104 . $this->data['redirect_uri'] . '&prompt=consent&access_type=offline&state='
105 . wp_create_nonce( Template::NAME )
106 );
107 $this->response = array(
108 'redirect' => $redirect,
109 'message' => 'We are redirecting you to zoho. please wait...',
110 );
111 } catch (Throwable $throwable) {
112 $this->errors = array( 'message' => $throwable->getMessage() );
113 }
114
115 $this->serve();
116 }
117
118 /**
119 * Retrieves the connection details.
120 *
121 * @return void
122 */
123 public function connection_get(): void {
124 $this->verify();
125 $this->response['account_domain'] = get_option( 'cmbird_zoho_crm_domain' );
126 $this->response['client_id'] = get_option( 'cmbird_zoho_crm_cid' );
127 $this->response['client_secret'] = get_option( 'cmbird_zoho_crm_cs' );
128 $this->response['crm_url'] = get_option( 'cmbird_zoho_crm_url' );
129 $this->response['redirect_uri'] = get_option( 'cmbird_authorization_redirect_uri' );
130 $this->serve();
131 }
132
133 /**
134 * Handles the oAuth code.
135 */
136 public function handle_code(): void {
137 $this->verify();
138 if ( array_key_exists( 'code', $this->request ) ) {
139 $class_functions = new CMBIRD_Auth_Zoho();
140 $code = $this->request['code'];
141 try {
142 $access_token = $class_functions->get_zoho_access_token( $code, 'zoho_crm' );
143 if ( array_key_exists( 'access_token', $access_token ) ) {
144 update_option( 'cmbird_zoho_crm_auth_code', $code );
145 update_option( 'cmbird_zoho_crm_access_token', $access_token['access_token'] );
146 update_option( 'cmbird_zoho_crm_refresh_token', $access_token['refresh_token'] );
147 update_option( 'cmbird_zoho_crm_timestamp', strtotime( gmdate( 'Y-m-d H:i:s' ) ) + $access_token['expires_in'] );
148 $this->response = (array) $access_token;
149 } else {
150 $this->errors = (array) $access_token;
151 }
152 } catch (Throwable $throwable) {
153 $this->errors = array( 'message' => $throwable->getMessage() );
154 }
155 }
156 $this->serve();
157 }
158
159 /**
160 * Resets the connection by deleting specific options from the database.
161 */
162 public function connection_reset(): void {
163 $this->verify();
164 try {
165 $options = array(
166 'cmbird_zoho_crm_domain',
167 'cmbird_zoho_crm_cid',
168 'cmbird_zoho_crm_cs',
169 'cmbird_zoho_crm_url',
170 'cmbird_zoho_crm_access_token',
171 );
172 foreach ( $options as $zi_option ) {
173 delete_option( $zi_option );
174 }
175 $this->response = array( 'message' => 'Reset successfully!' );
176 } catch (Throwable $throwable) {
177 $this->errors = array( 'message' => $throwable->getMessage() );
178 }
179
180 $this->serve();
181 }
182
183
184 public function connection_done() {
185 $this->verify();
186 $zoho_crm_url = get_option( 'cmbird_zoho_crm_url' );
187 $url = $zoho_crm_url . 'crm/v7/org';
188 $execute_curl_call_handle = new CMBIRD_API_Handler_Zoho();
189 $json = $execute_curl_call_handle->execute_curl_call_get( $url );
190 if ( is_wp_error( $json ) ) {
191 $this->errors = array( 'message' => $json->get_error_message() );
192 } elseif ( empty( $json ) ) {
193 $this->errors = array( 'message' => 'We lost connection with zoho. please refresh page.' );
194 } else {
195 $this->response = ! empty( $json->org ) ? (array) $json->org[0] : [];
196 // schedule a wp cron to refresh the token after one hour from now.
197 if ( ! wp_next_scheduled( 'zcrm_refresh_token' ) ) {
198 wp_schedule_event( time() + 3600, 'hourly', 'zcrm_refresh_token' );
199 } else {
200 // unschedule first and reschedule.
201 wp_unschedule_event( wp_next_scheduled( 'zcrm_refresh_token' ), 'zcrm_refresh_token' );
202 wp_schedule_event( time() + 3600, 'hourly', 'zcrm_refresh_token' );
203 }
204 }
205 $this->serve();
206 }
207
208 /**
209 * Get Zoho CRM custom fields.
210 * @since 1.0.0
211 * @return void
212 */
213 public function refresh_zcrm_fields() {
214 $module = isset( $_GET['module'] ) ? sanitize_text_field( wp_unslash( $_GET['module'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
215 if ( empty( $module ) ) {
216 $this->errors['message'] = 'Module name is required.';
217 } else {
218 $fields = ( new ZohoCRMSync() )->get_custom_fields( $module );
219 if ( is_wp_error( $fields ) ) {
220 $this->errors['message'] = $fields->get_error_message();
221 } else {
222 $option_name = 'zcrm_' . strtolower( $module ) . '_fields';
223 update_option( self::OPTIONS[ $option_name ], $fields );
224 $this->response = array( 'message' => 'Refresh successfully!' );
225 $this->response['fields'] = $fields;
226 }
227 $this->serve();
228 }
229
230 }
231
232 /**
233 * Get Zoho CRM fields from wordpress database.
234 */
235 public function get_zcrm_fields() {
236 $module = isset( $_GET['module'] ) ? sanitize_text_field( wp_unslash( $_GET['module'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
237 if ( empty( $module ) ) {
238 $this->errors['message'] = 'Module name is required.';
239 } else {
240 $fields = get_option( 'zcrm_' . strtolower( $module ) . '_fields', array() );
241 $this->response['fields'] = $fields;
242 $this->serve();
243 }
244 }
245
246 /**
247 * Retrieves the fields and serves the response.
248 *
249 * @return object
250 */
251 public function zcrm_get_custom_fields(): void {
252
253 $module = isset( $_GET['module'] ) ? sanitize_text_field( wp_unslash( $_GET['module'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
254
255 if ( empty( $module ) ) {
256 $this->errors['message'] = 'Module name is required.';
257 } else {
258 $this->verify();
259 $option_name = 'zcrm_' . strtolower( $module ) . '_custom_fields';
260 $this->response['form'] = get_option( $option_name, array() );
261 $this->serve();
262 }
263 }
264
265 /**
266 * Sets the custom fields for the form.
267 *
268 * @return void
269 */
270 public function zcrm_save_custom_fields(): void {
271 $this->verify( self::FORMS['fields'] );
272 $module = isset( $this->data['module'] ) ? $this->data['module'] : '';
273 if ( empty( $module ) ) {
274 $this->errors['message'] = 'Module name is required.';
275 } else {
276 try {
277 $option_name = 'zcrm_' . strtolower( $module ) . '_custom_fields';
278 update_option( $option_name, $this->data['form'] );
279 $this->response = array( 'message' => 'saved' );
280 } catch (Throwable $throwable) {
281 $this->errors = array( 'message' => $throwable->getMessage() );
282 }
283 $this->serve();
284 }
285 }
286
287 /**
288 * Resets the fields.
289 *
290 * @return void
291 */
292 public function zcrm_reset_custom_fields(): void {
293 $module = isset( $_GET['module'] ) ? sanitize_text_field( wp_unslash( $_GET['module'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
294 if ( empty( $module ) ) {
295 $this->errors['message'] = 'Module name is required.';
296 } else {
297 $this->verify();
298 $option_name = 'zcrm_' . strtolower( $module ) . '_custom_fields';
299 delete_option( $option_name );
300 $this->response = array( 'message' => 'Reset successfully!' );
301 $this->serve();
302 }
303 }
304
305 /**
306 * Export Orders to Zoho CRM.
307 *
308 * @param int $start_date_raw The start date.
309 * @param int $end_date_raw The end date.
310 */
311 public function export_order( $start_date_raw, $end_date_raw ) {
312 // $fd = fopen( __DIR__ . '/export_order.log', 'a+' );
313
314 $start_date = gmdate( 'Y-m-d H:i:s', $start_date_raw );
315 $end_date = gmdate( 'Y-m-d H:i:s', $end_date_raw );
316 // Define the order statuses to exclude
317 $exclude_statuses = array( 'wc-failed', 'wc-cancelled' );
318 $posts_per_page = 20;
319 $paged = 1;
320
321 do {
322 // Query to get orders
323 $args = array(
324 'date_created' => $start_date . '...' . $end_date,
325 'status' => array_diff( array_keys( wc_get_order_statuses() ), $exclude_statuses ),
326 'limit' => $posts_per_page,
327 'paged' => $paged,
328 'orderby' => 'date',
329 'order' => 'ASC',
330 'return' => 'ids',
331 );
332 $orders = wc_get_orders( $args );
333 // Loop through orders and schedule them for Zoho CRM sync
334 foreach ( $orders as $order_id ) {
335 // Use WC Action Scheduler to sync the order to Zoho CRM
336 $existing_schedule = as_has_scheduled_action( 'sync_zcrm_order', array( $order_id ) );
337 if ( ! $existing_schedule ) {
338 as_schedule_single_action( time(), 'sync_zcrm_order', array( $order_id ) );
339 }
340 }
341 // Increment the offset for the next batch
342 ++$paged;
343 } while ( ! empty( $orders ) );
344 // fclose( $fd );
345 }
346
347 public function order_export() {
348 $this->verify( self::FORMS['order'] );
349 if ( empty( $this->data ) || empty( $this->data['range'] ) ) {
350 $this->response['success'] = false;
351 $this->response['message'] = __( 'Select dates', 'commercebird' );
352 $this->serve();
353 }
354 // Set the date range to last 30 days
355 $start_date = strtotime( $this->data['range'][0] );
356 $end_date = strtotime( $this->data['range'][1] );
357 $zoho_crm_access_token = get_option( 'cmbird_zoho_crm_access_token' );
358 if ( empty( $zoho_crm_access_token ) ) {
359 $this->response['success'] = false;
360 $this->response['message'] = __( 'Zoho CRM is not Connected.', 'commercebird' );
361 $this->serve();
362 }
363 $this->export_order( $start_date, $end_date );
364 $this->response['success'] = true;
365 $this->response['message'] = __( 'Exported', 'commercebird' );
366 $this->serve();
367 }
368 }
369