我一直在尝试将 docusign 与焦点视图集成到我的 React 应用程序中。我正在使用用于nodejs的docusign SDK,并且express服务器发出所有API请求并通过docusign获取数据,因此我能够使用postman获取URL并访问链接直接打开表单,但是当在react应用程序中嵌入新的URL时,文档签名加载图标在焦点视图中无限循环。
控制台日志显示内容安全策略错误。 docusign React 示例应用程序没有太多运气。
下面是取自 docusign How-to 指南并针对 React 进行调整的代码:LINK
import React, { useEffect } from 'react';
import PropTypes from 'prop-types';
function DocumentSignUI({ integrationKey, docUrl }) {
useEffect(() => {
const loadDocuSign = async () => {
try {
const docusign = await window.DocuSign.loadDocuSign(integrationKey);
const url = `${docUrl}&output=embed`;
const signing = docusign.signing({
url,
displayFormat: 'focused',
});
signing.mount('#agreement');
} catch (ex) {
console.error(ex);
// Handle error
}
};
console.log('DOCUSIGN RENDER');
loadDocuSign();
}, []);
return (
<div className="docusign-agreement" id="agreement" />
);
}
DocumentSignUI.propTypes = {
integrationKey: PropTypes.string.isRequired,
docUrl: PropTypes.string.isRequired,
};
export default DocumentSignUI;
控制台日志中遇到的错误(Chromium) Chromium 控制台错误
控制台日志中遇到的错误(Firefox) Firefox 控制台错误
尝试在服务器上禁用内容安全策略,但不起作用,尝试在index.html中添加元标记,但这也不起作用。
这是API调用的代码
router.get("/sign-document", processFile, async (req, res) => {
try {
var userData = "";
await checkToken(req);
var apiClient = new docusign.ApiClient({
basePath: basePath,
oAuthBasePath: oAuthBasePath + "/oauth/token",
});
apiClient.addDefaultHeader(
"Authorization",
"Basic KEY"
);
userData = await apiClient.getUserInfo(req.session.access_token);
var baseUri = userData.accounts[0].baseUri;
var accountDomain = baseUri.split("/v2");
apiClient.setBasePath(accountDomain[0] + "/restapi");
const envelopeArgs = {
signerEmail: "EMAIL",
signerName: "NAME",
signerClientId: DOCUSIGN_JWT_CLIENT_ID,
docFile: req.file,
status: "created",
};
const envelope = makeEnvelope(envelopeArgs);
const envelopesApi = await getEnvelopes(req);
const userEnvelopeResult = await envelopesApi.createEnvelope(
userData.accounts[0].accountId,
{ envelopeDefinition: envelope }
);
const recepientRequest = {
dsReturnUrl: "https://localhost:5173/success",
signerEmail: "EMAIL",
signerName: "NAME",
signerClientId: DOCUSIGN_JWT_CLIENT_ID,
};
const viewRequest = await makeRecipientViewRequest(recepientRequest);
const viewRequestResult = await envelopesApi.createRecipientView(
userData.accounts[0].accountId,
userEnvelopeResult.envelopeId,
{
recipientViewRequest: viewRequest,
frameAncestors: [
"http://localhost",
"https://apps-d.docusign.com",
],
messageOrigins: ["https://apps-d.docusign.com"],
signerEmail: "[email protected]",
signerName: "KinessaJJJ"
}
);
res.status(200).json({
envelopeId: userEnvelopeResult.envelopeId,
redirectUrl: viewRequestResult.url,
});
} catch (error) {
console.error("Error processing request:", error);
res.status(500).json({
success: false,
message: "An error occurred while processing the request",
});
}
});
功能如下
const checkToken = async (req) => {
try {
var apiClient = new docusign.ApiClient({
basePath: basePath,
oAuthBasePath: oAuthBasePath + "/oauth/token",
});
apiClient.addDefaultHeader(
"Authorization",
"Basic OTAyY2IxNmYtYjBmZi00MzY2LWIyYzQtZDBmNWM3MTk1NTc0OjhlMzJjNzI0LTI1NjMtNDM0MC1iMTk5LWQxYTEwMTBhODM5YQ=="
);
var oauthLoginUrl = await apiClient.getJWTUri(
DOCUSIGN_JWT_CLIENT_ID,
"http://localhost:5173/",
oAuthBasePath
);
var scopes = [oAuth.Scope.IMPERSONATION, oAuth.Scope.SIGNATURE];
if (req.session.access_token && Date.now() < req.session.expires_at) {
console.log("re-using access token ", req.session.access_token);
} else {
console.log("creating new access token");
jWTResponse = await apiClient.requestJWTUserToken(
DOCUSIGN_JWT_CLIENT_ID,
DOCUSIGN_IMPERSONATED_USER_GUID,
scopes,
DOCUSIGN_RSA_KEY,
36000
);
console.log(jWTResponse.body.access_token);
req.session.access_token = jWTResponse.body.access_token;
req.session.expires_at =
Date.now() + (jWTResponse.body.expires_in - 60) * 1000;
}
} catch (error) {
console.error("Error while checking token:", error);
}
};
const getEnvelopes = async (req) => {
let dsApiClient = new docusign.ApiClient();
dsApiClient.setBasePath(basePath);
dsApiClient.addDefaultHeader(
"Authorization",
"Bearer " + req.session.access_token
);
return new docusign.EnvelopesApi(dsApiClient);
};
const makeEnvelope = (args) => {
let docPdfBytes;
// const filePath = path.resolve(__dirname, args.docFile);
// docPdfBytes = fs.readFileSync(filePath);
console.log(args.docFile);
let env = new docusign.EnvelopeDefinition();
env.emailSubject = "Please sign this document";
let doc1 = new docusign.Document();
let doc1b64 = Buffer.from(args.docFile.buffer).toString("base64");
doc1.documentBase64 = doc1b64;
doc1.name = "Lorem Ipsum";
doc1.fileExtension = "pdf";
doc1.documentId = "3";
env.documents = [doc1];
let signer1 = docusign.Signer.constructFromObject({
email: args.signerEmail,
name: args.signerName,
clientUserId: args.signerClientId,
recipientId: 1,
});
let signHere1 = docusign.SignHere.constructFromObject({
anchorString: "/sn1/",
anchorYOffset: "10",
anchorUnits: "pixels",
anchorXOffset: "20",
});
let signer1Tabs = docusign.Tabs.constructFromObject({
signHereTabs: [signHere1],
});
signer1.tabs = signer1Tabs;
let recipients = docusign.Recipients.constructFromObject({
signers: [signer1],
});
env.recipients = recipients;
env.status = "sent";
return env;
};
const makeRecipientViewRequest = (args) => {
let viewRequest = new docusign.RecipientViewRequest();
viewRequest.returnUrl = args.dsReturnUrl;
viewRequest.authenticationMethod = "none";
viewRequest.email = args.signerEmail;
viewRequest.userName = args.signerName;
viewRequest.clientUserId = args.signerClientId;
viewRequest.frameAncestors = [
"http://localhost:4000/api",
"https://apps-d.docusign.com",
];
viewRequest.messageOrigins = ["https://apps-d.docusign.com"];
return viewRequest;
};
问题是(已在评论中确认)
frameAncestors(一个数组,表示将在其中呈现聚焦视图的框架的原始域。它必须包含您网站的 URL 以及 https://apps-d.docusign.comhttps://apps-d。 docusign.com,在开发环境中在新窗口中打开,或 https://apps.docusign.comhttps://apps.docusign.com,在生产环境中在新窗口中打开 除非您的站点必须具有有效的 SSL 证书。您正在使用 http://localhost 域。)
未正确设置。
这是在服务器代码中完成的(或者 REST API 代码仍然可以来自使用 CORS 的客户端),这就是这里的问题。虽然您仍然会得到一个可以使用的 URL,但如果您没有正确设置 frameAncestors,它将不会加载。
这是一个片段:
viewRequest.frameAncestors = ['http://localhost:3000', 'https://apps-d.docusign.com'];
viewRequest.messageOrigins = ['https://apps-d.docusign.com'];