70 lines
2.6 KiB
JavaScript
70 lines
2.6 KiB
JavaScript
import assert from 'node:assert/strict'
|
|
import crypto from 'node:crypto'
|
|
import test from 'node:test'
|
|
import { YouYiDianNotificationClient } from './notification-client.mjs'
|
|
|
|
const secret = 'example-project-secret-at-least-24-chars'
|
|
|
|
const verifySignature = (request) => {
|
|
const url = new URL(request.url)
|
|
const timestamp = request.init.headers['x-yyd-timestamp']
|
|
const nonce = request.init.headers['x-yyd-nonce']
|
|
const bodyHash = crypto.createHash('sha256').update(request.init.body || '').digest('hex')
|
|
const canonical = [timestamp, nonce, request.init.method, url.pathname.replace('/notification-center', ''), bodyHash].join('\n')
|
|
const expected = crypto.createHmac('sha256', secret).update(canonical).digest('hex')
|
|
assert.equal(request.init.headers['x-yyd-signature'], expected)
|
|
}
|
|
|
|
test('发送通知使用业务正文原文签名并返回投递记录', async () => {
|
|
const requests = []
|
|
const client = new YouYiDianNotificationClient({
|
|
baseUrl: 'https://sc.example.com/notification-center',
|
|
projectCode: 'fixed_asset',
|
|
projectSecret: secret,
|
|
fetchImpl: async (url, init) => {
|
|
requests.push({ url, init })
|
|
return new Response(JSON.stringify({ id: 'delivery-1', status: 'pending' }), {
|
|
status: 202,
|
|
headers: { 'content-type': 'application/json' },
|
|
})
|
|
},
|
|
})
|
|
|
|
const payload = {
|
|
idempotencyKey: 'asset_disposal:53:user-1:v1',
|
|
recipientUserId: 'user-1',
|
|
title: '资产报废待审批',
|
|
content: '**申请时间:** 2026年7月16日 14:30',
|
|
actionTitle: '立即审批',
|
|
actionUrl: 'https://asset.example.com/workflows/disposals/53',
|
|
}
|
|
const delivery = await client.send(payload)
|
|
|
|
assert.deepEqual(delivery, { id: 'delivery-1', status: 'pending' })
|
|
assert.equal(requests.length, 1)
|
|
assert.equal(requests[0].url, 'https://sc.example.com/notification-center/v1/notifications')
|
|
assert.equal(requests[0].init.body, JSON.stringify(payload))
|
|
verifySignature(requests[0])
|
|
})
|
|
|
|
test('查询通知使用空正文签名', async () => {
|
|
let request
|
|
const client = new YouYiDianNotificationClient({
|
|
baseUrl: 'https://sc.example.com/notification-center',
|
|
projectCode: 'fixed_asset',
|
|
projectSecret: secret,
|
|
fetchImpl: async (url, init) => {
|
|
request = { url, init }
|
|
return new Response(JSON.stringify({ id: 'delivery-1', status: 'read' }), {
|
|
status: 200,
|
|
headers: { 'content-type': 'application/json' },
|
|
})
|
|
},
|
|
})
|
|
|
|
const delivery = await client.getDelivery('delivery-1')
|
|
assert.equal(delivery.status, 'read')
|
|
assert.equal(request.init.body, undefined)
|
|
verifySignature(request)
|
|
})
|