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>
This commit is contained in:
Miravia Connector Bot
2025-07-17 08:11:23 +02:00
commit a7d7dbb164
61 changed files with 8501 additions and 0 deletions

View File

@@ -0,0 +1,90 @@
<?php
require_once dirname(__FILE__) . '/MiraviaLink.php';
class MiraviaCategory extends MiraviaLink
{
public function getCategories($treeFormat = false)
{
$url = $this->api_url . '/category/tree';
$ret = $this->CallAPI($url);
if($ret === false){
return false;
}
$resp = json_decode($ret, true);
if(!isset($resp['success']) || !$resp['success']){
$this->last_error = $resp['error'];
return false;
}
if(isset($resp['data'])){
if($treeFormat) {
return $resp['data'];
}else{
return $this->treeToList($resp['data']);
}
}
return false;
}
public function getBrands()
{
$url = $this->api_url . '/category/brands';
$ret = $this->CallAPI($url);
if($ret === false){
return false;
}
$resp = json_decode($ret, true);
if(!isset($resp['success']) || !$resp['success']){
$this->last_error = $resp['error'];
return false;
}
if(isset($resp['data'])){
return $resp['data'];
}
return false;
}
public function getAttributes($id)
{
$url = $this->api_url . '/category/' . $id . '/attributes';
$ret = $this->CallAPI($url);
if($ret === false){
return false;
}
$resp = json_decode($ret, true);
if(!isset($resp['success']) || !$resp['success']){
$this->last_error = isset($resp['error']) ? $resp['error'] : $ret;
return false;
}
if(isset($resp['data'])){
return $resp['data'];
}
return false;
}
private function treeToList($tree = [], $prefix = '')
{
$ret = [];
$separator = $prefix=='' ? '' : ' / ';
foreach ($tree as $item) {
$name = $item['name'];
if(isset($item['children'])) {
$children = $this->treeToList($item['children'], $prefix . $separator . $name);
foreach($children as $key => $child){
$ret[] = [
'id' => $child['id'],
'name' => $child['name']
];
}
}else{
$ret[] = [
'id' => $item['category_id'],
'name' => $prefix . $separator . $name
];
}
}
return $ret;
}
}

View File

@@ -0,0 +1,59 @@
<?php
class MiraviaCombination
{
public $sku = '';
public $ean_code = '';
public $price = 0;
public $special_price = 0;
public $quantity = 0;
public $images = [];
public $width = 0;
public $height = 0;
public $length = 0;
public $weight = 0;
public $variation = [];
public function addVariation($name, $value)
{
$this->variation[$name] = $value;
}
public function getData()
{
$combination = [];
$this->weight = round((float)$this->weight, 2);
foreach ($this as $key => $value){
if($key=='ean_code' && empty($value)){
continue;
}
if($key === 'images' && is_array($value) && !empty($value)){
$combination['Images'] = ['Image' => $value];
} else if($key !== 'images') {
$combination[$key] = $value;
}
}
return $combination;
}
public function getStockData()
{
$combination = [
'sku' => $this->sku,
'price' => $this->price,
'special_price' => $this->special_price,
'quantity' => $this->quantity >= 0 ? $this->quantity : 0
];
return $combination;
}
public function getOnlyStockData()
{
$combination = [
'sku' => $this->sku,
'quantity' => $this->quantity >= 0 ? $this->quantity : 0
];
return $combination;
}
}

View File

@@ -0,0 +1,243 @@
<?php
class MiraviaFeed
{
private $products = [];
public $miravia_feed_id = '';
public $debug = false;
public $default_width = 0;
public $default_height = 0;
public $default_length = 0;
public $default_weight = 0;
public function __construct()
{
//
}
public function setProducts($products)
{
foreach($products as $p) {
$this->products[$p->id] = $p;
}
}
public function addProduct(MiraviaProduct $product)
{
$this->products[$product->id] = $product;
}
public function getProducts()
{
return $this->products;
}
public function getProductsIds()
{
return array_keys($this->products);
}
public function getJsonCreate($offset = 0, $limit = 200)
{
$ret = [];
$prods = array_slice($this->products, $offset, $limit);
foreach ($prods as $p) {
if($p->created==0){
$this->setDefaultValues($p);
$ret[] = $p->getData();
}
}
if(empty($ret)){
return false;
}
$ret = [
'products' => $ret
];
$flags = $this->debug ? JSON_PRETTY_PRINT : 0;
return json_encode($ret, $flags);
}
public function getJsonUpdate($offset = 0, $limit = 200)
{
$ret = [];
$prods = array_slice($this->products, $offset, $limit);
foreach ($prods as $p) {
if($p->created==1 && strlen($p->id_miravia)>14){
$this->setDefaultValues($p);
$ret[] = $p->getData();
}
}
if(empty($ret)){
return false;
}
$ret = [
'products' => $ret
];
$flags = $this->debug ? JSON_PRETTY_PRINT : 0;
return json_encode($ret, $flags);
}
public function setDefaultValues(MiraviaProduct &$product)
{
if((float)$product->weight == 0) $product->weight = $this->default_weight;
if((int)$product->height == 0) $product->height = $this->default_height;
if((int)$product->width == 0) $product->width = $this->default_width;
if((int)$product->length == 0) $product->length = $this->default_length;
}
public function getJsonUpdateStock($onlyStock = false, $offset = 0, $limit = 200)
{
$ret = [];
$prods = array_slice($this->products, $offset, $limit);
foreach ($prods as $p) {
if(!empty($p->id_miravia)){
if($onlyStock) {
$ret[] = $p->getOnlyStockData();
}else{
$ret[] = $p->getStockData();
}
}
}
if(empty($ret)){
return false;
}
$ret = [
'products' => $ret
];
$flags = $this->debug ? JSON_PRETTY_PRINT : 0;
return json_encode($ret, $flags);
}
public function applyFilter($jsonFilter)
{
if(empty($jsonFilter)){
return false;
}
$filter = new MiraviaFilter($jsonFilter);
if($ids = $filter->parseRecords($this->products)){
return $ids;
}
return false;
}
public function removeProductsById($ids)
{
if(!is_array($ids)){
$ids = [$ids];
}
foreach ($ids as $id){
unset($this->products[$id]);
}
}
public function keepProductsById($ids)
{
if(!is_array($ids)){
$ids = [$ids];
}
$keys = array_keys($this->products);
$ids = array_diff($keys, $ids);
foreach ($ids as $id){
unset($this->products[$id]);
}
}
public function applyNumericFieldAction($ids, $fields, $action, $value)
{
$afields = explode(',',$fields);
foreach ($afields as $field){
foreach ($ids as $id){
if(isset($this->products[$id])){
switch ($action){
case 'increment':
if($this->products[$id]->{$field}) {
$this->products[$id]->{$field} = (float)$this->products[$id]->{$field} + (float)$value;
}
foreach($this->products[$id]->combinations as &$combi){
$combi->{$field} += (float)$value;
}
break;
case 'decrement':
if($this->products[$id]->{$field}) {
$this->products[$id]->{$field} -= (float)$value;
}
foreach($this->products[$id]->combinations as &$combi){
$combi->{$field} -= (float)$value;
}
break;
case 'increment_percent':
if($this->products[$id]->{$field}) {
$this->products[$id]->{$field} += ((float)$this->products[$id]->{$field} * (float)$value / 100);
}
foreach($this->products[$id]->combinations as &$combi){
$combi->{$field} += ((float)$combi->{$field} * (float)$value / 100);
}
break;
case 'decrement_percent':
if($this->products[$id]->{$field}) {
$this->products[$id]->{$field} -= ((float)$this->products[$id]->{$field} * (float)$value / 100);
}
foreach($this->products[$id]->combinations as &$combi){
$combi->{$field} -= ((float)$combi->{$field} * (float)$value / 100);
}
break;
case 'multiply':
if($this->products[$id]->{$field}) {
$this->products[$id]->{$field} = ((float)$this->products[$id]->{$field} * (float)$value );
}
foreach($this->products[$id]->combinations as &$combi){
$combi->{$field} = ((float)$combi->{$field} * (float)$value );
}
break;
case 'set':
if($this->products[$id]->{$field}) {
$this->products[$id]->{$field} = (float)$value;
}
foreach($this->products[$id]->combinations as &$combi){
$combi->{$field} = (float)$value;
}
break;
}
}
}
}
}
public function applyTextFieldAction($ids, $field, $template)
{
foreach ($ids as $id) {
if (isset($this->products[$id])) {
$replaces = [
'name' => $this->products[$id]->name,
'description' => $this->products[$id]->description,
'short_description' => $this->products[$id]->short_description,
'manufacturer' => $this->products[$id]->getInfoValue('manufacturer'),
'supplier' => $this->products[$id]->getInfoValue('supplier'),
'category' => $this->products[$id]->getInfoValue('category'),
];
$this->products[$id]->{$field} = $template;
foreach($replaces as $search => $replace){
$this->products[$id]->{$field} = str_replace('%' . $search .'%', $replace, $this->products[$id]->{$field});
}
}
}
}
public function applyLogisticsAction($ids, $delivery, $warehouse)
{
foreach ($ids as $id) {
if (isset($this->products[$id])) {
$this->products[$id]->delivery = $delivery;
$this->products[$id]->warehouse = $warehouse;
}
}
}
public function getProductCount()
{
return sizeof($this->products);
}
}

View File

@@ -0,0 +1,134 @@
<?php
class MiraviaFilter
{
private $definition;
public function __construct($json)
{
$this->definition = json_decode($json, true);
}
/*
* Return a list of keys
*/
public function parseRecords($products)
{
if(!is_array($this->definition)){
return false;
}
$ret = [];
if(is_array($products)) {
foreach ($products as $key => $product) {
if ($this->parseGroup($this->definition, $product)) {
// condition is met
$ret[] = $product->id;
}else{
//$ret[] = "NO: " . $key;
}
}
}
return $ret;
}
private function parseGroup($condition, $product)
{
$final_result = false;
$rules_parsed = 0;
foreach ($condition as $rule){
$operator = $rule['logical_operator'];
if(!isset($rule['element_rule_id'])){
// group
$result = $this->parseGroup($rule, $product);
}else{
$result = $this->parseCondition($rule['condition'], $product);
}
if($rules_parsed==0){
$final_result = $result;
}else{
switch ($operator){
case 'OR':
$final_result = $final_result || $result;
break;
case 'AND':
$final_result = $final_result && $result;
break;
}
}
}
return $final_result;
}
private function parseCondition($condition, $product)
{
switch ($condition['field']){
case 'product_name':
$field = $product->name;
break;
case 'price':
$field = $product->price;
break;
case 'specific_price':
$field = $product->special_price;
break;
case 'stock':
$field = $product->quantity;
break;
case 'category':
$field = $product->info['id_category'];
break;
case 'supplier':
$field = $product->info['id_supplier'];
break;
case 'manufacturer':
$field = $product->info['id_manufacturer'];
break;
}
switch($condition['operator']){
case 'equal':
$value = $condition['filterValue'][0];
return $field==$value;
case 'not_equal':
$value = $condition['filterValue'][0];
return $field!=$value;
case 'less':
$value = $condition['filterValue'][0];
return $field<$value;
case 'less_or_equal':
$value = $condition['filterValue'][0];
return $field<=$value;
case 'greater':
$value = $condition['filterValue'][0];
return $field>$value;
case 'greater_or_equal':
$value = $condition['filterValue'][0];
return $field>=$value;
case 'begins_with':
$value = $condition['filterValue'][0];
return (substr($field, 0, strlen($value)) === $value);
case 'contains':
$value = $condition['filterValue'][0];
return (stripos($field, $value)!=false);
case 'ends_with':
$value = $condition['filterValue'][0];
return (substr($field, -1 * strlen($value)) === $value);
case 'not_begins_with':
$value = $condition['filterValue'][0];
return !(substr($field, 0, strlen($value)) === $value);
case 'not_contains':
$value = $condition['filterValue'][0];
return !(stripos($field, $value)!=false);
case 'not_ends_with':
$value = $condition['filterValue'][0];
return !(substr($field, -1 * strlen($value)) === $value);
case 'is_null':
case 'is_empty':
return empty($field);
case 'is_not_null':
case 'is_not_empty':
return !empty($field);
}
return false;
}
}

View File

@@ -0,0 +1,63 @@
<?php
class MiraviaLang
{
const ENGLISH = 'en';
const ARABIC = 'ar';
const GERMAN = 'de';
const SPANISH = 'es';
const FRENCH = 'fr';
const INDONESIAN = 'in';
const ITALIAN = 'it';
const HEBREW = 'iw';
const JAPANESE = 'ja';
const KOREAN = 'ko';
const DUTCH = 'nl';
const POLISH = 'pl';
const PORTUGUESE = 'pt';
const RUSSIAN = 'ru';
const THAI = 'th';
const TURKISH = 'tr';
const VIETNAMESE = 'vi';
public static $LanguagesISO = [
'ENGLISH' => 'en',
'ARABIC' => 'ar',
'GERMAN' => 'de',
'SPANISH' => 'es',
'FRENCH' => 'fr',
'INDONESIAN' => 'in',
'ITALIAN' => 'it',
'HEBREW' => 'iw',
'JAPANESE' => 'ja',
'KOREAN' => 'ko',
'DUTCH' => 'nl',
'POLISH' => 'pl',
'PORTUGUESE' => 'pt',
'RUSSIAN' => 'ru',
'THAI' => 'th',
'TURKISH' => 'tr',
'VIETNAMESE' => 'vi',
];
public static $Languages = [
'en' => 'en_US',
'ar' => 'ar_MA',
'de' => 'de_DE',
'es' => 'es_ES',
'fr' => 'fr_FR',
'in' => 'in_ID',
'it' => 'it_IT',
'iw' => 'iw_IL',
'ja' => 'ja_JP',
'ko' => 'ko_KR',
'nl' => 'nl_NL',
'pl' => 'pl_PL',
'pt' => 'pt_BR',
'ru' => 'ru_RU',
'th' => 'th_TH',
'tr' => 'tr_TR',
'vi' => 'vi_VN',
];
}

View File

@@ -0,0 +1,541 @@
<?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)
{
$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
));
}
$result = curl_exec($curl);
if($result === false){
$this->last_error = curl_error($curl);
}
curl_close($curl);
return $result;
}
}

View File

@@ -0,0 +1,186 @@
<?php
class MiraviaProduct
{
public $id = 0;
public $id_miravia = '';
public $miravia_status = '';
public $created = 0;
public $sku = '';
public $reference_sku = '';
public $lang = 'es-ES'; // ISO lang code
public $name = '';
public $short_description = '';
public $description = '';
public $brand = 'no brand';
public $model = '';
public $ean_code = '';
public $warranty = '';
public $id_category = '';
public $id_brand = '';
public $images = []; // Public URLs
public $video = '';
public $price = 0;
public $special_price = 0;
public $quantity = 0;
public $width = 0;
public $height = 0;
public $length = 0;
public $weight = 0;
public $warehouse = '';
public $delivery = '';
public $extra_attributes = []; // [ "id_attribute" => "value", ... ]
public $combinations = []; // Array of MiraviaCombination class
public $info = []; // Internal info (for filters)
protected $private_vars = ['private_vars', 'error', 'id', 'combinations', 'info'];
public $error = '';
public function __construct()
{
//
}
public function addAttr($key = false, $value = false) {
if($key and $value) {
$this->extra_attributes[$key] = $value;
}
}
public function getData()
{
$product = [];
foreach ($this as $key => $value){
if(!in_array($key, $this->private_vars)){
if($key === 'images' && is_array($value) && !empty($value)){
$product['Images'] = ['Image' => $value];
} else if($key !== 'images') {
$product[$key] = $value;
}
}
}
$combinations = $this->getCombinations();
$product['combinations'] = $combinations;
return $product;
}
public function getStockData()
{
$combis = [];
foreach ($this->combinations as $combination){
$combis[] = $combination->getStockData();
}
if(count($combis)==0){
$combis =[[
'sku' => $this->sku,
'price' => $this->price,
'special_price' => $this->special_price,
'quantity' => $this->quantity >= 0 ? $this->quantity : 0
]];
$this->reference_sku = $this->sku;
}
$ret = [
'id' => $this->id,
'id_miravia' => $this->id_miravia,
'sku' => $this->sku,
'combinations' => $combis
];
if(!empty($this->warehouse)){
$ret['warehouse'] = $this->warehouse;
}
return $ret;
}
public function getOnlyStockData()
{
$combis = [];
foreach ($this->combinations as $combination){
$combis[] = $combination->getOnlyStockData();
}
if(count($combis)==0){
$combis =[[
'sku' => $this->sku,
'quantity' => $this->quantity >= 0 ? $this->quantity : 0
]];
$this->reference_sku = $this->sku;
}
$ret = [
'id' => $this->id,
'id_miravia' => $this->id_miravia,
'sku' => $this->sku,
'combinations' => $combis
];
if(!empty($this->warehouse)){
$ret['warehouse'] = $this->warehouse;
}
return $ret;
}
public function getJSON($pretty = false)
{
$flags = $pretty ? JSON_PRETTY_PRINT : 0;
return json_encode($this->getData(), $flags);
}
public function getCombinations()
{
$ret = [];
foreach ($this->combinations as $combination){
$ret[] = $combination->getData();
}
return $ret;
}
public function createProduct($apiKey)
{
if(!empty($this->id_miravia)){
return $this->updateProduct($apiKey);
}
$jreq = json_encode($this->getData());
$link = new MiraviaLink($apiKey);
$ret = $link->createProduct($jreq);
if($ret == false) {
$this->error = $link->last_error;
}
if(isset($ret['data'])){
if(isset($ret['data']['item_id'])){
$this->id_miravia = $ret['data']['item_id'];
}
}
return true;
}
public function updateProduct($apiKey)
{
if(empty($this->id_miravia)){
$this->error = 'Invalid Miravia Id Product';
return false;
}
$jreq = json_encode($this->getData());
$link = new MiraviaLink($apiKey);
$ret = $link->updateProduct($this->id_miravia, $jreq);
if($ret == false) {
$this->error = $link->last_error;
}
if(isset($ret['data'])){
if(isset($ret['data']['item_id'])){
$this->id_miravia = $ret['data']['item_id'];
}
return true;
}
if(isset($ret['message'])){
$this->error = $ret['message'];
}
return false;
}
public function getInfoValue($field)
{
if(isset($this->info[$field])){
return $this->info[$field];
}
return '';
}
}