CI / Client installer (macos-latest) (push) Canceled after 0s
CI / Client installer (ubuntu-latest) (push) Canceled after 0s
CI / Client installer (windows-latest) (push) Canceled after 0s
CI / test (22) (push) Canceled after 0s
CI / test (24) (push) Canceled after 0s
CI / release-smoke (push) Canceled after 0s
75 lines
2.9 KiB
JavaScript
75 lines
2.9 KiB
JavaScript
#!/usr/bin/env node
|
|
import { readFileSync } from "node:fs";
|
|
import { XftOpenApiClient } from "../dist/src/xft-open-api.js";
|
|
|
|
const [appId, secretFile, enterpriseId, dingTalkUserId, historyBillId] = process.argv.slice(2);
|
|
if (!appId || !secretFile || !enterpriseId || !dingTalkUserId) {
|
|
console.error("usage: node scripts/xft-open-api-readonly.mjs <appId> <secretFile> <enterpriseId> <dingTalkUserId>");
|
|
process.exit(2);
|
|
}
|
|
|
|
const config = {
|
|
clientId: "readonly-smoke-test",
|
|
clientSecret: "readonly-smoke-test",
|
|
apiBaseUrl: "https://api.dingtalk.com",
|
|
oapiBaseUrl: "https://oapi.dingtalk.com",
|
|
publicBaseUrl: "https://localhost",
|
|
port: 3000,
|
|
requestTimeoutMs: 15_000,
|
|
officialLookbackDays: 120,
|
|
officialScanConcurrency: 2,
|
|
officialClientOnlyProcessCodes: [],
|
|
batchLimit: 20,
|
|
xftOpenApi: {
|
|
appId,
|
|
authoritySecret: (() => {
|
|
const lines = readFileSync(secretFile, "utf8").split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
|
|
return lines.length >= 2 ? lines[1] : lines[0];
|
|
})(),
|
|
enterpriseId,
|
|
apiBaseUrl: "https://api.cmbchina.com",
|
|
encrypted: true,
|
|
dingTalkAppCode: "DDingTalk",
|
|
},
|
|
};
|
|
|
|
const client = new XftOpenApiClient(config);
|
|
if (historyBillId && historyBillId !== "--auth-only") {
|
|
try {
|
|
const history = await client.request(
|
|
`/itrip/xft-api/v1/bills/taskHistory/${encodeURIComponent(historyBillId)}`,
|
|
undefined,
|
|
"GET",
|
|
);
|
|
console.log(JSON.stringify({ historyProbe: "ok", responseType: Array.isArray(history) ? "array" : typeof history }));
|
|
} catch (error) {
|
|
console.log(JSON.stringify({ historyProbe: "failed", message: error instanceof Error ? error.message : String(error) }));
|
|
}
|
|
}
|
|
const user = { userId: dingTalkUserId };
|
|
const auth = await client.authStatus(user);
|
|
if (historyBillId === "--auth-only") {
|
|
console.log(JSON.stringify({ authenticated: auth.authenticated, identity: auth.identity }, null, 2));
|
|
process.exit(0);
|
|
}
|
|
const todos = await client.listMyTodos(user, 200);
|
|
const detailCandidates = ["COMMON_REIM", "TRAVEL_REIM"]
|
|
.map((eventType) => todos.items.find((item) => item.eventType === eventType))
|
|
.filter(Boolean);
|
|
const details = await Promise.all(detailCandidates.map((item) => client.getTodoDetail(user, item.billId)));
|
|
console.log(JSON.stringify({
|
|
authenticated: auth.authenticated,
|
|
identity: auth.identity,
|
|
todoCount: todos.totalCount,
|
|
sample: todos.items.slice(0, 3).map(({ billId, title, applicantName, amount, eventType }) => ({ billId, title, applicantName, amount, eventType })),
|
|
detailProbes: details.map((detail) => ({
|
|
billId: detail.todo.billId,
|
|
eventType: detail.todo.eventType,
|
|
formType: Array.isArray(detail.form) ? "array" : typeof detail.form,
|
|
formTopLevelKeys: detail.form && typeof detail.form === "object" && !Array.isArray(detail.form)
|
|
? Object.keys(detail.form).slice(0, 30)
|
|
: [],
|
|
})),
|
|
diagnostics: todos.diagnostics,
|
|
}, null, 2));
|