FAQ - Häufig gestellte Fragen

So signieren Sie ein API-Token mit einem neuen Ablauf-Header

Mit folgendem Python-Code kann ein bestehender JWT decodiert, das exp-Claim (Ablaufzeitpunkt) neu gesetzt und der Token mit denselben Header-Informationen (inkl. kid und alg) erneut signiert werden. Ziel ist ein neuer, gültiger Token mit aktualisiertem Ablaufdatum:

from base64 import urlsafe_b64decode, b64encode 
from json import loads 
import datetime
from jwt import encode, decode
from typing import Dict, Any

def pad_base64url(b64string: str) -> str:
  return b64string + '=' * (-len(b64string) % 4)

def extract_header(jwt_token: str) -> Dict[str, Any]:
  header_b64 = jwt_token.split('.')[0]
  padded_header = pad_base64url(header_b64)
  header_json = urlsafe_b64decode(padded_header)

  return  loads(header_json)

def encode_secret(secret: str) -> bytes:
  return b64encode(secret.encode())

token: str = "eyJraWQiOiI1Zjc0RTZuME5pY…"
secret: bytes = encode_secret("d4cHsO5QTC…")

payload: Dict[str, Any] = decode(token, secret, algorithms=["HS512"], options={"verify_exp": False})

payload['exp'] = datetime.datetime.utcnow() + datetime.timedelta(hours=1)

new_token: str = encode(payload, secret, headers=extract_header(token), algorithm="HS512")

print(new_token)

Das ist besonders sinnvoll, wenn man kurzlebige Token verwenden möchte – etwa aus Sicherheitsgründen, um die Gültigkeitsdauer von Tokens bewusst zu begrenzen und so das Risiko bei Diebstahl oder Missbrauch zu minimieren.

Wie kann die easyBox bei meinen Artikel über die API aktivieren?

Um die easyBox zu nutzen muss einerseits der mode auf BUY_BOX gesetzt werden:

$priceSettings->setMode(RepricingItemPriceSettingsDTO::MODE_BUY_BOX);

Des weiteren muss die easyBox Strategie gesetzt werden:

$strategyAPI = new eSagu\Amzn\RePricing\V1\Api\RepricingItemStrategyApi();
$buyBoxAPI = new eSagu\Amzn\RePricing\V1\Api\RepricingBuyBoxSettingsApi();

$itemId = 1337;
$buyBoxSettings = $buyBoxAPI->callList();

$itemStrategy = $strategyAPI->get($itemId);
$itemStrategy->getPriceSettings()->setMode(RepricingItemPriceSettingsDTO::MODE_BUY_BOX);
$itemStrategy->setBuyBoxSettingsId($buyBoxSettings[0]->getId());

$strategyAPI->put($itemId, $settings);

Wie kann ich Clientseitig prüfen ob mein Token abgelaufen ist?

In diesem kurzen Beispiel in PHP wird der exp header des Token ausgelesen und geprüft, ob sein Ablaufdatum überschritten ist.

$token = 'PLACE_YOUR_JWT_HERE';

$tokenPayload = json_decode(base64_decode(explode('.', $token)[1]), true);
if ($tokenPayload['exp'] < time()) {
 throw new RuntimeException("Token \"{$tokenPayload['sub']}\" is expired!");
}

Server antwortet mit 400 - Ich nutze PHP und erhalte beim anpassen von Preisänderungen einen 400er Fehler.

Dieser tritt häufig dann auf, wenn Preise nicht als int sondern als string übertragen werden. Ein type cast als int löst dieses Problem in der Regel;

$priceSettings->setFixedPrice((int)$dPriceFix);
$priceSettings->setMaxPrice((int)($dPriceFix + 1));
$priceSettings->setMinPrice((int)($dPriceFix - 1));
$priceSettings->setMode(RepricingItemPriceSettingsDTO::MODE_FIXED_PRICE);

PHP API Client - Die Parameterreihenfolge einzelner Methoden hat sich nach einem Update geändert.

Leider fabriziert der Swagger Codegen beim neu generieren des API Clienten mit unter eine andere Parameterreihenfolge für einzelne Methoden. Dies lässt sich auch nicht verhindern wenn neue Filter optionen hinzugekommen sind.

Aber das kann man wie im folgenden Beispiel umgehen, indem man die Reihenfolge anhand der Parameter Namen bestimmt und die Methode mit einen Assoziativen Array "aufruft", wobei die Schlüssel im Assoziativen Array den Namen der einzelnen Parameter entsprechen.


setApiKey('Authorization', JWT_API_TOKEN);
eSagu\EBay\RePricing\V1\Configuration::getDefaultConfiguration()->setApiKeyPrefix('Authorization', 'Bearer');

$itemApi = new eSagu\EBay\RePricing\V1\Api\ItemApi();

$itemsPerPage = 5;
$page = 0;
try {
    do {
        $items = callWithOrderedParams($itemApi, 'callList', [
            'offset'   => $page++ * $itemsPerPage,
            'limit'    => $itemsPerPage,
            'by_title' => "Turnschuhe",
        ]);

        $hasMore = count($items) === $itemsPerPage;
        $ebayItemIds = implode(', ', array_map(function (RepricingItemDTO $item) { return $item->getItemId(); }, $items));

        echo "Page: \"$page\", Item Ids: \"$ebayItemIds\"", PHP_EOL;

    } while ($hasMore);
} catch (Exception $e) {
    echo $e->getMessage(), PHP_EOL;
}

/**
 * @param mixed $apiInstance
 * @param string $methodName
 * @param array $paramsAssoc
 * @return mixed
 * @throws \ReflectionException
 */
function callWithOrderedParams($apiInstance, $methodName, $paramsAssoc)
{
    $params = [];
    foreach ((new \ReflectionMethod($apiInstance, $methodName))->getParameters() as $refParam) {
        $params[$refParam->name] = null;
    }

    foreach ($paramsAssoc as $key => $val) {
        if (array_key_exists($key, $params)) {
            $params[$key] = $val;
            continue;
        }

        $className = get_class($apiInstance);
        $methodParams = implode(', ', array_map(function ($p) { return "\$$p"; }, array_keys($params)));

        throw new InvalidArgumentException("Param \"$key\" is not present in \"$className->$methodName($methodParams)\"!");
    }

    return call_user_func_array([$apiInstance, $methodName], $params);
}