| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- /**
- * 新用户 E2E 扣费验证脚本
- *
- * 前置:用一个**没用过**的手机号在 https://app.fmode.cn/dev/apig-pay/ 登录+支付
- * 把登录后的 sessionToken 填到下面 NEW_TOKEN
- *
- * 运行:
- * node scripts/tools/verify-newuser-e2e.js <sessionToken>
- *
- * 脚本动作:
- * 1. GET /parse/users/me?include=company → 验证新 user 有没有 company
- * 2. 列出该 user 名下所有 APIGAuth(应当只有 user 指针,无 company)
- * 3. 调用 /api/voc-ecom/forward → 预期 200(符合陈经理说的正常逻辑)
- * 4. 再次查 APIGAuth → 验证 count-1 / used+1
- */
- const TOKEN = process.argv[2];
- if (!TOKEN) {
- console.error('用法: node verify-newuser-e2e.js <sessionToken>');
- process.exit(1);
- }
- const API = 'https://server.fmode.cn';
- const H = { 'X-Parse-Application-Id': 'ncloudmaster', 'X-Parse-Session-Token': TOKEN };
- function line() { console.log('━'.repeat(60)); }
- (async () => {
- line();
- console.log(' STEP 1. 查看新 user 信息');
- line();
- const me = await (await fetch(`${API}/parse/users/me?include=company`, { headers: H })).json();
- if (!me.objectId) {
- console.error('❌ Token 无效:', me);
- process.exit(1);
- }
- console.log(` userId: ${me.objectId}`);
- console.log(` username: ${me.username}`);
- console.log(` mobile: ${me.mobile || '(无)'}`);
- console.log(` company: ${me.company ? me.company.objectId : '(无) ✅ 正是我们要的新用户'}`);
- const userId = me.objectId;
- const companyId = me.company?.objectId;
- line();
- console.log(' STEP 2. 查该 user 名下所有 APIGAuth');
- line();
- const q = encodeURIComponent(JSON.stringify({
- user: { __type: 'Pointer', className: '_User', objectId: userId }
- }));
- const auths = await (await fetch(
- `${API}/parse/classes/APIGAuth?where=${q}&include=api&limit=20`,
- { headers: H }
- )).json();
- if (!auths.results || auths.results.length === 0) {
- console.log(' (该 user 还没有任何 APIGAuth —— 需要先去 apig-pay 支付一次)');
- } else {
- auths.results.forEach(a => {
- console.log(` ${a.objectId} api=${a.api?.objectId}(${a.api?.title}) count=${a.count} used=${a.used} company=${a.company?.objectId || '(无)'}`);
- });
- }
- const ecomAuth = auths.results?.find(a => a.api?.objectId === '7HwdQZk55B');
- if (!ecomAuth) {
- console.log('\n⚠️ 未找到电商 APIG(7HwdQZk55B) 的 APIGAuth,请先在 apig-pay 充值电商服务再跑此脚本');
- process.exit(0);
- }
- console.log(`\n → 使用 APIGAuth ${ecomAuth.objectId}, 余额 ${ecomAuth.count}`);
- line();
- console.log(' STEP 3. 调用 /api/voc-ecom/forward');
- line();
- const t0 = Date.now();
- const callResp = await fetch(`${API}/api/voc-ecom/forward`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- 'Authorization': 'Bearer ' + TOKEN
- },
- body: JSON.stringify({
- path: '/api/KeywordQuery',
- method: 'POST',
- query: { domain: 1 },
- body: { Keyword: 'natural reed diffuser' }
- })
- });
- const cost = Date.now() - t0;
- const result = await callResp.text();
- console.log(` HTTP ${callResp.status} (${cost}ms)`);
- console.log(` Body: ${result.substring(0, 400)}`);
- if (callResp.status !== 200) {
- console.log('\n❌ 接口没打通。分析:');
- if (callResp.status === 403) {
- if (companyId) {
- console.log(' - user 有 company → 后端走 company 分支');
- console.log(` - company ${companyId} 下应该查不到 APIGAuth → 403 符合后端正常逻辑`);
- console.log(` - 解决:apig-pay 应该按 company 维度写 APIGAuth(带 company 指针)`);
- } else {
- console.log(' - user 无 company → 后端应走 user 分支');
- console.log(' - 但仍 403 表示 user 维度 APIGAuth 也查不到,或者后端还有其他校验');
- }
- }
- process.exit(1);
- }
- line();
- console.log(' STEP 4. 再查余额,验证扣费');
- line();
- await new Promise(r => setTimeout(r, 1500));
- const after = await (await fetch(
- `${API}/parse/classes/APIGAuth/${ecomAuth.objectId}?keys=count,used`,
- { headers: H }
- )).json();
- const dCount = after.count - ecomAuth.count;
- const dUsed = after.used - ecomAuth.used;
- console.log(` count: ${ecomAuth.count} → ${after.count} (Δ=${dCount})`);
- console.log(` used: ${ecomAuth.used} → ${after.used} (Δ=${dUsed})`);
- if (dCount === -1 && dUsed === 1) {
- console.log('\n🎉 扣费链路打通!新用户流程端到端验证通过');
- } else {
- console.log('\n⚠️ 接口 200 但余额未按预期变动,检查后端扣费逻辑');
- }
- })().catch(e => console.error('[FATAL]', e));
|