WAPC2F 实现企微审批样件 dry-run
这个提交包含在:
@@ -1,6 +1,8 @@
|
||||
const { getWecomAppAccessToken, sanitizeWecomResponse } = require("./wecomAccessToken");
|
||||
|
||||
const WECOM_API_BASE = "https://qyapi.weixin.qq.com";
|
||||
const APPROVAL_CREATE_TEMPLATE_ENDPOINT = "/cgi-bin/oa/approval/create_template";
|
||||
const APPROVAL_APPLY_EVENT_ENDPOINT = "/cgi-bin/oa/applyevent";
|
||||
|
||||
const APPROVAL_POC_TARGETS = Object.freeze([
|
||||
{ key: "leave", label: "请假" },
|
||||
@@ -107,6 +109,12 @@ function summarizeApprovalPayload(payload) {
|
||||
function sanitizeApprovalApiResponse(payload) {
|
||||
if (!payload || typeof payload !== "object") return null;
|
||||
const result = sanitizeWecomResponse(payload) ?? {};
|
||||
if (payload.template_id || payload.templateId) {
|
||||
result.templateIdPrefix = maskApprovalIdentifier(payload.template_id ?? payload.templateId);
|
||||
}
|
||||
if (payload.sp_no || payload.spNo) {
|
||||
result.spNoPrefix = maskApprovalIdentifier(payload.sp_no ?? payload.spNo);
|
||||
}
|
||||
if (payload.template_content) {
|
||||
const summary = summarizeTemplatePayload(payload);
|
||||
result.fieldCount = summary.fieldCount;
|
||||
@@ -333,10 +341,142 @@ async function fetchWecomApprovalDetail({
|
||||
}
|
||||
}
|
||||
|
||||
function extractTemplateId(payload) {
|
||||
return toSafeString(payload?.template_id ?? payload?.templateId, 160);
|
||||
}
|
||||
|
||||
function extractSpNo(payload) {
|
||||
return toSafeString(payload?.sp_no ?? payload?.spNo, 160);
|
||||
}
|
||||
|
||||
async function fetchWecomApprovalTemplateCreate({
|
||||
config,
|
||||
payload,
|
||||
fetchImpl = fetch,
|
||||
timeoutMs = config?.wecomRequestTimeoutMs ?? 10000,
|
||||
}) {
|
||||
try {
|
||||
const token = await getApprovalAccessToken({ config, fetchImpl, timeoutMs });
|
||||
const result = await fetchWecomApprovalJson(APPROVAL_CREATE_TEMPLATE_ENDPOINT, token.accessToken, payload, {
|
||||
fetchImpl,
|
||||
timeoutMs,
|
||||
});
|
||||
|
||||
if (!result.ok) {
|
||||
const error = classifyWecomApprovalResult(result, "wecom_approval_create_template_failed");
|
||||
return {
|
||||
ok: false,
|
||||
skipped: false,
|
||||
retryable: false,
|
||||
code: error.code,
|
||||
message: error.message,
|
||||
tokenSource: token.tokenSource,
|
||||
endpoint: `POST ${APPROVAL_CREATE_TEMPLATE_ENDPOINT}`,
|
||||
response: error.response,
|
||||
templateId: null,
|
||||
summary: null,
|
||||
};
|
||||
}
|
||||
|
||||
const templateId = extractTemplateId(result.payload);
|
||||
return {
|
||||
ok: true,
|
||||
skipped: false,
|
||||
retryable: false,
|
||||
code: "wecom_approval_template_created",
|
||||
message: null,
|
||||
tokenSource: token.tokenSource,
|
||||
endpoint: `POST ${APPROVAL_CREATE_TEMPLATE_ENDPOINT}`,
|
||||
response: sanitizeApprovalApiResponse(result.payload),
|
||||
templateId,
|
||||
summary: {
|
||||
templateIdPrefix: maskApprovalIdentifier(templateId),
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
ok: false,
|
||||
skipped: false,
|
||||
retryable: Boolean(error?.details?.retryable),
|
||||
code: error?.code || "wecom_approval_create_template_failed",
|
||||
message: sanitizeErrorMessage(error?.message || error),
|
||||
tokenSource: "WECOM_AGENT_SECRET",
|
||||
endpoint: `POST ${APPROVAL_CREATE_TEMPLATE_ENDPOINT}`,
|
||||
response: error?.details?.response || null,
|
||||
templateId: null,
|
||||
summary: null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchWecomApprovalApplyEvent({
|
||||
config,
|
||||
payload,
|
||||
fetchImpl = fetch,
|
||||
timeoutMs = config?.wecomRequestTimeoutMs ?? 10000,
|
||||
}) {
|
||||
try {
|
||||
const token = await getApprovalAccessToken({ config, fetchImpl, timeoutMs });
|
||||
const result = await fetchWecomApprovalJson(APPROVAL_APPLY_EVENT_ENDPOINT, token.accessToken, payload, {
|
||||
fetchImpl,
|
||||
timeoutMs,
|
||||
});
|
||||
|
||||
if (!result.ok) {
|
||||
const error = classifyWecomApprovalResult(result, "wecom_approval_apply_event_failed");
|
||||
return {
|
||||
ok: false,
|
||||
skipped: false,
|
||||
retryable: false,
|
||||
code: error.code,
|
||||
message: error.message,
|
||||
tokenSource: token.tokenSource,
|
||||
endpoint: `POST ${APPROVAL_APPLY_EVENT_ENDPOINT}`,
|
||||
response: error.response,
|
||||
spNo: null,
|
||||
summary: null,
|
||||
};
|
||||
}
|
||||
|
||||
const spNo = extractSpNo(result.payload);
|
||||
return {
|
||||
ok: true,
|
||||
skipped: false,
|
||||
retryable: false,
|
||||
code: "wecom_approval_apply_event_submitted",
|
||||
message: null,
|
||||
tokenSource: token.tokenSource,
|
||||
endpoint: `POST ${APPROVAL_APPLY_EVENT_ENDPOINT}`,
|
||||
response: sanitizeApprovalApiResponse(result.payload),
|
||||
spNo,
|
||||
summary: {
|
||||
spNoPrefix: maskApprovalIdentifier(spNo),
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
ok: false,
|
||||
skipped: false,
|
||||
retryable: Boolean(error?.details?.retryable),
|
||||
code: error?.code || "wecom_approval_apply_event_failed",
|
||||
message: sanitizeErrorMessage(error?.message || error),
|
||||
tokenSource: "WECOM_AGENT_SECRET",
|
||||
endpoint: `POST ${APPROVAL_APPLY_EVENT_ENDPOINT}`,
|
||||
response: error?.details?.response || null,
|
||||
spNo: null,
|
||||
summary: null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
APPROVAL_POC_TARGETS,
|
||||
APPROVAL_APPLY_EVENT_ENDPOINT,
|
||||
APPROVAL_CREATE_TEMPLATE_ENDPOINT,
|
||||
WecomApprovalPocError,
|
||||
fetchWecomApprovalApplyEvent,
|
||||
fetchWecomApprovalDetail,
|
||||
fetchWecomApprovalTemplateCreate,
|
||||
fetchWecomApprovalTemplateDetail,
|
||||
maskApprovalIdentifier,
|
||||
sanitizeApprovalApiResponse,
|
||||
|
||||
在新工单中引用
屏蔽一个用户