Miravia Connector Bot 09d24aa191 Fix image upload structure for Miravia API compliance
🔧 Bug Fixes:
- Fixed product image structure to match Miravia API requirements
- Updated MiraviaProduct.php getData() method to wrap images in {"Image": [...]} format
- Updated MiraviaCombination.php getData() method to wrap SKU images properly
- Resolved error "[4224] The Main image of the product is required"

📋 Changes:
- Modified getData() methods to transform flat image arrays to nested structure
- Product images: images[] → Images: {"Image": [...]}
- SKU images: images[] → Images: {"Image": [...]}
- Maintains backward compatibility for empty image arrays

🎯 Impact:
- Product uploads will now pass Miravia's image validation
- Both product-level and SKU-level images properly formatted
- Complies with official Miravia API documentation structure

🤖 Generated with Claude Code (https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-21 09:55:11 +02:00

572 lines
16 KiB
PHP

<?php
class MiraviaLink
{
protected $api_url = 'https://miravia.wecomm.es';
protected $api_key = '';
public $last_error = '';
public $request_id = '';
public $insecure_mode = true;
public $sandbox_mode = false;
public function __construct($api_key = '')
{
$this->api_key = $api_key;
if( strpos($api_key, '_f6649cb881216ce050bd0e3') ){
$this->sandbox_mode = true;
$this->api_url = 'https://sandbox.miravia.wecomm.es';
}
}
public function getRegisterUrl($callback_url)
{
$url = $this->api_url . '/token';
$ret = $this->CallAPI($url, 'POST',
array('callback_url' => $callback_url));
if($ret === false){
return '';
}
$response = json_decode($ret, true);
if(!is_array($response)){
$last_error = $ret;
return '';
}
if(isset($response['error'])){
$this->last_error = $response['error'];
}
$url = isset($response['url']) ? $response['url'] : '';
$this->request_id = isset($response['request_id']) ? $response['request_id'] : '';
return $url;
}
public function getSellerInfo($notify_endpoint = '')
{
$url = $this->api_url . '/seller/info';
$ret = $this->CallAPI($url);
if($ret === false){
return false;
}
$resp = json_decode($ret, true);
if(!isset($resp['success']) || !$resp['success']){
//$this->last_error = print_r($resp,true);
return false;
}
// update data
$url = $this->api_url . '/seller/update';
if(!empty($notify_endpoint)){
$data = [ 'notification_url' => $notify_endpoint ];
}
$data = json_encode($data);
$ret = $this->CallAPI($url, 'POST', $data);
if(isset($resp['seller'])){
return $resp['seller'];
}
//$this->last_error = print_r($resp,true);
return false;
}
public function getWarehouses()
{
$url = $this->api_url . '/seller/warehouses';
$ret = $this->CallAPI($url);
if($ret === false){
return false;
}
$resp = json_decode($ret, true);
if(!isset($resp['success']) || !$resp['success']){
$this->last_error = print_r($resp,true);
return false;
}
if(isset($resp['module'])){
return $resp['module'];
}
return false;
}
public function getFeedResult($document)
{
$url = $this->api_url . '/feed/result/' . $document;
$ret = $this->CallAPI($url);
return $ret;
}
public function createProduct($json_product)
{
$url = $this->api_url . '/product/create';
$ret = $this->CallAPI($url, 'POST', $json_product);
if($ret === false){
return false;
}
$resp = json_decode($ret, true);
if(!isset($resp['success'])){
return false;
}else if(!$resp['success']){
$this->last_error = $resp['message'];
if(isset($resp['detail'])){
foreach ($resp['detail'] as $det){
$this->last_error .= "\r" . $det['field'] . ': ' . $det['message'];
}
}
}
return $resp;
}
public function updateProduct($miravia_id, $json_product)
{
$url = $this->api_url . '/product/' . $miravia_id . '/update';
$ret = $this->CallAPI($url, 'POST', $json_product);
if($ret === false){
return false;
}
$resp = json_decode($ret, true);
if(!isset($resp['success'])){
return false;
}else if(!$resp['success']){
$this->last_error = $resp['message'];
if(isset($resp['detail'])){
foreach ($resp['detail'] as $det){
$this->last_error .= "\r" . $det['field'] . ': ' . $det['message'];
}
}
}
return $resp;
}
public function getProductList($page = 1, $pagesize = 50)
{
$url = $this->api_url . '/product/list?pagesize=' . $pagesize . '&page=' . $page;
$ret = $this->CallAPI($url);
return json_decode($ret, true);
}
public function getProductBySku($sku)
{
$url = $this->api_url . '/product/' . $sku . '/find';
$ret = $this->CallAPI($url);
return json_decode($ret);
}
public function getProductById($id)
{
$url = $this->api_url . '/product/' . $id . '/get';
$ret = $this->CallAPI($url);
return json_decode($ret);
}
public function updateStock($json_stock, $use_feed = false)
{
if($use_feed){
$url = $this->api_url . '/feed/stock';
}else{
$url = $this->api_url . '/product/update_stock';
}
$ret = $this->CallAPI($url, 'POST', $json_stock);
if($ret === false){
return false;
}
$resp = json_decode($ret, true);
if(!isset($resp['success'])){
return false;
}else if(!$resp['success']){
$this->last_error = $resp['message'];
if(isset($resp['detail'])){
foreach ($resp['detail'] as $det){
$this->last_error .= "\r" . $det['field'] . ': ' . $det['message'];
}
}
}
return $resp;
}
public function disableProducts($itemids)
{
if(!is_array($itemids)){
$itemids = [$itemids];
}
$itemids = json_encode([
'item_ids' => $itemids
]);
$url = $this->api_url . '/product/disable';
$ret = $this->CallAPI($url, 'POST', $itemids);
if($ret === false){
return false;
}
$resp = json_decode($ret, true);
if(!isset($resp['success'])){
return false;
}else {
return (bool) $resp['success'];
}
}
public function enableProducts($itemids)
{
if(!is_array($itemids)){
$itemids = [$itemids];
}
$itemids = json_encode([
'item_ids' => $itemids
]);
$url = $this->api_url . '/product/enable';
$ret = $this->CallAPI($url, 'POST', $itemids);
if($ret === false){
return false;
}
$resp = json_decode($ret, true);
if(!isset($resp['success'])){
return false;
}else {
return (bool) $resp['success'];
}
}
public function deleteProduct($itemid)
{
$url = $this->api_url . '/product/' . $itemid . '/delete';
$ret = $this->CallAPI($url, 'GET');
if($ret === false){
return false;
}
$resp = json_decode($ret, true);
if(!isset($resp['success'])){
return false;
}else {
return (bool) $resp['success'];
}
}
public function getFeeds()
{
$url = $this->api_url . '/feed/list';
$ret = $this->CallAPI($url);
if($ret === false){
return false;
}
$resp = json_decode($ret, true);
if(!isset($resp['success']) || !$resp['success']){
return false;
}
if(isset($resp['feeds'])){
return $resp['feeds'];
}
//$this->last_error = print_r($resp,true);
return false;
}
public function getFeedInfo($id)
{
$url = $this->api_url . '/feed/' . $id . '/get' ;
$ret = $this->CallAPI($url);
if($ret === false){
return false;
}
$resp = json_decode($ret, true);
if(isset($resp['feed_result'])) {
$response = [];
if(isset($resp['response'])) {
$response = $resp['response'];
}
$resp = $resp['feed_result'];
$resp['response'] = $response;
}else{
if(isset($resp['code'])){
$this->last_error = $resp['code'] . ': ' .
@$resp['message'] ?: '';
}
}
if(!isset($resp['success']) || !$resp['success']){
return false;
}
return $resp;
}
public function cancelFeed($id)
{
$url = $this->api_url . '/feed/' . $id . '/cancel' ;
$ret = $this->CallAPI($url, 'POST');
if($ret === false){
return false;
}
$resp = json_decode($ret, true);
if(isset($resp['feed_result'])) {
$resp = $resp['feed_result'];
}
if(!isset($resp['success']) || !$resp['success']){
return false;
}
return $resp;
}
public function sendFeed($data, $type = 'create')
{
$url = $this->api_url . '/feed/' . $type;
$ret = $this->CallAPI($url, 'POST', $data);
if($ret === false){
return false;
}
$resp = json_decode($ret, true);
if(!isset($resp['success'])){
return false;
}else if(!$resp['success']){
// $this->last_error = $resp['message'];
if(isset($resp['detail'])){
foreach ($resp['detail'] as $det){
$this->last_error .= "\r" . $det['field'] . ': ' . $det['message'];
}
}
}
return $resp;
}
/*
* $fromDate format: YYYY-MM-DD ('Y-m-d')
*/
public function getOrders(string $fromDate)
{
if($d = date_parse_from_format('Y-m-d', $fromDate)){
$fromDate = date('Y-m-d', mktime(0, 0, 0, $d['month'], $d['day'], $d['year']));
}else{
$this->last_error= 'Invalid date';
return false;
}
$url = $this->api_url . '/order/list';
$url .= '?from_date=' . $fromDate;
$ret = $this->CallAPI($url);
if($ret === false){
return false;
}
$resp = json_decode($ret, true);
if(!isset($resp['success']) || !$resp['success']){
return false;
}
return $resp;
}
public function getOrder($order_number)
{
$url = $this->api_url . '/order/' . $order_number . '/get';
$ret = $this->CallAPI($url);
if($ret === false){
return false;
}
$resp = json_decode($ret, true);
if(!isset($resp['success']) || !$resp['success']){
return false;
}
return $resp;
}
public function orderConfirmation($order_number, $status)
{
$url = $this->api_url . '/order/confirmation/' . $order_number . '/' . $status;
$ret = $this->CallAPI($url);
if($ret === false){
return false;
}
$resp = json_decode($ret, true);
if(!isset($resp['success']) || !$resp['success']){
return false;
}
return $resp;
}
public function orderPack($id_order, $products)
{
$url = $this->api_url . '/order/' . $id_order . '/pack';
if(is_array($products)){
$data = json_encode($products);
}else{
$data = $products;
}
$ret = $this->CallAPI($url , 'POST', $data);
if($ret === false){
return false;
}
$resp = json_decode($ret, true);
if(!isset($resp['success']) || !$resp['success']){
return false;
}
return $resp;
}
public function getShippingLabel($package_id)
{
$url = $this->api_url . '/order/label/' . $package_id;
$ret = $this->CallAPI($url);
if($ret === false){
return false;
}
$resp = json_decode($ret, true);
if(!isset($resp['success']) || !$resp['success']){
return false;
}
return $resp;
}
public function getDBSCarriers()
{
$url = $this->api_url . '/order/dbs/providers';
$ret = $this->CallAPI($url);
if($ret === false){
return false;
}
$resp = json_decode($ret, true);
if(isset($resp['result'])){
$resp = $resp['result'];
}
if(!isset($resp['success']) || !$resp['success']){
return false;
}
return $resp;
}
public function setDBSTracking($packages, $tracking, $provider)
{
if(!is_array($packages)){
$packages = [$packages];
}
$payload = [];
foreach ($packages as $package){
$payload['packages'][] = [
'package_id' => $package,
'tracking_number' => $tracking,
'shipment_provider_code' => $provider
];
}
$url = $this->api_url . '/order/dbs/update_tracking';
$data = json_encode($payload);
$ret = $this->CallAPI($url, 'POST', $data);
$resp = json_decode($ret, true);
if(!isset($resp['success']) || !$resp['success']){
$this->last_error = $ret;
return false;
}
return true;
}
public function subscribe($seconds, $message='')
{
$url = $this->api_url . '/seller/notify/' . (int)$seconds;
if(!empty($message)){
$url .= '?message=' . urlencode($message);
}
$ret = $this->CallAPI($url);
if($ret === false){
return false;
}
$resp = json_decode($ret, true);
if(!isset($resp['success']) || !$resp['success']){
return false;
}
return true;
}
public function purgeImageCache()
{
$url = $this->api_url . '/image/cache/purge';
$ret = $this->CallAPI($url);
return json_decode($ret, true);
}
protected function CallAPI($url, $method='GET', $data = false)
{
if(class_exists('LOG')) {
LOG::add("DEBUG API: Making {$method} request to: {$url}");
if($data && strlen($data) < 1000) {
LOG::add("DEBUG API: Request payload: " . $data);
} elseif($data) {
LOG::add("DEBUG API: Request payload size: " . strlen($data) . " bytes");
}
}
$curl = curl_init();
switch ($method)
{
case "POST":
curl_setopt($curl, CURLOPT_POST, 1);
if ($data) {
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
}
break;
case "PUT":
curl_setopt($curl, CURLOPT_PUT, 1);
break;
default:
if ($data)
$url = sprintf("%s?%s", $url, http_build_query($data));
}
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
if($this->insecure_mode) {
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
}
if(!empty($this->api_key)){
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
'Api-Token: ' . $this->api_key
));
if(class_exists('LOG')) {
LOG::add("DEBUG API: Using API token: " . substr($this->api_key, 0, 10) . "...");
}
}
$start_time = microtime(true);
$result = curl_exec($curl);
$end_time = microtime(true);
$response_time = round(($end_time - $start_time) * 1000, 2);
$http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if(class_exists('LOG')) {
LOG::add("DEBUG API: Response time: {$response_time}ms, HTTP code: {$http_code}");
if($result && strlen($result) < 2000) {
LOG::add("DEBUG API: Response: " . $result);
} elseif($result) {
LOG::add("DEBUG API: Response size: " . strlen($result) . " bytes");
}
}
if($result === false){
$this->last_error = curl_error($curl);
if(class_exists('LOG')) {
LOG::add("DEBUG API: CURL Error: " . $this->last_error);
}
}
curl_close($curl);
return $result;
}
}