210 lines
6.5 KiB
PHP
210 lines
6.5 KiB
PHP
<?php
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Softra Rent API client with JWT token caching.
|
|
* Uses native cURL (matching softra-test.php) instead of WP HTTP API.
|
|
*/
|
|
class Carei_Softra_API {
|
|
|
|
private static $instance = null;
|
|
|
|
private $base_url;
|
|
private $username;
|
|
private $password;
|
|
|
|
const TOKEN_TRANSIENT = 'carei_softra_token';
|
|
const TOKEN_EXPIRY = 3000; // 50 minutes (token valid 60 min)
|
|
|
|
private function __construct( $base_url, $username, $password ) {
|
|
$this->base_url = rtrim( $base_url, '/' );
|
|
$this->username = $username;
|
|
$this->password = $password;
|
|
}
|
|
|
|
public static function init( $base_url, $username, $password ) {
|
|
if ( null === self::$instance ) {
|
|
self::$instance = new self( $base_url, $username, $password );
|
|
}
|
|
return self::$instance;
|
|
}
|
|
|
|
public static function get_instance() {
|
|
return self::$instance;
|
|
}
|
|
|
|
/**
|
|
* Native cURL request — mirrors softra-test.php requestJson().
|
|
*/
|
|
private function curl_request( $method, $url, $payload = null, $extra_headers = array() ) {
|
|
$ch = curl_init( $url );
|
|
if ( false === $ch ) {
|
|
return new WP_Error( 'carei_curl_init', 'cURL init failed' );
|
|
}
|
|
|
|
$headers = array_merge( array( 'Accept: application/json' ), $extra_headers );
|
|
if ( null !== $payload ) {
|
|
$headers[] = 'Content-Type: application/json';
|
|
}
|
|
|
|
curl_setopt_array( $ch, array(
|
|
CURLOPT_CUSTOMREQUEST => strtoupper( $method ),
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_HTTPHEADER => $headers,
|
|
CURLOPT_TIMEOUT => 30,
|
|
CURLOPT_CONNECTTIMEOUT => 15,
|
|
) );
|
|
|
|
if ( null !== $payload ) {
|
|
curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( $payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES ) );
|
|
}
|
|
|
|
$raw = curl_exec( $ch );
|
|
$err = curl_error( $ch );
|
|
$status = (int) curl_getinfo( $ch, CURLINFO_HTTP_CODE );
|
|
curl_close( $ch );
|
|
|
|
if ( false === $raw ) {
|
|
return new WP_Error( 'carei_curl_error', 'cURL error: ' . $err );
|
|
}
|
|
|
|
$decoded = json_decode( $raw, true );
|
|
if ( ! is_array( $decoded ) ) {
|
|
$decoded = null;
|
|
}
|
|
|
|
return array(
|
|
'status' => $status,
|
|
'body' => $decoded,
|
|
'raw' => $raw,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get JWT token (cached in WP transient).
|
|
*/
|
|
public function get_token() {
|
|
$token = get_transient( self::TOKEN_TRANSIENT );
|
|
if ( false !== $token ) {
|
|
return $token;
|
|
}
|
|
|
|
$res = $this->curl_request( 'POST', $this->base_url . '/account/auth', array(
|
|
'login' => $this->username,
|
|
'password' => $this->password,
|
|
) );
|
|
|
|
if ( is_wp_error( $res ) ) {
|
|
return new WP_Error( 'carei_auth_failed', 'Softra API auth failed: ' . $res->get_error_message() );
|
|
}
|
|
|
|
if ( 200 !== $res['status'] || empty( $res['body']['token'] ) ) {
|
|
$detail = isset( $res['raw'] ) ? $res['raw'] : '';
|
|
return new WP_Error( 'carei_auth_failed', 'Softra API auth failed (HTTP ' . $res['status'] . '): ' . $detail );
|
|
}
|
|
|
|
$token = $res['body']['token'];
|
|
set_transient( self::TOKEN_TRANSIENT, $token, self::TOKEN_EXPIRY );
|
|
|
|
return $token;
|
|
}
|
|
|
|
/**
|
|
* Generic API request with auth.
|
|
*/
|
|
public function request( $method, $endpoint, $body = null, $query_params = array() ) {
|
|
$token = $this->get_token();
|
|
if ( is_wp_error( $token ) ) {
|
|
return $token;
|
|
}
|
|
|
|
$url = $this->base_url . $endpoint;
|
|
if ( ! empty( $query_params ) ) {
|
|
$url .= '?' . http_build_query( $query_params );
|
|
}
|
|
|
|
$res = $this->curl_request(
|
|
$method,
|
|
$url,
|
|
$body,
|
|
array( 'Authorization: Bearer ' . $token )
|
|
);
|
|
|
|
if ( is_wp_error( $res ) ) {
|
|
return $res;
|
|
}
|
|
|
|
if ( $res['status'] < 200 || $res['status'] >= 300 ) {
|
|
return new WP_Error(
|
|
'carei_api_error',
|
|
'Softra API error: HTTP ' . $res['status'],
|
|
array( 'status' => $res['status'], 'body' => $res['body'] )
|
|
);
|
|
}
|
|
|
|
return $res['body'];
|
|
}
|
|
|
|
// ─── Public API Methods ───────────────────────────────────────
|
|
|
|
public function get_branches() {
|
|
return $this->request( 'GET', '/branch/list' );
|
|
}
|
|
|
|
public function get_all_car_classes() {
|
|
return $this->request( 'GET', '/car/class/listAll' );
|
|
}
|
|
|
|
public function get_car_classes( $date_from, $date_to, $branch_name ) {
|
|
return $this->request( 'POST', '/car/class/list', array(
|
|
'dateFrom' => $date_from,
|
|
'dateTo' => $date_to,
|
|
'branchName' => $branch_name,
|
|
) );
|
|
}
|
|
|
|
public function get_car_models( $date_from, $date_to, $branch_name, $category = '' ) {
|
|
return $this->request( 'POST', '/car/model/list', array(
|
|
'dateFrom' => $date_from,
|
|
'dateTo' => $date_to,
|
|
'branchName' => $branch_name,
|
|
'category' => $category,
|
|
), array( 'includeBrandDetails' => 'true' ) );
|
|
}
|
|
|
|
public function get_pricelist( $category, $date_from, $date_to, $pickup_location, $language = 'pl', $currency = 'PLN' ) {
|
|
return $this->request( 'POST', '/pricelist/list', array(
|
|
'category' => $category,
|
|
'dateFrom' => $date_from,
|
|
'dateTo' => $date_to,
|
|
'pickUpLocation' => $pickup_location,
|
|
'language' => $language,
|
|
'currency' => $currency,
|
|
) );
|
|
}
|
|
|
|
public function get_pricing_summary( $params ) {
|
|
return $this->request( 'POST', '/rent/princingSummary', $params );
|
|
}
|
|
|
|
public function add_customer( $data ) {
|
|
return $this->request( 'POST', '/customer/add', $data );
|
|
}
|
|
|
|
public function make_booking( $data ) {
|
|
return $this->request( 'POST', '/rent/makebooking', $data );
|
|
}
|
|
|
|
public function confirm_booking( $reservation_id ) {
|
|
return $this->request( 'POST', '/rent/confirm', array(
|
|
'reservationId' => $reservation_id,
|
|
) );
|
|
}
|
|
|
|
public function get_agreements() {
|
|
return $this->request( 'GET', '/agreement/def/list' );
|
|
}
|
|
}
|