修复快手销毁请求验签
This commit is contained in:
@@ -0,0 +1,65 @@
|
|||||||
|
import test from 'node:test'
|
||||||
|
import assert from 'node:assert/strict'
|
||||||
|
|
||||||
|
import {
|
||||||
|
buildKuaishouIndustrySignSource,
|
||||||
|
signKuaishouIndustryPayload,
|
||||||
|
verifyKuaishouIndustrySignature,
|
||||||
|
} from './crypto.js'
|
||||||
|
|
||||||
|
const TEST_CONFIG = { signSecret: 'test-secret' } as any
|
||||||
|
|
||||||
|
test('buildKuaishouIndustrySignSource keeps nested eticket fields for destroy-code payload', () => {
|
||||||
|
const source = buildKuaishouIndustrySignSource(
|
||||||
|
{
|
||||||
|
appkey: 'ks-test',
|
||||||
|
param: {
|
||||||
|
oid: '2618901686368642',
|
||||||
|
reason: 'USER_APPLY_REFUND',
|
||||||
|
etickets: [
|
||||||
|
{
|
||||||
|
code: null,
|
||||||
|
goodsValue: 3800,
|
||||||
|
id: 'KSVW9JTD4FZM4VDHKBV',
|
||||||
|
num: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
signMethod: 'MD5',
|
||||||
|
timestamp: 1783497998539,
|
||||||
|
version: '1',
|
||||||
|
},
|
||||||
|
TEST_CONFIG,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert.match(
|
||||||
|
source,
|
||||||
|
/param=\{"etickets":\[\{"code":null,"goodsValue":3800,"id":"KSVW9JTD4FZM4VDHKBV","num":1\}\],"oid":"2618901686368642","reason":"USER_APPLY_REFUND"\}/,
|
||||||
|
)
|
||||||
|
assert.doesNotMatch(source, /"etickets":\[\{\}\]/)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('verifyKuaishouIndustrySignature accepts nested object payload signed by the same canonical source', () => {
|
||||||
|
const payload = {
|
||||||
|
appkey: 'ks-test',
|
||||||
|
param: {
|
||||||
|
oid: '2618901686368642',
|
||||||
|
reason: 'USER_APPLY_REFUND',
|
||||||
|
etickets: [
|
||||||
|
{
|
||||||
|
code: null,
|
||||||
|
goodsValue: 3800,
|
||||||
|
id: 'KSVW9JTD4FZM4VDHKBV',
|
||||||
|
num: 1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
signMethod: 'MD5',
|
||||||
|
timestamp: 1783497998539,
|
||||||
|
version: '1',
|
||||||
|
}
|
||||||
|
|
||||||
|
const sign = signKuaishouIndustryPayload(payload, 'MD5', TEST_CONFIG)
|
||||||
|
|
||||||
|
assert.equal(verifyKuaishouIndustrySignature({ ...payload, sign }, TEST_CONFIG), true)
|
||||||
|
})
|
||||||
@@ -103,8 +103,28 @@ function stringifySignValue(value: unknown) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (typeof value === 'object') {
|
if (typeof value === 'object') {
|
||||||
return JSON.stringify(value, Object.keys(value as Record<string, unknown>).sort())
|
return JSON.stringify(normalizeSignJsonValue(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
return String(value)
|
return String(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function normalizeSignJsonValue(value: unknown): unknown {
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
return value.map((item) => normalizeSignJsonValue(item))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value && typeof value === 'object') {
|
||||||
|
const record = value as Record<string, unknown>
|
||||||
|
const normalized: Record<string, unknown> = {}
|
||||||
|
for (const key of Object.keys(record).sort()) {
|
||||||
|
const current = normalizeSignJsonValue(record[key])
|
||||||
|
if (current !== undefined) {
|
||||||
|
normalized[key] = current
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return normalized
|
||||||
|
}
|
||||||
|
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user