import assert from 'node:assert/strict'; import { buildApp } from '../dist/app.js'; import { signAccessToken } from '../dist/auth/jwt.js'; const secret = 'test-only-recharge-route-secret-32'; const token = signAccessToken({ sub: '21', sid: '5c4d3af8-c63c-4edb-bf95-b84127bb3f6e', tid: '7', aid: '9', rv: 1 }, secret, 900); let createdInput; let listInput; let prepayInput; let notifyInput; const app = await buildApp({ recharge: { jwtSecret: secret, authRepository: { async validateSession() { return { id: '5c4d3af8-c63c-4edb-bf95-b84127bb3f6e', tenantId: '7', platformAppId: '9', expiresAt: new Date(Date.now() + 60000), user: { id: '21', tenantId: '7', userType: 'CUSTOMER', status: 'ACTIVE', roleVersion: 1, nickname: '', avatarUrl: '', phone: '' } }; } }, accessControl: { async getAccessProfile() { return { roles: ['CUSTOMER'], capabilities: ['profile.read'], storeIds: [] }; } }, service: { async listAvailablePlans(input) { listInput = input; return [{ planId: '31', storeId: '11', name: 'charge 100 gift 20', payAmountCents: 10000, giftAmountCents: 2000, scopeType: 'STORE' }]; }, async createRechargeOrder(input) { createdInput = input; return { rechargeOrderId: '901', planId: input.planId, rechargeNo: 'RCHTEST', status: 'PENDING_PAYMENT', payAmountCents: 10000, giftAmountCents: 2000, idempotent: false }; }, async createWechatPrepay(input) { prepayInput = input; return { rechargeOrderId: input.rechargeOrderId, rechargeNo: 'RCHTEST', amountCents: 10000, timeStamp: '1782360000', nonceStr: 'nonce', package: 'prepay_id=wx-recharge-prepay', signType: 'RSA', paySign: 'signed' }; }, async processWechatNotification(headers, rawBody, traceId) { notifyInput = { headers, rawBody, traceId }; return { rechargeOrderId: '901', status: 'CREDITED', idempotent: false }; } } } }); const plans = await app.inject({ method: 'GET', url: '/app-api/recharge/plans?storeId=11', headers: { authorization: `Bearer ${token}` } }); assert.equal(plans.statusCode, 200); assert.deepEqual(listInput, { tenantId: '7', storeId: '11' }); assert.equal(plans.json().data[0].payAmountCents, 10000); const created = await app.inject({ method: 'POST', url: '/app-api/recharge/orders', headers: { authorization: `Bearer ${token}`, 'x-trace-id': 'm08a-recharge-order' }, payload: { planId: '31', storeId: '11', clientRequestId: 'miniapp-recharge-001' } }); assert.equal(created.statusCode, 201); assert.equal(createdInput.tenantId, '7'); assert.equal(createdInput.userId, '21'); assert.equal(createdInput.planId, '31'); assert.equal(createdInput.traceId, 'm08a-recharge-order'); const prepay = await app.inject({ method: 'POST', url: '/app-api/recharge/orders/901/wechat-prepay', headers: { authorization: `Bearer ${token}` } }); assert.equal(prepay.statusCode, 200); assert.equal(prepayInput.tenantId, '7'); assert.equal(prepayInput.platformAppId, '9'); assert.equal(prepayInput.userId, '21'); assert.equal(prepay.json().data.package, 'prepay_id=wx-recharge-prepay'); const notify = await app.inject({ method: 'POST', url: '/app-api/recharge/wechat/notify', headers: { 'content-type': 'application/json', 'wechatpay-timestamp': '1782360001', 'wechatpay-nonce': 'notify-nonce', 'wechatpay-serial': 'PLATFORM-SERIAL', 'wechatpay-signature': 'signature' }, payload: '{"resource":"encrypted"}' }); assert.equal(notify.statusCode, 200); assert.equal(notifyInput.headers.serial, 'PLATFORM-SERIAL'); assert.equal(notifyInput.rawBody, '{"resource":"encrypted"}'); const invalid = await app.inject({ method: 'POST', url: '/app-api/recharge/orders', headers: { authorization: `Bearer ${token}` }, payload: { planId: 'bad' } }); assert.equal(invalid.statusCode, 400); await app.close(); console.log('PASS: M08-A recharge routes expose available plans and customer order creation.');