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:
90
connector-miravia/classes/shared/MiraviaCategory.php
Normal file
90
connector-miravia/classes/shared/MiraviaCategory.php
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
59
connector-miravia/classes/shared/MiraviaCombination.php
Normal file
59
connector-miravia/classes/shared/MiraviaCombination.php
Normal 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;
|
||||
}
|
||||
}
|
||||
243
connector-miravia/classes/shared/MiraviaFeed.php
Normal file
243
connector-miravia/classes/shared/MiraviaFeed.php
Normal 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);
|
||||
}
|
||||
}
|
||||
134
connector-miravia/classes/shared/MiraviaFilter.php
Normal file
134
connector-miravia/classes/shared/MiraviaFilter.php
Normal 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;
|
||||
}
|
||||
}
|
||||
63
connector-miravia/classes/shared/MiraviaLang.php
Normal file
63
connector-miravia/classes/shared/MiraviaLang.php
Normal 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',
|
||||
];
|
||||
}
|
||||
541
connector-miravia/classes/shared/MiraviaLink.php
Normal file
541
connector-miravia/classes/shared/MiraviaLink.php
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
186
connector-miravia/classes/shared/MiraviaProduct.php
Normal file
186
connector-miravia/classes/shared/MiraviaProduct.php
Normal 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 '';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user