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-21 11:34:59 +02:00
parent dc50508c1c
commit 752600f337
79 changed files with 7970 additions and 36 deletions

View File

@@ -0,0 +1,12 @@
<?php
namespace Sweeper\PlatformMiddleware\Sdk\AeSdk\Iop;
class Constants
{
public static $log_level_debug = "DEBUG";
public static $log_level_info = "INFO";
public static $log_level_error = "ERROR";
}

View File

@@ -0,0 +1,303 @@
<?php
namespace Sweeper\PlatformMiddleware\Sdk\AeSdk\Iop;
use function Sweeper\PlatformMiddleware\root_path;
class IopClient
{
public $appkey;
public $secretKey;
public $gatewayUrl;
public $connectTimeout;
public $readTimeout;
protected $signMethod = "sha256";
protected $sdkVersion = "iop-sdk-php-20220608";
public $logLevel;
public function getAppkey()
{
return $this->appkey;
}
public function __construct($url = "", $appkey = "", $secretKey = "")
{
$length = strlen($url);
if ($length == 0) {
throw new \InvalidArgumentException("url is empty", 0);
}
$this->gatewayUrl = $url;
$this->appkey = $appkey;
$this->secretKey = $secretKey;
$this->logLevel = Constants::$log_level_error;
}
protected function generateSign($apiName, $params): string
{
ksort($params);
$stringToBeSigned = '';
if (str_contains($apiName, '/')) {//rest服务协议
$stringToBeSigned .= $apiName;
}
foreach ($params as $k => $v) {
$stringToBeSigned .= "$k$v";
}
unset($k, $v);
return strtoupper($this->hmac_sha256($stringToBeSigned, $this->secretKey));
}
public function hmac_sha256($data, $key): string
{
return hash_hmac('sha256', $data, $key);
}
public function curl_get($url, $apiFields = null, $headerFields = null)
{
$ch = curl_init();
foreach ($apiFields as $key => $value) {
$url .= "&" . "$key=" . urlencode($value);
}
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FAILONERROR, false);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
if ($headerFields) {
$headers = [];
foreach ($headerFields as $key => $value) {
$headers[] = "$key: $value";
}
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
unset($headers);
}
if ($this->readTimeout) {
curl_setopt($ch, CURLOPT_TIMEOUT, $this->readTimeout);
}
if ($this->connectTimeout) {
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->connectTimeout);
}
curl_setopt($ch, CURLOPT_USERAGENT, $this->sdkVersion);
//https ignore ssl check ?
if (strlen($url) > 5 && strtolower(substr($url, 0, 5)) === "https") {
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
}
$output = curl_exec($ch);
$errno = curl_errno($ch);
if ($errno) {
curl_close($ch);
throw new \RuntimeException($errno, 0);
}
$httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if (200 !== $httpStatusCode) {
throw new \RuntimeException($output, $httpStatusCode);
}
return $output;
}
public function curl_post($url, $postFields = null, $fileFields = null, $headerFields = null)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FAILONERROR, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
if ($this->readTimeout) {
curl_setopt($ch, CURLOPT_TIMEOUT, $this->readTimeout);
}
if ($this->connectTimeout) {
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->connectTimeout);
}
if ($headerFields) {
$headers = [];
foreach ($headerFields as $key => $value) {
$headers[] = "$key: $value";
}
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
unset($headers);
}
curl_setopt($ch, CURLOPT_USERAGENT, $this->sdkVersion);
//https ignore ssl check ?
if (strlen($url) > 5 && strtolower(substr($url, 0, 5)) === "https") {
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
}
$delimiter = '-------------' . uniqid();
$data = '';
if ($postFields != null) {
foreach ($postFields as $name => $content) {
$data .= "--" . $delimiter . "\r\n";
$data .= 'Content-Disposition: form-data; name="' . $name . '"';
$data .= "\r\n\r\n" . $content . "\r\n";
}
unset($name, $content);
}
if ($fileFields != null) {
foreach ($fileFields as $name => $file) {
$data .= "--" . $delimiter . "\r\n";
$data .= 'Content-Disposition: form-data; name="' . $name . '"; filename="' . $file['name'] . "\" \r\n";
$data .= 'Content-Type: ' . $file['type'] . "\r\n\r\n";
$data .= $file['content'] . "\r\n";
}
unset($name, $file);
}
$data .= "--" . $delimiter . "--";
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER,
[
'Content-Type: multipart/form-data; boundary=' . $delimiter,
'Content-Length: ' . strlen($data)
]
);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$response = curl_exec($ch);
unset($data);
$errno = curl_errno($ch);
if ($errno) {
curl_close($ch);
throw new \RuntimeException($errno, 0);
}
$httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if (200 !== $httpStatusCode) {
throw new \RuntimeException($response, $httpStatusCode);
}
return $response;
}
public function execute(IopRequest $request, $accessToken = null)
{
$sysParams["app_key"] = $this->appkey;
$sysParams["sign_method"] = $this->signMethod;
$sysParams["timestamp"] = $this->msectime();
$sysParams["method"] = $request->apiName;
$sysParams["partner_id"] = $this->sdkVersion;
$sysParams["simplify"] = $request->simplify;
$sysParams["format"] = $request->format;
if (null !== $accessToken) {
$sysParams["session"] = $accessToken;
}
$apiParams = $request->udfParams;
$requestUrl = $this->gatewayUrl;
if ($this->endWith($requestUrl, "/")) {
$requestUrl = substr($requestUrl, 0, -1);
}
// $requestUrl .= $request->apiName;
$requestUrl .= '?';
if ($this->logLevel === Constants::$log_level_debug) {
$sysParams["debug"] = 'true';
}
$sysParams["sign"] = $this->generateSign($request->apiName, array_merge($apiParams, $sysParams));
foreach ($sysParams as $sysParamKey => $sysParamValue) {
$requestUrl .= "$sysParamKey=" . urlencode($sysParamValue) . "&";
}
$requestUrl = substr($requestUrl, 0, -1);
$resp = '';
try {
if ($request->httpMethod === 'POST') {
$resp = $this->curl_post($requestUrl, $apiParams, $request->fileParams, $request->headerParams);
} else {
$resp = $this->curl_get($requestUrl, $apiParams, $request->headerParams);
}
} catch (\Throwable $e) {
$this->logApiError($requestUrl, "HTTP_ERROR_" . $e->getCode(), $e->getMessage());
throw $e;
}
unset($apiParams);
$respObject = json_decode($resp);
if (isset($respObject->code) && $respObject->code != "0") {
$this->logApiError($requestUrl, $respObject->code, $respObject->message);
} else {
if ($this->logLevel == Constants::$log_level_debug || $this->logLevel == Constants::$log_level_info) {
$this->logApiError($requestUrl, '', '');
}
}
return $resp;
}
protected function logApiError($requestUrl, $errorCode, $responseTxt)
{
$localIp = $_SERVER["SERVER_ADDR"] ?? "CLI";
$logger = new IopLogger;
$logger->conf["log_file"] = rtrim(root_path(), '\\/') . '/' . "logs/iopsdk.log." . date("Y-m-d");
$logger->conf["separator"] = "^_^";
$logData = [
date("Y-m-d H:i:s"),
$this->appkey,
$localIp,
PHP_OS,
$this->sdkVersion,
$requestUrl,
$errorCode,
str_replace("\n", "", $responseTxt)
];
$logger->log($logData);
}
public function msectime(): string
{
[$msec, $sec] = explode(' ', microtime());
return $sec . '000';
}
public function endWith($haystack, $needle): bool
{
$length = strlen($needle);
if ($length === 0) {
return false;
}
return (substr($haystack, -$length) === $needle);
}
}

View File

@@ -0,0 +1,43 @@
<?php
namespace Sweeper\PlatformMiddleware\Sdk\AeSdk\Iop;
class IopLogger
{
public $conf = [
"separator" => "\t",
"log_file" => ""
];
private $fileHandle;
protected function getFileHandle()
{
if (null === $this->fileHandle) {
if (empty($this->conf["log_file"])) {
trigger_error("no log file spcified.");
}
$logDir = dirname($this->conf["log_file"]);
if (!is_dir($logDir) && !mkdir($logDir, 0777, true) && !is_dir($logDir)) {
throw new \RuntimeException(sprintf('Directory "%s" was not created', $logDir));
}
$this->fileHandle = fopen($this->conf["log_file"], "a");
}
return $this->fileHandle;
}
public function log($logData)
{
if ("" == $logData || [] == $logData) {
return false;
}
if (is_array($logData)) {
$logData = implode($this->conf["separator"], $logData);
}
$logData .= "\n";
fwrite($this->getFileHandle(), $logData);
}
}

View File

@@ -0,0 +1,78 @@
<?php
namespace Sweeper\PlatformMiddleware\Sdk\AeSdk\Iop;
class IopRequest
{
public $apiName;
public $headerParams = [];
public $udfParams = [];
public $fileParams = [];
public $httpMethod = 'POST';
public $simplify = 'false';
public $format = 'json';//支持TOP的xml
public function __construct($apiName, $httpMethod = 'POST')
{
$this->apiName = $apiName;
$this->httpMethod = $httpMethod;
if ($this->startWith($apiName, "//")) {
throw new \InvalidArgumentException("api name is invalid. It should be start with /");
}
}
public function addApiParam($key, $value)
{
if (!is_string($key)) {
throw new \InvalidArgumentException("api param key should be string");
}
if (is_object($value)) {
$this->udfParams[$key] = json_decode($value);
} else {
$this->udfParams[$key] = $value;
}
}
public function addFileParam($key, $content, $mimeType = 'application/octet-stream')
{
if (!is_string($key)) {
throw new \InvalidArgumentException("api file param key should be string");
}
$file = [
'type' => $mimeType,
'content' => $content,
'name' => $key
];
$this->fileParams[$key] = $file;
}
public function addHttpHeaderParam($key, $value)
{
if (!is_string($key)) {
throw new \InvalidArgumentException("http header param key should be string");
}
if (!is_string($value)) {
throw new \InvalidArgumentException("http header param value should be string");
}
$this->headerParams[$key] = $value;
}
public function startWith($str, $needle)
{
return strpos($str, $needle) === 0;
}
}

View File

@@ -0,0 +1,12 @@
<?php
namespace Sweeper\PlatformMiddleware\Sdk\AeSdk\Iop;
class UrlConstants
{
public static $api_gateway_url_tw = "https://api-sg.aliexpress.com/sync";
public static $api_authorization_url = "https://auth.taobao.tw/rest";
}

View File

@@ -0,0 +1,342 @@
<?php
namespace Sweeper\PlatformMiddleware\Sdk\AeSdk;
use Sweeper\PlatformMiddleware\Sdk\AeSdk\Iop\IopLogger;
use function Sweeper\PlatformMiddleware\root_path;
class IopClient
{
public $appKey;
public $secretKey;
public $gatewayUrl;
public $connectTimeout;
public $readTimeout;
protected $signMethod = "sha256";
protected $sdkVersion = "iop-sdk-php-20220608";
public $logLevel;
public $log_level_debug = "DEBUG";
public $log_level_info = "INFO";
public $log_level_error = "ERROR";
public function getAppKey()
{
return $this->appKey;
}
public function __construct($url = "", $appKey = "", $secretKey = "")
{
$length = strlen($url);
if ($length === 0) {
throw new \InvalidArgumentException("url is empty", 0);
}
$this->gatewayUrl = $url;
$this->appKey = $appKey;
$this->secretKey = $secretKey;
$this->logLevel = $this->log_level_error;
}
protected function generateSign($apiName, $params): string
{
ksort($params);
$stringToBeSigned = '';
if (strpos($apiName, '/')) {//rest服务协议
$stringToBeSigned .= $apiName;
}
foreach ($params as $k => $v) {
$stringToBeSigned .= "$k$v";
}
unset($k, $v);
return strtoupper($this->hmac_sha256($stringToBeSigned, $this->secretKey));
}
public function hmac_sha256($data, $key): string
{
return hash_hmac('sha256', $data, $key);
}
public function curl_get($url, $apiFields = null, $headerFields = null)
{
$ch = curl_init();
foreach ($apiFields as $key => $value) {
$url .= "&" . "$key=" . urlencode($value);
}
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FAILONERROR, false);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
if ($headerFields) {
$headers = [];
foreach ($headerFields as $key => $value) {
$headers[] = "$key: $value";
}
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
unset($headers);
}
if ($this->readTimeout) {
curl_setopt($ch, CURLOPT_TIMEOUT, $this->readTimeout);
}
if ($this->connectTimeout) {
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->connectTimeout);
}
curl_setopt($ch, CURLOPT_USERAGENT, $this->sdkVersion);
//https ignore ssl check ?
if (strlen($url) > 5 && stripos($url, "https") === 0) {
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
}
$output = curl_exec($ch);
$errno = curl_errno($ch);
if ($errno) {
curl_close($ch);
throw new \RuntimeException($errno, 0);
}
$httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if (200 !== $httpStatusCode) {
throw new \RuntimeException($output, $httpStatusCode);
}
return $output;
}
public function curl_post($url, $postFields = null, $fileFields = null, $headerFields = null)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FAILONERROR, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
if ($this->readTimeout) {
curl_setopt($ch, CURLOPT_TIMEOUT, $this->readTimeout);
}
if ($this->connectTimeout) {
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->connectTimeout);
}
if ($headerFields) {
$headers = [];
foreach ($headerFields as $key => $value) {
$headers[] = "$key: $value";
}
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
unset($headers);
}
curl_setopt($ch, CURLOPT_USERAGENT, $this->sdkVersion);
//https ignore ssl check ?
if (strlen($url) > 5 && stripos($url, "https") === 0) {
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
}
$delimiter = '-------------' . uniqid();
$data = '';
if ($postFields != null) {
foreach ($postFields as $name => $content) {
$data .= "--" . $delimiter . "\r\n";
$data .= 'Content-Disposition: form-data; name="' . $name . '"';
$data .= "\r\n\r\n" . $content . "\r\n";
}
unset($name, $content);
}
if ($fileFields !== null) {
foreach ($fileFields as $name => $file) {
$data .= "--" . $delimiter . "\r\n";
$data .= 'Content-Disposition: form-data; name="' . $name . '"; filename="' . $file['name'] . "\" \r\n";
$data .= 'Content-Type: ' . $file['type'] . "\r\n\r\n";
$data .= $file['content'] . "\r\n";
}
unset($name, $file);
}
$data .= "--" . $delimiter . "--";
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER,
[
'Content-Type: multipart/form-data; boundary=' . $delimiter,
'Content-Length: ' . strlen($data)
]
);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$response = curl_exec($ch);
unset($data);
$errno = curl_errno($ch);
if ($errno) {
curl_close($ch);
throw new \RuntimeException($errno, 0);
}
$httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if (200 !== $httpStatusCode) {
throw new \RuntimeException($response, $httpStatusCode);
}
return $response;
}
public function execute(IopRequest $request, $accessToken = null)
{
if ($accessToken && $this->isOverdueToken($accessToken)) {
throw new \InvalidArgumentException('token已过期请重新授权谢谢');
}
$sysParams["app_key"] = $this->appKey;
$sysParams["sign_method"] = $this->signMethod;
$sysParams["timestamp"] = $this->msectime();
$sysParams["method"] = $request->apiName;
$sysParams["partner_id"] = $this->sdkVersion;
$sysParams["simplify"] = $request->simplify;
$sysParams["format"] = $request->format;
if (null !== $accessToken) {
$sysParams["session"] = $accessToken;
}
$apiParams = $request->udfParams;
$requestUrl = $this->gatewayUrl;
if ($this->endWith($requestUrl, "/")) {
$requestUrl = substr($requestUrl, 0, -1);
}
$requestUrl .= '?';
if ($this->logLevel === $this->log_level_debug) {
$sysParams["debug"] = 'true';
}
$sysParams["sign"] = $this->generateSign($request->apiName, array_merge($apiParams, $sysParams));
foreach ($sysParams as $sysParamKey => $sysParamValue) {
$requestUrl .= "$sysParamKey=" . urlencode($sysParamValue) . "&";
}
$requestUrl = substr($requestUrl, 0, -1);
try {
if ($request->httpMethod === 'POST') {
$resp = $this->curl_post($requestUrl, $apiParams, $request->fileParams, $request->headerParams);
} else {
$resp = $this->curl_get($requestUrl, $apiParams, $request->headerParams);
}
} catch (\Throwable $e) {
throw $e;
}
unset($apiParams);
if (strpos($resp, 'specified access token is invalid')) {
$this->saveOverdueToken($accessToken);
} else {
$this->clearOverdueToken($accessToken);
}
$respObject = json_decode($resp, false, 512, JSON_BIGINT_AS_STRING);
if ($respObject === false) {
throw new \RuntimeException('响应格式异常,解析失败;响应内容为' . $resp);
}
return $respObject;
}
protected function logApiError($requestUrl, $errorCode, $responseTxt): void
{
$localIp = $_SERVER["SERVER_ADDR"] ?? "CLI";
$logger = new IopLogger;
$logger->conf["log_file"] = rtrim(root_path(), '\\/') . '/' . "logs/iopsdk.log." . date("Y-m-d");
$logger->conf["separator"] = "^_^";
$logData = [
date("Y-m-d H:i:s"),
$this->appKey,
$localIp,
PHP_OS,
$this->sdkVersion,
$requestUrl,
$errorCode,
str_replace("\n", "", $responseTxt)
];
$logger->log($logData);
}
public function msectime(): string
{
[$msec, $sec] = explode(' ', microtime());
return $sec . '000';
}
public function endWith($haystack, $needle): bool
{
$length = strlen($needle);
if ($length === 0) {
return false;
}
return (substr($haystack, -$length) === $needle);
}
public function isOverdueToken($token): bool
{
$file = rtrim(root_path(), '\\/') . '/tmp/ali_overdue_token/' . $token;
if (is_file($file)) {
$num = file_get_contents($file);
// 验证超过5次 或者 半小时以内创建的,不重新放行
if ($num > 5 || (filemtime($file)) > (time() - 300)) {
return true;
}
}
return false;
}
public function saveOverdueToken($token): bool
{
$path = rtrim(root_path(), '\\/') . '/tmp/ali_overdue_token/';
if (!is_dir($path) && !mkdir($path) && !is_dir($path)) {
throw new \RuntimeException(sprintf('Directory "%s" was not created', $path));
}
$file = $path . '/' . $token;
$num = is_file($file) ? file_get_contents($file) + 1 : 1;
file_put_contents($file, $num);
return true;
}
public function clearOverdueToken($token): void
{
$file = rtrim(root_path(), '\\/') . '/tmp/ali_overdue_token/' . $token;
if (is_file($file)) {
@unlink($file);
}
}
}

View File

@@ -0,0 +1,117 @@
<?php
namespace Sweeper\PlatformMiddleware\Sdk\AeSdk;
class IopRequest
{
public $apiName;
public $headerParams = [];
public $udfParams = [];
public $fileParams = [];
public $httpMethod = 'POST';
public $simplify = 'false';
public $format = 'json';//支持TOP的xml
public function __construct($apiName, $httpMethod = 'POST')
{
$this->apiName = $apiName;
$this->httpMethod = $httpMethod;
if ($this->startWith($apiName, "//")) {
throw new \InvalidArgumentException("api name is invalid. It should be start with /");
}
}
/**
* 添加API参数
* Author: Sweeper <wili.lixiang@gmail.com>
* DateTime: 2024/3/18 17:14
* @param $key
* @param $value
* @return $this
*/
public function addApiParam($key, $value): IopRequest
{
if (!is_string($key)) {
throw new \InvalidArgumentException("api param key should be string");
}
if (is_object($value)) {
$this->udfParams[$key] = json_decode($value, false);
} else {
$this->udfParams[$key] = $value;
}
return $this;
}
/**
* 添加文件参数
* Author: Sweeper <wili.lixiang@gmail.com>
* DateTime: 2024/3/18 16:53
* @param $key
* @param $content
* @param string $mimeType
* @return $this
*/
public function addFileParam($key, $content, string $mimeType = 'application/octet-stream'): IopRequest
{
if (!is_string($key)) {
throw new \InvalidArgumentException("api file param key should be string");
}
$file = [
'type' => $mimeType,
'content' => $content,
'name' => $key
];
$this->fileParams[$key] = $file;
return $this;
}
/**
* 添加HTTP头参数
* Author: Sweeper <wili.lixiang@gmail.com>
* DateTime: 2024/3/18 16:53
* @param $key
* @param $value
* @return $this
*/
public function addHttpHeaderParam($key, $value): IopRequest
{
if (!is_string($key)) {
throw new \InvalidArgumentException("http header param key should be string");
}
if (!is_string($value)) {
throw new \InvalidArgumentException("http header param value should be string");
}
$this->headerParams[$key] = $value;
return $this;
}
/**
* 判断字符串是否以某个字符开头
* Author: Sweeper <wili.lixiang@gmail.com>
* DateTime: 2024/3/18 16:54
* @param $str
* @param $needle
* @return bool
*/
public function startWith($str, $needle): bool
{
return strpos($str, $needle) === 0;
}
}

View File

@@ -0,0 +1,14 @@
<?php
namespace Sweeper\PlatformMiddleware\Sdk\AeSdk;
class UrlConstants
{
/** @var string API 网关地址 */
public const API_GATEWAY_URL = 'https://api-sg.aliexpress.com/sync';
public static $api_gateway_url_tw = self::API_GATEWAY_URL;
public const API_GATEWAY_URL_TW_NEW = "http://api-sg.aliexpress.com/rest";
}

View File

@@ -0,0 +1,11 @@
<?php
use Sweeper\PlatformMiddleware\Sdk\AeSdk\Iop\IopClient;
use Sweeper\PlatformMiddleware\Sdk\AeSdk\Iop\IopRequest;
$c = new IopClient('https://api.taobao.tw/rest', '${appKey}', '${appSecret}');
$request = new IopRequest('/xiaoxuan/mockfileupload');
$request->addApiParam('file_name', 'pom.xml');
$request->addFileParam('file_bytes', file_get_contents('/Users/xt/Documents/work/tasp/tasp/pom.xml'));
var_dump($c->execute($request));

View File

@@ -0,0 +1,15 @@
<?php
use Sweeper\PlatformMiddleware\Sdk\AeSdk\Iop\Constants;
use Sweeper\PlatformMiddleware\Sdk\AeSdk\Iop\IopClient;
use Sweeper\PlatformMiddleware\Sdk\AeSdk\Iop\IopRequest;
$c = new IopClient('api.taobao.tw/rest', '100240', 'hLeciS15d7UsmXKoND76sBVPpkzepxex');
$c->logLevel = Constants::$log_level_debug;
$request = new IopRequest('/product/item/get', 'GET');
$request->addApiParam('itemId', '157432005');
$request->addApiParam('authDO', '{"sellerId":2000000016002}');
var_dump($c->execute($request, null));
echo PHP_INT_MAX;
var_dump($c->msectime());

View File

@@ -0,0 +1,12 @@
<?php
use Sweeper\PlatformMiddleware\Sdk\AeSdk\Iop\IopClient;
use Sweeper\PlatformMiddleware\Sdk\AeSdk\Iop\IopRequest;
$c = new IopClient('https://api-pre.aliexpress.com/sync', '33505222', 'e1fed6b34feb26aabc391d187732af93');
$request = new IopRequest('aliexpress.logistics.redefining.getlogisticsselleraddresses');
$request->simplify = "true";
$request->format = "xml";
$request->addApiParam('seller_address_query', 'pickup');
var_dump($c->execute($request, "50000001a27l15rndYBjw6PrtFFHPGZfy09k1Cp1bd8597fsduP0RsNy0jhF6FL"));