PluginProbe ʕ •ᴥ•ʔ
CommerceBird – AI Command Center, ERP Integrations & B2B for WooCommerce (Zoho, Exact Online). / 2.8.5
CommerceBird – AI Command Center, ERP Integrations & B2B for WooCommerce (Zoho, Exact Online). v2.8.5
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 / Connectors / Connector.php
commercebird / admin / includes / Connectors Last commit date
Connector.php 2 months ago index.php 1 year ago
Connector.php
394 lines
1 <?php
2
3 namespace CommerceBird\Admin\Connectors;
4
5 use CommerceBird\Admin\Actions\Ajax\SettingsAjax;
6 use CommerceBird\Admin\Traits\LogWriter;
7 use WP_Error;
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 /**
14 * Connector class for interacting with the CommerceBird API and Exact Online.
15 *
16 * Provides methods for retrieving and saving data such as subscriptions, account settings,
17 * products, orders, and webhooks, as well as handling API requests and logging.
18 */
19 final class Connector {
20 use LogWriter;
21
22 const COST_CENTERS = 'customs/exact/cost-centers';
23 const COST_UNITS = 'customs/exact/cost-units';
24 const GL_ACCOUNTS = 'customs/exact/gl-accounts';
25 const INVOICE_LAYOUTS = 'customs/exact/invoice-layouts';
26 const JOURNAL_LIST = 'customs/exact/journal';
27 const EXACT_WAREHOUSES = 'customs/exact/warehouses';
28 const EXACT_GENERAL_SETTINGS = 'customs/exact/gen-settings';
29 const ITEM = 'customs/exact/bulk-items';
30 const CUSTOMER = 'customs/exact/bulk-customers';
31 const ORDER = 'customs/exact/bulk-orders';
32 const PAYMENT_STATUS = 'customs/exact/invoice-payment-status';
33 const WEBHOOKS = 'customs/exact/webhooks';
34 const WOO_WEBHOOKS = 'customs/woo/webhooks';
35 const CONNECT_EXACT = 'webapp/exact/auth-url/plugin';
36 const EXACT_DIVISIONS = 'webapp/exact/divisions/plugin';
37 const ACCOUNT_SETTINGS = 'customs/settings';
38 const SUBSCRIPTION = 'customs/subscriptions';
39 const EXACT_TAXMAPPING = 'customs/exact/settings/taxes';
40 const EXACT_VATCODES = 'customs/exact/settings/vat-codes';
41 const EXACT_PAYMENT_CONDITIONS = 'customs/exact/settings/payment-conditions';
42 const EXACT_PAYMENT_STATUS_MAPPING = 'customs/exact/settings/payment-status';
43 const EXACT_RESET_CONNECTION = 'webapp/exact/disconnect/plugin';
44 const API = 'https://api.commercebird.com';
45 // const API = 'https://6c09a9134e1f.ngrok-free.app';
46
47 /**
48 * Get Subscription data from CommerceBird API.
49 *
50 * @param integer $subscription_id
51 * @param string $store_token
52 * @return array|WP_Error
53 */
54 public function get_subscription( $data ) {
55 $response = $this->request(
56 self::SUBSCRIPTION,
57 'POST',
58 $data
59 );
60 if ( is_wp_error( $response ) ) {
61 $this->write_log( $response->get_error_message(), 'commercebird-connector' );
62 return new WP_Error( 'request_failed', $response->get_error_message() );
63 }
64 if ( isset( $response['code'] ) && 200 !== $response['code'] ) {
65 $this->write_log( $response['message'], 'commercebird-connector' );
66 return new WP_Error( 'request_failed', $response['message'] );
67 }
68 return $response['data'];
69 }
70
71 /**
72 * Connect to exact online and get authorization URL.
73 *
74 * @param array $data array ( callback_url, topic )
75 * @return array|WP_Error array ( webhook_id, topic )
76 */
77 public function create_woo_webbhook() {
78 return $this->request( self::WOO_WEBHOOKS, 'POST' );
79 }
80
81 /**
82 * Connect to exact online and get authorization URL.
83 *
84 * @param array $data array ( callback_url, topic )
85 * @return array|WP_Error array ( webhook_id, topic )
86 */
87 public function connect_exact( $domain_suffix ) {
88 return $this->request( self::CONNECT_EXACT, 'GET', array(), array( 'domain' => $domain_suffix ) );
89 }
90
91 public function get_account_settings() {
92 return $this->request( self::ACCOUNT_SETTINGS );
93 }
94 public function save_account_settings( array $data ) {
95 return $this->request( self::ACCOUNT_SETTINGS, 'POST', $data );
96 }
97
98 public function get_exact_divisions() {
99 return $this->request( self::EXACT_DIVISIONS );
100 }
101
102 public function cost_centers() {
103 return $this->request( self::COST_CENTERS );
104 }
105
106 public function gl_accounts() {
107 return $this->request( self::GL_ACCOUNTS );
108 }
109
110 /**
111 * Get the list of journals from Exact Online.
112 *
113 * @return array|WP_Error
114 */
115 public function journals() {
116 return $this->request( self::JOURNAL_LIST );
117 }
118
119 /**
120 * Get the list of invoice layouts from Exact Online.
121 *
122 * @return array|WP_Error
123 */
124 public function invoice_layouts() {
125 return $this->request( self::INVOICE_LAYOUTS );
126 }
127
128 /**
129 * Get the list warehouses from Exact Online.
130 *
131 * @return array|WP_Error
132 */
133 public function exact_warehouses() {
134 return $this->request( self::EXACT_WAREHOUSES );
135 }
136
137 /**
138 * Get mapped general settings for Exact Online.
139 *
140 * @return array|WP_Error
141 */
142 public function exact_general_settings() {
143 return $this->request( self::EXACT_GENERAL_SETTINGS );
144 }
145
146 /**
147 * Save general settings for Exact Online.
148 *
149 * @param array $data mapped general settings data
150 * @return array|WP_Error
151 */
152 public function save_exact_general_settings( array $data ) {
153 return $this->request( self::EXACT_GENERAL_SETTINGS, 'POST', $data );
154 }
155
156 /**
157 * Get exact vat codes.
158 *
159 * @return array|WP_Error
160 */
161 public function get_exact_vat_codes() {
162 return $this->request( self::EXACT_VATCODES );
163 }
164
165 /**
166 * Get mapped taxes for Exact Online.
167 *
168 * @return array|WP_Error
169 */
170 public function get_exact_tax_mapping() {
171 return $this->request( self::EXACT_TAXMAPPING );
172 }
173
174 /**
175 * Save mapped taxes for Exact Online.
176 *
177 * @param array $data mapped taxes data
178 * @return array|WP_Error
179 */
180 public function save_exact_tax_mapping( array $data ) {
181 return $this->request( self::EXACT_TAXMAPPING, 'POST', $data );
182 }
183
184 /**
185 * Get mapped payment conditions for Exact Online.
186 *
187 * @return array|WP_Error
188 */
189 public function get_exact_payment_conditions() {
190 return $this->request( self::EXACT_PAYMENT_CONDITIONS );
191 }
192
193 /**
194 * Get mapped payment staus for Exact Online.
195 *
196 * @return array|WP_Error
197 */
198 public function get_exact_payment_status_mapping() {
199 return $this->request( self::EXACT_PAYMENT_STATUS_MAPPING );
200 }
201
202 /**
203 * Save mapped payment status for Exact Online.
204 *
205 * @param array $data mapped taxes data
206 * @return array|WP_Error
207 */
208 public function save_exact_payment_status_mapping( array $data ) {
209 return $this->request( self::EXACT_PAYMENT_STATUS_MAPPING, 'POST', $data );
210 }
211
212 /**
213 * Suscribe to Exact Online Webhooks. Pass the webhook URL to Exact Online and Topic
214 *
215 * @param array $data array ( callback_url, topic )
216 * @return array|WP_Error array ( webhook_id, topic )
217 */
218 public function subscribe_exact_webhooks( array $data ) {
219 $response = $this->request( self::WEBHOOKS, 'POST', $data );
220 return $response['code'] === 200 ? $response['data'] : $response['message'];
221 }
222
223 /**
224 * Collect customer or account id
225 *
226 * @param array $customer array ( customer_email, company_name )
227 *
228 * @return array|WP_Error array ( account_id, company_id )
229 * @throws WP_Error Invalid customer if empty
230 */
231 public function customer( bool $reset_sync = false ): array|string {
232 $params = $reset_sync ? array( 'reset_sync' => 'true' ) : array();
233 $response = $this->request( self::CUSTOMER, 'GET', array(), $params );
234 if ( $response['code'] === 200 ) {
235 return $response['data'];
236 }
237 if ( $response['code'] === 404 ) {
238 return array( 'customers' => array() );
239 }
240 return $response['message'];
241 }
242 /**
243 * Collect customer or account id
244 *
245 * @param array $customer array ( customer_email, company_name )
246 *
247 * @return array|WP_Error array ( account_id, company_id )
248 * @throws WP_Error Invalid customer if empty
249 */
250 public function order( bool $reset_sync = false ): array|string {
251 $params = $reset_sync ? array( 'reset_sync' => 'true' ) : array();
252 $response = $this->request( self::ORDER, 'GET', array(), $params );
253 if ( $response['code'] === 200 ) {
254 return $response['data'];
255 }
256 if ( $response['code'] === 404 ) {
257 return array( 'orders' => array() );
258 }
259 return $response['message'];
260 }
261
262 /**
263 * Send Order Ids to Exact Online using the bulk endpoint
264 *
265 * @param array $data array ( order_ids )
266 * @return array|WP_Error array ( order_ids )
267 * @throws WP_Error Invalid order if empty
268 */
269 public function send_orders( array $data ) {
270 $response = $this->request( self::ORDER, 'POST', $data );
271 return $response['code'] === 200 ? $response['data'] : $response['message'];
272 }
273
274 /**
275 * Get item ID by product ID
276 *
277 * @param int $id of the item
278 *
279 * @return array|WP_Error The ID of the item or an error object.
280 */
281 public function products( bool $reset_sync = false ): array|string {
282 $params = $reset_sync ? array( 'reset_sync' => 'true' ) : array();
283 $response = $this->request( self::ITEM, 'GET', array(), $params );
284 if ( $response['code'] === 200 ) {
285 return $response['data'];
286 }
287 if ( $response['code'] === 404 ) {
288 return array( 'items' => array() );
289 }
290 return $response['message'];
291 }
292
293 public function cost_units() {
294 return $this->request( self::COST_UNITS );
295 }
296
297 /**
298 * Get payment status
299 *
300 * @param array
301 *
302 * @return array|WP_Error array ( payment_status )
303 */
304 public function payment_status( array $data ) {
305 $response = $this->request( self::PAYMENT_STATUS, 'POST', $data, array() );
306 return $response['code'] === 200 ? $response['data'] : $response['message'];
307 }
308
309 /**
310 * Disconnect Exact Online Connection via DELETE call
311 *
312 * @return array|WP_Error
313 */
314 public function reset_exact_connection() {
315 $response = $this->request( self::EXACT_RESET_CONNECTION, 'DELETE', array() );
316 return $response;
317 }
318
319 /**
320 * Generate request URL
321 *
322 * @param string $endpoint Endpoint for the API request.
323 * @param string $method HTTP method (GET, POST, DELETE).
324 * @param array $data Data to be sent in the request body.
325 * @param array $params Query parameters to be appended to the URL.
326 * @return array|WP_Error
327 */
328 public function request( string $endpoint, string $method = 'GET', array $data = array(), array $params = array() ) {
329 // $token = ExactOnlineAjax::instance()->get_token();
330 $token = SettingsAjax::instance()->get_token();
331
332 $token = ! empty( $token ) ? $token : '';
333 $url = sprintf( '%s/%s?token=%s', self::API, $endpoint, $token );
334 if ( ! empty( $params ) ) {
335 $url .= '&' . http_build_query( $params );
336 }
337
338 // if current site contains localhost, use https://dev.commercebird.com.
339 $current_site_url = isset( $_SERVER['HTTP_HOST'] ) ? sanitize_url( wp_unslash( $_SERVER['HTTP_HOST'] ) ) : '';
340 $site_url = empty( $current_site_url ) || str_contains( $current_site_url, 'localhost' ) ? 'https://dev.commercebird.com' : site_url();
341 if ( 'POST' === $method ) {
342 $response = wp_remote_post(
343 $url,
344 array(
345 'headers' => array(
346 'Accept' => 'application/json',
347 'Content-Type' => 'application/json',
348 'zohowooagent' => $site_url,
349 ),
350 'timeout' => 60,
351 'sslverify' => false,
352 'body' => wp_json_encode( $data ),
353 )
354 );
355 } elseif ( 'GET' === $method ) {
356 $response = wp_remote_get(
357 $url,
358 array(
359 'headers' => array(
360 'Accept' => 'application/json',
361 'zohowooagent' => $site_url,
362 'x-woozo-module' => $data['module'] ?? '',
363 ),
364 'timeout' => 60,
365 'sslverify' => false,
366 )
367 );
368 } elseif ( 'DELETE' === $method ) {
369 $response = wp_remote_request(
370 $url,
371 array(
372 'method' => 'DELETE',
373 'headers' => array(
374 'Accept' => 'application/json',
375 'Content-Type' => 'application/json',
376 'zohowooagent' => $site_url,
377 ),
378 'timeout' => 60,
379 'sslverify' => false,
380 )
381 );
382 } else {
383 return new WP_Error( 'invalid_method', 'Invalid HTTP method specified.' );
384 }
385
386 if ( is_wp_error( $response ) ) {
387 $this->write_log( $response->get_error_message(), 'commercebird-connector' );
388 return new WP_Error( 'request_failed', $response->get_error_message() );
389 }
390 $response = wp_remote_retrieve_body( $response );
391 return json_decode( $response, true );
392 }
393 }
394