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
+4
View File
@@ -41,6 +41,10 @@ export class PlatformsService {
platform.capabilities,
'default_locale',
),
default_currency_code: stringCapability(
platform.capabilities,
'default_currency_code',
),
}));
}
@@ -1,4 +1,5 @@
import {
createDecipheriv,
createCipheriv,
createHash,
createHmac,
@@ -35,3 +36,23 @@ export function encryptStoreSecret(
.digest('base64url'),
};
}
/** 仅供受信任的后台 Worker 使用;调用方不得记录返回值。 */
export function decryptStoreSecret(
ciphertextWithTag: Buffer,
nonce: Buffer,
keyMaterial: string,
): string {
const authenticationTagLength = 16;
if (ciphertextWithTag.length <= authenticationTagLength) {
throw new Error('Invalid encrypted store secret');
}
const key = createHash('sha256').update(keyMaterial).digest();
const ciphertext = ciphertextWithTag.subarray(0, -authenticationTagLength);
const tag = ciphertextWithTag.subarray(-authenticationTagLength);
const decipher = createDecipheriv('aes-256-gcm', key, nonce);
decipher.setAuthTag(tag);
return Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString(
'utf8',
);
}
+28 -1
View File
@@ -470,6 +470,19 @@ export class StoresService {
'门店凭据尚未验证通过,无法同步仓库',
);
}
if (kind === 'store_credential_verification') {
await transaction.query(
`UPDATE atlas.stores SET status = 'verifying', credential_status = 'unknown',
last_error_code = NULL, last_error_message = NULL, last_error_at = NULL,
revision = revision + 1, updated_at = now() WHERE id = $1`,
[storeId],
);
await transaction.query(
`UPDATE atlas.store_secrets SET status = 'unknown', updated_at = now()
WHERE store_id = $1 AND kind = 'seller_api_key' AND revoked_at IS NULL`,
[storeId],
);
}
const operation = await this.createOperation(
transaction,
userId,
@@ -605,6 +618,20 @@ export class StoresService {
[kind, storeId, userId],
);
const operation = toOperation(created.rows[0]);
const payload: { store_id: string; operation_id: string; secret_id?: string } = {
store_id: storeId,
operation_id: operation.id,
};
// 验证任务绑定创建当刻的密钥行;密钥后来被替换时,旧任务不得验证或覆盖新状态。
if (kind === 'store_credential_verification') {
const secret = await transaction.query<{ id: string }>(
`SELECT id FROM atlas.store_secrets
WHERE store_id = $1 AND kind = 'seller_api_key' AND revoked_at IS NULL`,
[storeId],
);
if (!secret.rows[0]) throw new Error('Current store secret is missing');
payload.secret_id = secret.rows[0].id;
}
await transaction.query(
`INSERT INTO atlas.outbox_events
(workspace_id, aggregate_type, aggregate_id, event_type, event_payload, deduplication_key)
@@ -612,7 +639,7 @@ export class StoresService {
[
storeId,
`${kind}.requested`,
{ store_id: storeId, operation_id: operation.id },
payload,
operation.id,
],
);