跳至內容
ShopentlyLearn

上傳文章照片

文章、作者、留言審核與排程發布。

POST/api/v1/addons/shopently.blog/media

身份驗證
Bearer
最低方案
BASIC
所需的已安裝模組
shopently.blog · 模組契約版本 1
所需權限
addon.shopently.blog:media_upload

程式碼範例

請求示例

cURL

: "${SHOPENTLY_SHOP_URL:?}"

case "${SHOPENTLY_IMAGE_FILE:?}" in *[!a-zA-Z0-9/._\ -]*) echo "Unsupported image path" >&2; exit 1;; esac

curl --disable --globoff --fail-with-body --silent --show-error \
  --proto '=https' --connect-timeout 5 --max-time 30 \
  --request POST \
  --header "Authorization: Bearer ${SHOPENTLY_ACCESS_TOKEN:?}" \
  --header 'Idempotency-Key: learn-3ccd36e66a3647eaaf03bf4cddfb471a' \
  --form "file=@${SHOPENTLY_IMAGE_FILE:?};filename=article.png;type=image/png" \
  --url "${SHOPENTLY_SHOP_URL%/}"/api/v1/addons/shopently.blog/media

PHP

<?php
declare(strict_types=1);

$baseUrl = rtrim(getenv('SHOPENTLY_SHOP_URL') ?: '', '/');
$origin = parse_url($baseUrl);
if (!$origin || ($origin['scheme'] ?? '') !== 'https' || empty($origin['host']) ||
    isset($origin['user'], $origin['pass']) || isset($origin['user']) || isset($origin['path']) ||
    isset($origin['query']) || isset($origin['fragment'])) {
    throw new RuntimeException('SHOPENTLY_SHOP_URL must be an HTTPS origin');
}
$credential = getenv('SHOPENTLY_ACCESS_TOKEN') ?: '';
if ($credential === '' || strpbrk($credential, "\r\n") !== false) {
    throw new RuntimeException('Invalid credential');
}
$headers = ['Idempotency-Key: learn-3ccd36e66a3647eaaf03bf4cddfb471a'];
$headers[] = 'Authorization: Bearer ' . $credential;
$responseHeaders = [];
$handle = curl_init($baseUrl . '/api/v1/addons/shopently.blog/media');
curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FOLLOWLOCATION => false,
    CURLOPT_PROTOCOLS => CURLPROTO_HTTPS,
    CURLOPT_SSL_VERIFYPEER => true,
    CURLOPT_SSL_VERIFYHOST => 2,
    CURLOPT_CONNECTTIMEOUT => 5,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HEADERFUNCTION => static function ($handle, string $line) use (&$responseHeaders): int {
        if (str_contains($line, ':')) {
            [$name, $value] = explode(':', $line, 2);
            $responseHeaders[strtolower(trim($name))] = trim($value);
        }
        return strlen($line);
    },
]);
$image = getenv('SHOPENTLY_IMAGE_FILE') ?: '';
if (!is_file($image) || !is_readable($image) || filesize($image) > 5242880) {
    throw new RuntimeException('Expected a readable PNG image up to 5 MiB');
}
curl_setopt($handle, CURLOPT_POSTFIELDS, ['file' => new CURLFile($image, 'image/png', 'article.png')]);
$raw = curl_exec($handle);
$status = curl_getinfo($handle, CURLINFO_RESPONSE_CODE);
$error = curl_error($handle);
curl_close($handle);
if ($raw === false) {
    throw new RuntimeException('Transport error: ' . $error);
}
if ($status < 200 || $status >= 300) {
    throw new RuntimeException('HTTP ' . $status . '; request_id=' .
        ($responseHeaders['x-request-id'] ?? '') . '; retry_after=' . ($responseHeaders['retry-after'] ?? ''));
}
$result = $raw === '' ? null : json_decode($raw, true, 512, JSON_THROW_ON_ERROR | JSON_BIGINT_AS_STRING);
echo json_encode($result, JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE), PHP_EOL;

Python

from contextlib import ExitStack
import json
import os
from urllib.parse import urlsplit

import requests  # python -m pip install requests

base_url = os.environ["SHOPENTLY_SHOP_URL"].rstrip("/")
origin = urlsplit(base_url)
if origin.scheme != "https" or not origin.hostname or origin.username or origin.password or origin.path or origin.query or origin.fragment:
    raise ValueError("SHOPENTLY_SHOP_URL must be an HTTPS origin")
credential = os.environ['SHOPENTLY_ACCESS_TOKEN']
if not credential or "\r" in credential or "\n" in credential:
    raise ValueError("Invalid credential")
headers = {'Idempotency-Key': 'learn-3ccd36e66a3647eaaf03bf4cddfb471a'}
headers["Authorization"] = 'Bearer' + " " + credential
body = None
if body is not None:
    headers["Content-Type"] = "application/json"

with ExitStack() as stack:
    session = stack.enter_context(requests.Session())
    files = None
    if True:
        image = stack.enter_context(open(os.environ["SHOPENTLY_IMAGE_FILE"], "rb"))
        if os.fstat(image.fileno()).st_size > 5242880:
            raise ValueError("Image exceeds 5 MiB")
        files = {"file": ("article.png", image, "image/png")}
    response = session.request(
        'POST', base_url + '/api/v1/addons/shopently.blog/media', headers=headers,
        data=body.encode("utf-8") if body is not None else None, files=files,
        timeout=(5, 30), allow_redirects=False,
    )
    if not 200 <= response.status_code < 300:
        raise RuntimeError(f"HTTP {response.status_code}; request_id={response.headers.get('X-Request-ID', '')}; retry_after={response.headers.get('Retry-After', '')}")
    if False:
        if response.headers.get("Content-Type") != "image/webp" or len(response.content) > 5242880:
            raise ValueError("Unexpected image response")
        with open(os.environ["SHOPENTLY_OUTPUT_FILE"], "xb") as output:
            output.write(response.content)
    else:
        result = response.json() if response.content else None
        print(json.dumps(result, ensure_ascii=False, indent=2))

回應示例 201

JSON
{
  "data": {
    "bytes": 366,
    "height": 100,
    "id": "e8663afe-3c38-461c-a142-a980085630af",
    "version": 1,
    "width": 200
  },
  "meta": {
    "request_id": "56412902-d48f-42a2-a128-8f3cc940c768"
  }
}

概覽

使用 HTML 文章、照片、作者資訊與搜尋中繼資料經營商店部落格。儲存草稿、準備翻譯,並立即發布或排程於指定時區的所選時間發布。在面板中管理留言與審核;外部生成工具可以透過已授予權限的 API 進行操作。

BASIC · api.enabled · addons.use(shopently.blog) · addon.shopently.blog:media_upload

參數

請求標頭

Idempotency-Key字串必填

單個邏輯寫入操作的唯一識別碼。

minLength: 1maxLength: 128
約束
pattern
"^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$"
示例: "learn-3ccd36e66a3647eaaf03bf4cddfb471a"

請求本文

multipart/form-data · 必填

物件附加欄位: 否
file字串必填

照片 (PNG; multipart/form-data)

format: "binary"

回應

回應 201

data物件附加欄位: 否必填

成功回應的資料。

欄位 · data
bytes整數必填

大小(位元組)

minimum: 1maximum: 15728640
height整數必填

高度

minimum: 1maximum: 1600
id字串必填

資源識別碼;請保留回傳的原值。

format: "uuid"
version整數必填

用於並行控制的資源版本。

minimum: 1maximum: 9223372036854775807
width整數必填

寬度

minimum: 1maximum: 1600
meta物件附加欄位: 否必填

回應元資料。

欄位 · meta
request_id字串必填

申請識別碼;在回應元資料中表示 HTTP 請求識別碼。

minLength: 1maxLength: 100
回應示例

HTTP 狀態

201
資源已建立 架構
400
無效請求
401
需要身分驗證
403
權限不足
404
找不到資源
409
版本衝突
422
驗證失敗
429
超出請求限制
其他 HTTP 狀態 (7)
405
不允許的方法
413
請求過大
415
不支援的格式
500
伺服器錯誤
502
API 閘道錯誤
503
服務無法使用
504
閘道逾時

錯誤目錄: ErrorResponse

請求標頭與回應標頭

401

WWW-Authenticate字串選填

伺服器要求的身份驗證方案。

405

Allow字串選填

此資源支援的 HTTP 方法。

429, 503

Retry-After整數選填

重試前最少等待的秒數。

minimum: 0