import test from 'node:test' import assert from 'node:assert/strict' import { buildOpen91SignSource, encryptOpen91Cards, signOpen91Payload, verifyOpen91Signature, } from './crypto.js' import { buildOpen91CardItem, formatOpen91ExpireTime, resolveOpen91QueryState } from './response.js' test('signOpen91Payload signs only request body fields', () => { const config = { userId: '1001', secret: 'rste57w8rsubsnxsb384ur3u9kn5fzhr', } const payload = { orderNo: 'P91KS202605040001', productNo: 'KS-CLOUD-SKU-001', buyNum: 1, maxAmount: '0.0000', callbackUrl: 'https://cb.example.com/notify/91/order', timestamp: 1777867200, version: '1.0', } const source = buildOpen91SignSource(payload, config) assert.equal( source, 'rste57w8rsubsnxsb384ur3u9kn5fzhrbuyNum=1&callbackUrl=https://cb.example.com/notify/91/order&maxAmount=0.0000&orderNo=P91KS202605040001&productNo=KS-CLOUD-SKU-001×tamp=1777867200&version=1.0rste57w8rsubsnxsb384ur3u9kn5fzhr', ) const sign = signOpen91Payload(payload, config) assert.equal(sign.length, 32) assert.equal(verifyOpen91Signature({ ...payload, sign }, config), true) }) test('signOpen91Payload does not add missing optional fields or configured userId', () => { const config = { userId: '1001', secret: 'rste57w8rsubsnxsb384ur3u9kn5fzhr', } const payload = { orderNo: '2613300083829561', productNo: '183999074510936', buyNum: 1, maxAmount: '0.01', timestamp: 1778670308, version: '1.0', } assert.equal( buildOpen91SignSource(payload, config), 'rste57w8rsubsnxsb384ur3u9kn5fzhrbuyNum=1&maxAmount=0.01&orderNo=2613300083829561&productNo=183999074510936×tamp=1778670308&version=1.0rste57w8rsubsnxsb384ur3u9kn5fzhr', ) }) test('encryptOpen91Cards matches documented AES ECB base64 sample', () => { const cards = [ { cardNo: '10001', cardPwd: '123456', expireTime: '2023-06-19 17:16:01', }, ] assert.equal( encryptOpen91Cards(cards, '0a091b3aa4324435aab703142518a8f7'), '34APdvSJhWfr5wnzE4YzxAsI0gfI6pI/Njrj1UQMHJrZ8Dq9EWsDnln0pp08gn4KES4iQu9/f0Y8UMN4dGdSK67oi0Bc12/V8hrNxqoC3Lk=', ) }) test('resolveOpen91QueryState returns success only when every task is ready', () => { assert.deepEqual( resolveOpen91QueryState({ tasks: [ { id: 1, task_status: 'pending_binding_prepare' }, { id: 2, task_status: 'waiting_binding' }, ], readyTaskIds: [1, 2], }), { orderStatus: 20, failCode: 0, failReason: '', }, ) assert.deepEqual( resolveOpen91QueryState({ tasks: [ { id: 1, task_status: 'pending_binding_prepare' }, { id: 2, task_status: 'waiting_binding' }, ], readyTaskIds: [1], }), { orderStatus: 10, failCode: 0, failReason: '', }, ) assert.deepEqual( resolveOpen91QueryState({ tasks: [{ id: 1, task_status: 'manual_review', last_error: '商品未配置' }], readyTaskIds: [], }), { orderStatus: 30, failCode: 1204, failReason: '商品未配置', }, ) }) test('buildOpen91CardItem mirrors claim link into jumpLink and leaves password empty', () => { assert.deepEqual( buildOpen91CardItem({ claimUrl: 'https://example.com/#/claim/abc123xyz', expireTime: '2026-05-05 12:00:00', }), { cardNo: 'https://example.com/#/claim/abc123xyz', cardPwd: '', expireTime: '2026-05-05 12:00:00', jumpLink: 'https://example.com/#/claim/abc123xyz', }, ) }) test('formatOpen91ExpireTime keeps 91-compatible values and normalizes dates to Beijing time', () => { assert.equal(formatOpen91ExpireTime('2026-05-05 12:00:00'), '2026-05-05 12:00:00') assert.equal(formatOpen91ExpireTime('1778674551'), '1778674551') assert.equal(formatOpen91ExpireTime(new Date('2026-05-14T12:15:51.842Z')), '2026-05-14 20:15:51') })