feat(store): 添加门店、门店验证

This commit is contained in:
R524809
2026-09-04 10:27:29 +08:00
parent 66ca8b496c
commit 70d9d5b92a
19 changed files with 602 additions and 26 deletions
+46
View File
@@ -0,0 +1,46 @@
/** 401 是认证失败;403 表示密钥权限或账户组合不被允许。 */
export class OzonCredentialError extends Error {
public constructor(public readonly status: 401 | 403) {
super(`Ozon credential request failed (${status})`);
}
}
/** 认证以外的确定性 4xx,不能误报为凭据无效。 */
export class OzonRequestError extends Error {
public constructor(public readonly status: number) {
super(`Ozon verification request was rejected (${status})`);
}
}
export class OzonRetryableError extends Error {}
/**
* Uses the category-tree read endpoint as the credential probe. It has no write side effect and,
* unlike warehouse-list, is verified against the current Ozon account integration.
*/
export async function verifyOzonCredentials(
clientId: string,
apiKey: string,
): Promise<void> {
let response: Response;
try {
response = await fetch('https://api-seller.ozon.ru/v1/description-category/tree', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Client-Id': clientId,
'Api-Key': apiKey,
},
body: JSON.stringify({ language: 'ZH_HANS' }),
signal: AbortSignal.timeout(30_000),
});
} catch {
throw new OzonRetryableError('Ozon request could not be completed');
}
if (response.ok) return;
if (response.status === 401 || response.status === 403) {
throw new OzonCredentialError(response.status);
}
if (response.status === 429 || response.status >= 500) {
throw new OzonRetryableError(`Ozon temporarily unavailable (${response.status})`);
}
throw new OzonRequestError(response.status);
}