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:
142
connector-miravia/classes/Services/Mirakl/Order.php
Normal file
142
connector-miravia/classes/Services/Mirakl/Order.php
Normal file
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
|
||||
namespace Sweeper\PlatformMiddleware\Services\Mirakl;
|
||||
|
||||
use Mirakl\MMP\Shop\Request\Order\Document\DownloadOrdersDocumentsRequest;
|
||||
use Mirakl\MMP\Shop\Request\Order\Document\GetOrderDocumentsRequest;
|
||||
use Mirakl\MMP\Shop\Request\Order\Get\GetOrdersRequest;
|
||||
use Mirakl\MMP\Shop\Request\Order\Tracking\UpdateOrderTrackingInfoRequest;
|
||||
use Sweeper\GuzzleHttpRequest\Response;
|
||||
|
||||
/**
|
||||
* Mirakl - Catch 订单相关接口
|
||||
* Created by Sweeper PhpStorm.
|
||||
* Author: Sweeper <wili.lixiang@gmail.com>
|
||||
* DateTime: 2024/2/26 13:18
|
||||
* @Package \Sweeper\PlatformMiddleware\Services\Mirakl\Order
|
||||
*/
|
||||
class Order extends Request
|
||||
{
|
||||
|
||||
/**
|
||||
* 获取订单列表
|
||||
* Author: Sweeper <wili.lixiang@gmail.com>
|
||||
* DateTime: 2024/2/26 13:42
|
||||
* @doc https://help.mirakl.net/help/api-doc/seller/mmp.html#OR11
|
||||
* @param array $params
|
||||
* @return Response
|
||||
*/
|
||||
public function getOrders(array $params = []): Response
|
||||
{
|
||||
// Building request
|
||||
$request = new GetOrdersRequest($params);
|
||||
|
||||
// Calling the API
|
||||
// $response = $this->clientMMP()->run($request);
|
||||
// $response = $this->clientMMP()->getOrders($request);
|
||||
// $response = $this->clientMMP()->raw()->getOrders($request);
|
||||
return $this->execute($this->clientMMP(), $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 接受或拒绝订单行
|
||||
* Author: Sweeper <wili.lixiang@gmail.com>
|
||||
* DateTime: 2024/2/26 13:44
|
||||
* @doc https://help.mirakl.net/help/api-doc/seller/mmp.html#OR21
|
||||
* @param string $orderId
|
||||
* @param array $orderLines {'order_lines':[{'accepted':true,'id':'Order_00012-B-1'}]}
|
||||
* @return Response
|
||||
*/
|
||||
public function acceptRefuseOrder(string $orderId, array $orderLines): Response
|
||||
{
|
||||
// return static::handleResponse($this->clientMMP()->run(new AcceptOrderRequest($orderId, $orderLines)));// 官方SDK调不通,不知道错误信息,只提示400
|
||||
return static::put($this->buildRequestUri("orders/{$orderId}/accept"), $orderLines, static::buildHeaders($this->getConfig('api_key')));
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消订单
|
||||
* Author: Sweeper <wili.lixiang@gmail.com>
|
||||
* DateTime: 2024/2/26 13:45
|
||||
* @doc https://help.mirakl.net/help/api-doc/seller/mmp.html#OR29
|
||||
* @param string $orderId
|
||||
* @return Response
|
||||
*/
|
||||
public function cancelOrder(string $orderId): Response
|
||||
{
|
||||
// return static::handleResponse($this->clientMMP()->run(new CancelOrderRequest($orderId)));
|
||||
return static::put($this->buildRequestUri("orders/{$orderId}/cancel"), [], static::buildHeaders($this->getConfig('api_key')));
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新特定订单的承运商跟踪信息
|
||||
* Author: Sweeper <wili.lixiang@gmail.com>
|
||||
* DateTime: 2024/2/26 13:45
|
||||
* @doc https://help.mirakl.net/help/api-doc/seller/mmp.html#OR23
|
||||
* @param string $orderId
|
||||
* @param array $trackingOrderInfo {'carrier_code':'UPS','carrier_name':'UPS','carrier_url':'https://ups.com','tracking_number':'5555'}
|
||||
* @return Response
|
||||
*/
|
||||
public function updateOrderTrackingInfo(string $orderId, array $trackingOrderInfo): Response
|
||||
{
|
||||
return $this->execute($this->clientMMP(), new UpdateOrderTrackingInfoRequest($orderId, $trackingOrderInfo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单文档
|
||||
* Author: Sweeper <wili.lixiang@gmail.com>
|
||||
* DateTime: 2024/2/26 13:46
|
||||
* @doc https://help.mirakl.net/help/api-doc/seller/mmp.html#OR72
|
||||
* @param array $orderIds
|
||||
* @return Response
|
||||
* @throws \Mirakl\Core\Exception\RequestValidationException
|
||||
*/
|
||||
public function getOrderDocuments(array $orderIds): Response
|
||||
{
|
||||
// Building request
|
||||
$request = new GetOrderDocumentsRequest($orderIds);
|
||||
|
||||
// Calling the API
|
||||
return $this->execute($this->clientMMP(), $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载订单文档
|
||||
* Author: Sweeper <wili.lixiang@gmail.com>
|
||||
* DateTime: 2024/2/26 13:47
|
||||
* @doc https://help.mirakl.net/help/api-doc/seller/mmp.html#OR73
|
||||
* @param array $orderIds
|
||||
* @param bool $download
|
||||
* @return Response
|
||||
*/
|
||||
public function downloadOrdersDocuments(array $orderIds, bool $download = false): Response
|
||||
{
|
||||
// Building request
|
||||
$request = new DownloadOrdersDocumentsRequest();
|
||||
$request->setOrderIds($orderIds);
|
||||
$result = $this->clientMMP()->downloadOrdersDocuments($request);
|
||||
if ($download) {
|
||||
$result->download();
|
||||
}
|
||||
if (ob_get_length()) {
|
||||
ob_clean();
|
||||
}
|
||||
$result->getFile()->rewind();
|
||||
|
||||
return Response::success('Success', [$result->getFile()->fpassthru()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验订单发货 Valid the shipment of the order
|
||||
* Author: Sweeper <wili.lixiang@gmail.com>
|
||||
* DateTime: 2024/2/26 13:48
|
||||
* @doc https://help.mirakl.net/help/api-doc/seller/mmp.html#OR24
|
||||
* @param string $orderId
|
||||
* @return Response
|
||||
*/
|
||||
public function shipOrder(string $orderId): Response
|
||||
{
|
||||
// return static::handleResponse($this->clientMMP()->run(new ShipOrderRequest($orderId)));
|
||||
return static::put($this->buildRequestUri("orders/{$orderId}/ship"), [], static::buildHeaders($this->getConfig('api_key')));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Sweeper\PlatformMiddleware\Services\Mirakl;
|
||||
|
||||
use Mirakl\MMP\Shop\Request\Shipping\GetShippingCarriersRequest;
|
||||
use Sweeper\GuzzleHttpRequest\Response;
|
||||
|
||||
/**
|
||||
* Mirakl - Catch 平台配置相关接口
|
||||
* Created by Sweeper PhpStorm.
|
||||
* Author: Sweeper <wili.lixiang@gmail.com>
|
||||
* DateTime: 2024/2/26 13:16
|
||||
* @Package \Sweeper\PlatformMiddleware\Services\Mirakl\PlatformSetting
|
||||
*/
|
||||
class PlatformSetting extends Request
|
||||
{
|
||||
|
||||
/**
|
||||
* 列出所有承运商信息
|
||||
* Author: Sweeper <wili.lixiang@gmail.com>
|
||||
* DateTime: 2024/2/26 13:17
|
||||
* @param array $params
|
||||
* @return Response
|
||||
*/
|
||||
public function carriers(array $params = []): Response
|
||||
{
|
||||
return $this->execute($this->clientMMP(), new GetShippingCarriersRequest($params));
|
||||
}
|
||||
|
||||
}
|
||||
166
connector-miravia/classes/Services/Mirakl/Request.php
Normal file
166
connector-miravia/classes/Services/Mirakl/Request.php
Normal file
@@ -0,0 +1,166 @@
|
||||
<?php
|
||||
|
||||
namespace Sweeper\PlatformMiddleware\Services\Mirakl;
|
||||
|
||||
use Mirakl\Core\Client\AbstractApiClient;
|
||||
use Mirakl\Core\Request\AbstractRequest;
|
||||
use Mirakl\MCI\Shop\Client\ShopApiClient as MCIShopApiClient;
|
||||
use Mirakl\MCM\Shop\Client\ShopApiClient as MCMShopApiClient;
|
||||
use Mirakl\MMP\Shop\Client\ShopApiClient as MMPShopApiClient;
|
||||
use Sweeper\GuzzleHttpRequest\Response;
|
||||
use Sweeper\HelperPhp\Tool\ClientRequest;
|
||||
|
||||
/**
|
||||
* Mirakl - Catch - 请求处理
|
||||
* Created by Sweeper PhpStorm.
|
||||
* Author: Sweeper <wili.lixiang@gmail.com>
|
||||
* DateTime: 2024/2/26 13:01
|
||||
* @Package \Sweeper\PlatformMiddleware\Services\Mirakl\Request
|
||||
*/
|
||||
class Request extends ClientRequest
|
||||
{
|
||||
|
||||
public const OPEN_API_URI = 'https://marketplace.catch.com.au/';
|
||||
|
||||
public const OPEN_API_URL = 'https://marketplace.catch.com.au/api/';
|
||||
|
||||
/** @var string */
|
||||
public const TYPE_MCI = 'MCI';
|
||||
|
||||
/** @var string */
|
||||
public const TYPE_MCM = 'MCM';
|
||||
|
||||
/** @var string Marketplace for Products Seller API */
|
||||
public const TYPE_MMP = 'MMP';
|
||||
|
||||
/**
|
||||
* 获取 API 服务URL
|
||||
* Author: Sweeper <wili.lixiang@gmail.com>
|
||||
* DateTime: 2024/2/26 13:05
|
||||
* @return string
|
||||
*/
|
||||
protected function getServerDomain(): string
|
||||
{
|
||||
return static::OPEN_API_URI;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取服务请求的路径
|
||||
* Author: Sweeper <wili.lixiang@gmail.com>
|
||||
* DateTime: 2024/2/26 13:05
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
protected function getServerPath(string $path): string
|
||||
{
|
||||
return $this->getVersion() ? "/api/{$this->getVersion()}/{$path}" : "/api/{$path}";
|
||||
}
|
||||
|
||||
/**
|
||||
* 实例化客户端
|
||||
* Author: Sweeper <wili.lixiang@gmail.com>
|
||||
* DateTime: 2024/2/26 13:05
|
||||
* @param string $type
|
||||
* @return AbstractApiClient
|
||||
*/
|
||||
public function getClientByType(string $type = self::TYPE_MMP): AbstractApiClient
|
||||
{
|
||||
// Instantiating the Mirakl API Client
|
||||
switch ($type) {
|
||||
case static::TYPE_MCM:
|
||||
$shopApiClient = $this->clientMCM();
|
||||
break;
|
||||
case static::TYPE_MCI:
|
||||
$shopApiClient = $this->clientMCI();
|
||||
break;
|
||||
case static::TYPE_MMP:
|
||||
default:
|
||||
$shopApiClient = $this->clientMMP();
|
||||
break;
|
||||
}
|
||||
|
||||
return $shopApiClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* MMP 客户端
|
||||
* Author: Sweeper <wili.lixiang@gmail.com>
|
||||
* DateTime: 2024/2/26 13:05
|
||||
* @return MMPShopApiClient
|
||||
*/
|
||||
public function clientMMP(): MMPShopApiClient
|
||||
{
|
||||
// Instantiating the Mirakl API Client
|
||||
$shopApiClient = new MMPShopApiClient($this->getConfig('api_url'), $this->getConfig('api_key'), $this->getConfig('shop_id'));
|
||||
|
||||
return $shopApiClient->setOptions(['verify' => false, 'connect_timeout' => static::getConnectTimeout(), 'timeout' => static::getTimeout()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* MCI 客户端
|
||||
* Author: Sweeper <wili.lixiang@gmail.com>
|
||||
* DateTime: 2024/2/26 13:05
|
||||
* @return MCIShopApiClient
|
||||
*/
|
||||
public function clientMCI(): MCIShopApiClient
|
||||
{
|
||||
// Instantiating the Mirakl API Client
|
||||
$shopApiClient = new MCIShopApiClient($this->getConfig('api_url'), $this->getConfig('api_key'), $this->getConfig('shop_id'));
|
||||
|
||||
return $shopApiClient->setOptions(['verify' => false, 'connect_timeout' => static::getConnectTimeout(), 'timeout' => static::getTimeout()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* MCM 客户端
|
||||
* Author: Sweeper <wili.lixiang@gmail.com>
|
||||
* DateTime: 2024/2/26 13:05
|
||||
* @return MCMShopApiClient
|
||||
*/
|
||||
public function clientMCM(): MCMShopApiClient
|
||||
{
|
||||
// Instantiating the Mirakl API Client
|
||||
$shopApiClient = new MCMShopApiClient($this->getConfig('api_url'), $this->getConfig('api_key'), $this->getConfig('shop_id'));
|
||||
|
||||
return $shopApiClient->setOptions(['verify' => false, 'connect_timeout' => static::getConnectTimeout(), 'timeout' => static::getTimeout()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行请求 -> 解析响应
|
||||
* Author: Sweeper <wili.lixiang@gmail.com>
|
||||
* DateTime: 2024/2/26 13:05
|
||||
* @param AbstractApiClient $client
|
||||
* @param AbstractRequest $request
|
||||
* @return Response
|
||||
*/
|
||||
public function execute(AbstractApiClient $client, AbstractRequest $request): Response
|
||||
{
|
||||
/** @var \GuzzleHttp\Psr7\Response $result */
|
||||
// Calling the API
|
||||
// $response = $client->run($request);// $this->client()->getOrders($request); $this->client()->raw()->getOrders($request);
|
||||
|
||||
return $this->resolveResponse($client->run($request));// return json_decode($result->getBody()->getContents() ?? '', true) ?: [];
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建头选项
|
||||
* Author: Sweeper <wili.lixiang@gmail.com>
|
||||
* DateTime: 2024/2/26 13:07
|
||||
* @param string $authorization
|
||||
* @param array $options
|
||||
* @return array
|
||||
*/
|
||||
protected static function buildHeaders(string $authorization, array $options = []): array
|
||||
{
|
||||
return array_replace([
|
||||
'headers' => [
|
||||
'Content-Type' => 'application/json',
|
||||
'Authorization' => $authorization,
|
||||
'Accept' => "*/*",
|
||||
],
|
||||
'verify' => false,
|
||||
'connect_timeout' => 10,
|
||||
'timeout' => 60,
|
||||
], $options);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user