133 lines
3.8 KiB
JavaScript
133 lines
3.8 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import { generateKeyPairSync } from 'node:crypto';
|
|
import { buildApp } from '../dist/app.js';
|
|
import { loadConfig } from '../dist/config.js';
|
|
import { signAccessToken } from '../dist/auth/jwt.js';
|
|
import { WechatPayClient } from '../dist/payments/wechat-pay-client.js';
|
|
|
|
assert.equal(loadConfig({
|
|
NODE_ENV: 'production',
|
|
QIPAI_JWT_SECRET: 'production-profit-share-secret-long-enough',
|
|
QIPAI_PROFIT_SHARE_MOCK_ENABLED: 'true'
|
|
}).payment.profitShareMockEnabled, false);
|
|
assert.equal(loadConfig({
|
|
NODE_ENV: 'test',
|
|
QIPAI_PROFIT_SHARE_MOCK_ENABLED: 'true'
|
|
}).payment.profitShareMockEnabled, true);
|
|
|
|
const keys = generateKeyPairSync('rsa', {
|
|
modulusLength: 2048,
|
|
publicKeyEncoding: { type: 'spki', format: 'pem' },
|
|
privateKeyEncoding: { type: 'pkcs8', format: 'pem' }
|
|
});
|
|
let apiRequest;
|
|
const client = new WechatPayClient({
|
|
async request(input) {
|
|
apiRequest = input;
|
|
return {
|
|
status: 200,
|
|
headers: {},
|
|
body: JSON.stringify({ order_id: 'wx-share-order', state: 'FINISHED' })
|
|
};
|
|
}
|
|
});
|
|
const shareResult = await client.createProfitSharing({
|
|
appId: 'wx-test',
|
|
merchantId: '1900000109',
|
|
serialNo: 'serial-test',
|
|
privateKeyPem: keys.privateKey,
|
|
apiV3Key: '0123456789abcdef0123456789abcdef',
|
|
platformCertificates: {},
|
|
profitShareReceivers: {}
|
|
}, {
|
|
transactionId: 'wx-transaction-001',
|
|
outOrderNo: 'share-request-001',
|
|
receivers: [{
|
|
type: 'MERCHANT_ID',
|
|
account: 'receiver-account-private',
|
|
amountCents: 1200,
|
|
description: 'sanitized share'
|
|
}],
|
|
finish: true
|
|
});
|
|
assert.equal(shareResult.state, 'FINISHED');
|
|
assert.match(apiRequest.url, /\/v3\/profitsharing\/orders$/);
|
|
assert.match(apiRequest.body, /"amount":1200/);
|
|
assert.equal(apiRequest.headers.Authorization.includes(keys.privateKey), false);
|
|
|
|
const secret = 'profit-sharing-route-secret-32-characters';
|
|
const token = signAccessToken({
|
|
sub: '21', sid: '5c4d3af8-c63c-4edb-bf95-b84127bb3f6e',
|
|
tid: '7', aid: '9', rv: 1
|
|
}, secret, 900);
|
|
let executeInput;
|
|
const app = await buildApp({
|
|
payment: {
|
|
jwtSecret: secret,
|
|
testAdapterEnabled: false,
|
|
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: 'ADMIN', status: 'ACTIVE',
|
|
roleVersion: 1, nickname: '', avatarUrl: '', phone: ''
|
|
}
|
|
};
|
|
}
|
|
},
|
|
accessControl: {
|
|
async getAccessProfile() {
|
|
return {
|
|
roles: ['TENANT_ADMIN'],
|
|
capabilities: ['tenant.manage'],
|
|
storeIds: []
|
|
};
|
|
}
|
|
},
|
|
repository: {
|
|
async createPayment() { return {}; },
|
|
async processTestCallback() { return {}; }
|
|
},
|
|
profitSharing: {
|
|
async saveCollectionAccount() {
|
|
return { accountId: '41', created: true };
|
|
},
|
|
async saveReceiver() {
|
|
return { receiverId: '42', created: true };
|
|
},
|
|
async savePolicy() {
|
|
return { saved: true };
|
|
},
|
|
async execute(input) {
|
|
executeInput = input;
|
|
return {
|
|
shares: [{ shareId: '43', amountCents: 1200, status: 'SUCCEEDED' }],
|
|
idempotent: false
|
|
};
|
|
},
|
|
async list() {
|
|
return { accounts: [], shares: [] };
|
|
}
|
|
}
|
|
}
|
|
});
|
|
const executed = await app.inject({
|
|
method: 'POST',
|
|
url: '/admin-api/pay/profit-shares',
|
|
headers: { authorization: `Bearer ${token}` },
|
|
payload: {
|
|
paymentId: '31',
|
|
clientRequestId: 'share-request-001',
|
|
mode: 'MOCK'
|
|
}
|
|
});
|
|
assert.equal(executed.statusCode, 200);
|
|
assert.equal(executeInput.tenantId, '7');
|
|
assert.equal(executeInput.access.capabilities[0], 'tenant.manage');
|
|
|
|
await app.close();
|
|
console.log('PASS: M05-D Wechat profit-sharing request, production mock gate and admin routes.');
|