147 lines
3.9 KiB
JavaScript
147 lines
3.9 KiB
JavaScript
'use strict';
|
|
|
|
const assert = require('node:assert/strict');
|
|
const test = require('node:test');
|
|
const {
|
|
createPddOpenPlatformClient,
|
|
normalizeCategoryRule,
|
|
resolvePddOpenPlatformCredential,
|
|
signPddParameters,
|
|
} = require('../src/services/pddOpenPlatformClient');
|
|
|
|
test('PDD signing uses UTF-8 and JSON encodes object values before sorting', () => {
|
|
const params = {
|
|
type: 'pdd.test',
|
|
client_id: 'cid',
|
|
timestamp: 1723723200,
|
|
data_type: 'JSON',
|
|
payload: { title: '中文', rows: [1, 2] },
|
|
};
|
|
assert.equal(
|
|
signPddParameters(params, 'secret'),
|
|
'3E0C5F16D0D478A19D44950A628411DB'
|
|
);
|
|
});
|
|
|
|
test('PDD credential resolver matches one shop and rejects ambiguous matches', async () => {
|
|
const rows = [
|
|
{
|
|
id: '1',
|
|
name: '卓禾旗舰店',
|
|
mallID: '10001',
|
|
accessToken: 'token-a',
|
|
client_id: 'client-a',
|
|
secrity: 'secret-a',
|
|
},
|
|
{
|
|
id: '2',
|
|
name: '其他旗舰店',
|
|
mallID: '10002',
|
|
accessToken: 'token-b',
|
|
client_id: 'client-b',
|
|
secrity: 'secret-b',
|
|
},
|
|
];
|
|
const credential = await resolvePddOpenPlatformCredential({
|
|
shopId: '10001',
|
|
shopName: '拼多多-卓禾旗舰店',
|
|
}, { rows });
|
|
assert.equal(credential.mallId, '10001');
|
|
assert.equal(credential.accessToken, 'token-a');
|
|
|
|
await assert.rejects(
|
|
resolvePddOpenPlatformCredential({ shopName: '卓禾旗舰店' }, {
|
|
rows: [rows[0], { ...rows[0], id: '3', mallID: '10003' }],
|
|
}),
|
|
(error) => error.code === 'PDD_CREDENTIAL_AMBIGUOUS'
|
|
);
|
|
});
|
|
|
|
test('PDD client never logs credentials and maps whitelist failures', async () => {
|
|
let sentBody;
|
|
const client = createPddOpenPlatformClient({
|
|
name: 'test',
|
|
clientId: 'client-id',
|
|
clientSecret: 'client-secret',
|
|
accessToken: 'access-token',
|
|
}, {
|
|
httpClient: {
|
|
post: async (_url, body) => {
|
|
sentBody = body;
|
|
return {
|
|
data: {
|
|
error_response: {
|
|
error_code: 20005,
|
|
error_msg: 'IP白名单校验失败',
|
|
request_id: 'request-1',
|
|
},
|
|
},
|
|
};
|
|
},
|
|
},
|
|
});
|
|
await assert.rejects(
|
|
client.getMallInfo(),
|
|
(error) => error.code === 'PDD_IP_NOT_WHITELISTED' && error.pddErrorCode === 20005
|
|
);
|
|
assert.equal(sentBody.client_secret, undefined);
|
|
assert.equal(sentBody.access_token, 'access-token');
|
|
assert.match(sentBody.sign, /^[A-F0-9]{32}$/);
|
|
});
|
|
|
|
test('only the final draft write treats transport failures as an unknown result', async () => {
|
|
const timeoutError = Object.assign(new Error('timeout'), { code: 'ETIMEDOUT' });
|
|
const client = createPddOpenPlatformClient({
|
|
name: '测试店铺',
|
|
clientId: 'client-id',
|
|
clientSecret: 'client-secret',
|
|
accessToken: 'access-token',
|
|
}, {
|
|
httpClient: { post: async () => { throw timeoutError; } },
|
|
timeout: 10,
|
|
});
|
|
|
|
await assert.rejects(
|
|
client.getMallInfo(),
|
|
(error) => error.code === 'PDD_TRANSPORT_ERROR'
|
|
&& error.retryable === true
|
|
&& error.resultUnknown === false
|
|
);
|
|
await assert.rejects(
|
|
client.saveGoodsDraft({ goods_name: '测试商品' }),
|
|
(error) => error.code === 'PDD_DRAFT_RESULT_UNKNOWN'
|
|
&& error.retryable === false
|
|
&& error.resultUnknown === true
|
|
);
|
|
});
|
|
|
|
test('category rules normalize required properties and enum values', () => {
|
|
const result = normalizeCategoryRule({
|
|
cat_rule_get_response: {
|
|
goods_properties_rule: {
|
|
properties: [{
|
|
ref_pid: 1628,
|
|
name: '环保等级',
|
|
required: false,
|
|
is_important: true,
|
|
choose_max_num: 1,
|
|
values: [{ vid: 368832, value: 'E0级' }],
|
|
}],
|
|
},
|
|
},
|
|
});
|
|
assert.deepEqual(result.properties[0], {
|
|
refPid: 1628,
|
|
name: '环保等级',
|
|
required: false,
|
|
important: true,
|
|
chooseMaxNum: 1,
|
|
valueType: 0,
|
|
minValue: null,
|
|
maxValue: null,
|
|
valueUnit: '',
|
|
showCondition: null,
|
|
values: [{ vid: 368832, value: 'E0级' }],
|
|
});
|
|
});
|