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